cubecl_core/frontend/container/array/
base.rs1use core::ops::{Deref, DerefMut};
2
3use cubecl_ir::{
4 Scope, VectorSize,
5 interfaces::MaybeVectorizedType,
6 pliron::{
7 r#type::{Typed, TypedHandle},
8 value::Value,
9 },
10 read_value,
11 types::{ArrayType, PointerType, aggregate::SliceType},
12};
13
14use crate::frontend::{CubePrimitive, NativeExpand};
15use crate::prelude::*;
16use crate::{self as cubecl};
17use crate::{frontend::CubeType, unexpanded};
18use cubecl_macros::{cube, intrinsic};
19
20#[derive(Clone, Copy)]
22pub struct Array<E> {
23 _buffer: [E; 1],
24}
25
26type ArrayExpand<E> = NativeExpand<Array<E>>;
27
28impl<E> AsMutExpand for ArrayExpand<E> {
29 fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
30 self
31 }
32}
33
34mod new {
36 use cubecl_ir::{attributes::ZeroAttr, types::ArrayType};
37 use cubecl_macros::intrinsic;
38
39 use super::*;
40 use crate::frontend::container::slice;
41
42 #[cube]
43 impl<T: CubePrimitive + Clone> Array<T> {
44 pub fn new(#[comptime] length: usize) -> Self {
46 intrinsic!(|scope| {
47 let elem = T::__expand_as_type(scope);
51 let ty = ArrayType::get(scope.ctx(), elem, length);
52 let null = ZeroAttr::new(ty);
53 let buffer = scope.create_local_mut(ty, Some(null.into()));
54 let slice = slice::from_raw_parts::<T>(
55 scope,
56 buffer,
57 0usize.into_expand(scope),
58 length.into_expand(scope),
59 );
60 slice.expand.into()
61 })
62 }
63 }
64}
65
66mod vector {
68 use cubecl_ir::{interfaces::TypedExt, read_value};
69
70 use super::*;
71
72 impl<P: CubePrimitive> Array<P> {
73 pub fn vector_size(&self) -> VectorSize {
81 P::vector_size()
82 }
83
84 pub fn __expand_vector_size(
86 expand: <Self as CubeType>::ExpandType,
87 scope: &Scope,
88 ) -> VectorSize {
89 expand.__expand_vector_size_method(scope)
90 }
91 }
92
93 #[cube]
94 impl<P: CubePrimitive> Array<P> {
95 pub fn into_vector<N: Size>(self) -> Vector<P::Scalar, N> {
96 intrinsic!(|scope| {
97 let arr = read_value(scope, self.__extract_list(scope));
98 let vec_ty = Vector::<P::Scalar, N>::__expand_as_type(scope);
99 reinterpret_value(scope, arr, vec_ty).into()
100 })
101 }
102
103 pub fn from_vector<S: Scalar, N: Size>(vector: Vector<S, N>) -> Array<P> {
104 intrinsic!(|scope| {
105 let vec = vector.read_value(scope);
106 let vec_p = P::__expand_vector_size(scope);
107 let len = vec.vector_size(scope.ctx()) / vec_p;
108 let arr_ty =
109 ArrayType::get(scope.ctx(), P::__expand_as_type(scope), len).to_handle();
110 reinterpret_value(scope, vec, arr_ty).into()
111 })
112 }
113 }
114}
115
116#[cube]
117impl<E: CubePrimitive> Array<E> {
118 #[allow(clippy::len_without_is_empty)]
120 pub fn len(&self) -> comptime_type!(usize) {
121 intrinsic!(|scope| {
122 let ty = inner_array_ty(scope, self.value(scope));
123 ty.deref(scope.ctx()).length
124 })
125 }
126}
127
128impl<C: CubePrimitive> Assign for ArrayExpand<C> {
129 fn __expand_assign_method(&mut self, scope: &Scope, value: Self) {
130 let value = value.__extract_list(scope);
131 let arr = self.__extract_list(scope);
132 assign::expand_element(scope, value.into(), arr.into());
133 }
134}
135
136impl<C: CubePrimitive> RuntimeAssign for ArrayExpand<C> {
137 fn init_mut(&self, scope: &Scope) -> Self::Expand {
138 let ty = inner_array_ty(scope, self.value(scope));
139 let length = ty.deref(scope.ctx()).length;
140 Array::__expand_new(scope, length)
141 }
142}
143
144impl<C: CubeType> CubeType for Array<C> {
145 type ExpandType = NativeExpand<Array<C>>;
146}
147
148impl<T: CubePrimitive> ReadValue for NativeExpand<Array<T>> {
149 fn read_value(&self, scope: &Scope) -> Value {
150 read_value(scope, self.__extract_list(scope))
151 }
152}
153
154impl<C: CubeType> IntoMut for ArrayExpand<C> {
155 fn into_mut(self, _scope: &Scope) -> Self {
156 self
157 }
158}
159
160impl<T: CubePrimitive> SizedContainer<usize> for Array<T> {
161 fn len(&self) -> usize {
162 unexpanded!()
163 }
164}
165
166impl<T: CubePrimitive> SizedContainerExpand<usize> for ArrayExpand<T> {
167 fn __expand_len_method(&self, scope: &Scope) -> NativeExpand<usize> {
168 self.__expand_len_method(scope).into_expand(scope)
169 }
170}
171
172impl<T: CubeType> Iterator for Array<T> {
173 type Item = T;
174
175 fn next(&mut self) -> Option<Self::Item> {
176 unexpanded!()
177 }
178}
179
180impl<T: CubePrimitive> Deref for Array<T> {
181 type Target = [T];
182
183 fn deref(&self) -> &Self::Target {
184 unexpanded!()
185 }
186}
187
188impl<T: CubePrimitive> DerefMut for Array<T> {
189 fn deref_mut(&mut self) -> &mut Self::Target {
190 unexpanded!()
191 }
192}
193
194impl<T: CubePrimitive> Deref for ArrayExpand<T> {
195 type Target = SliceExpand<T>;
196
197 fn deref(&self) -> &Self::Target {
198 unsafe { self.as_type_ref_unchecked() }
199 }
200}
201
202impl<T: CubePrimitive> DerefMut for ArrayExpand<T> {
203 fn deref_mut(&mut self) -> &mut Self::Target {
204 unsafe { self.as_type_mut_unchecked() }
205 }
206}
207
208impl<T: CubePrimitive> List<T> for Array<T> {}
209impl<T: CubePrimitive> ListExpand<T> for ArrayExpand<T> {
210 fn __expand_len_method(&self, scope: &Scope) -> NativeExpand<usize> {
211 Array::<T>::__expand_len(scope, self).into_expand(scope)
212 }
213}
214
215impl<T: CubePrimitive> Vectorized for Array<T> {}
216impl<T: CubePrimitive> VectorizedExpand for ArrayExpand<T> {
217 fn __expand_vector_size_method(&self, scope: &Scope) -> VectorSize {
218 let ty = inner_array_ty(scope, self.value(scope));
219 ty.deref(scope.ctx()).vector_size(scope.ctx())
220 }
221}
222
223pub(crate) fn inner_array_ty(scope: &Scope, value: Value) -> TypedHandle<ArrayType> {
224 let ctx = scope.ctx();
225 let ty = value.get_type(ctx).deref(ctx);
226 let SliceType { base_ty, .. } = *ty.downcast_ref().unwrap();
227 let base_ty = base_ty.deref(ctx);
228 let PointerType { inner, .. } = base_ty.downcast_ref().unwrap();
229 TypedHandle::from_handle(*inner, ctx).unwrap()
230}