use core::ops::{Deref, DerefMut};
use cubecl_ir::{
Scope, VectorSize,
interfaces::MaybeVectorizedType,
pliron::{
r#type::{Typed, TypedHandle},
value::Value,
},
read_value,
types::{ArrayType, PointerType, aggregate::SliceType},
};
use crate::frontend::{CubePrimitive, NativeExpand};
use crate::prelude::*;
use crate::{self as cubecl};
use crate::{frontend::CubeType, unexpanded};
use cubecl_macros::{cube, intrinsic};
#[derive(Clone, Copy)]
pub struct Array<E> {
_buffer: [E; 1],
}
type ArrayExpand<E> = NativeExpand<Array<E>>;
impl<E> AsMutExpand for ArrayExpand<E> {
fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
self
}
}
mod new {
use cubecl_ir::{attributes::ZeroAttr, types::ArrayType};
use cubecl_macros::intrinsic;
use super::*;
use crate::frontend::container::slice;
#[cube]
impl<T: CubePrimitive + Clone> Array<T> {
pub fn new(#[comptime] length: usize) -> Self {
intrinsic!(|scope| {
let elem = T::__expand_as_type(scope);
let ty = ArrayType::get(scope.ctx(), elem, length);
let null = ZeroAttr::new(ty);
let buffer = scope.create_local_mut(ty, Some(null.into()));
let slice = slice::from_raw_parts::<T>(
scope,
buffer,
0usize.into_expand(scope),
length.into_expand(scope),
);
slice.expand.into()
})
}
}
}
mod vector {
use cubecl_ir::{interfaces::TypedExt, read_value};
use super::*;
impl<P: CubePrimitive> Array<P> {
pub fn vector_size(&self) -> VectorSize {
P::vector_size()
}
pub fn __expand_vector_size(
expand: <Self as CubeType>::ExpandType,
scope: &Scope,
) -> VectorSize {
expand.__expand_vector_size_method(scope)
}
}
#[cube]
impl<P: CubePrimitive> Array<P> {
pub fn into_vector<N: Size>(self) -> Vector<P::Scalar, N> {
intrinsic!(|scope| {
let arr = read_value(scope, self.__extract_list(scope));
let vec_ty = Vector::<P::Scalar, N>::__expand_as_type(scope);
reinterpret_value(scope, arr, vec_ty).into()
})
}
pub fn from_vector<S: Scalar, N: Size>(vector: Vector<S, N>) -> Array<P> {
intrinsic!(|scope| {
let vec = vector.read_value(scope);
let vec_p = P::__expand_vector_size(scope);
let len = vec.vector_size(scope.ctx()) / vec_p;
let arr_ty =
ArrayType::get(scope.ctx(), P::__expand_as_type(scope), len).to_handle();
reinterpret_value(scope, vec, arr_ty).into()
})
}
}
}
#[cube]
impl<E: CubePrimitive> Array<E> {
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> comptime_type!(usize) {
intrinsic!(|scope| {
let ty = inner_array_ty(scope, self.value(scope));
ty.deref(scope.ctx()).length
})
}
}
impl<C: CubePrimitive> Assign for ArrayExpand<C> {
fn __expand_assign_method(&mut self, scope: &Scope, value: Self) {
let value = value.__extract_list(scope);
let arr = self.__extract_list(scope);
assign::expand_element(scope, value.into(), arr.into());
}
}
impl<C: CubePrimitive> RuntimeAssign for ArrayExpand<C> {
fn init_mut(&self, scope: &Scope) -> Self::Expand {
let ty = inner_array_ty(scope, self.value(scope));
let length = ty.deref(scope.ctx()).length;
Array::__expand_new(scope, length)
}
}
impl<C: CubeType> CubeType for Array<C> {
type ExpandType = NativeExpand<Array<C>>;
}
impl<T: CubePrimitive> ReadValue for NativeExpand<Array<T>> {
fn read_value(&self, scope: &Scope) -> Value {
read_value(scope, self.__extract_list(scope))
}
}
impl<C: CubeType> IntoMut for ArrayExpand<C> {
fn into_mut(self, _scope: &Scope) -> Self {
self
}
}
impl<T: CubePrimitive> SizedContainer<usize> for Array<T> {
fn len(&self) -> usize {
unexpanded!()
}
}
impl<T: CubePrimitive> SizedContainerExpand<usize> for ArrayExpand<T> {
fn __expand_len_method(&self, scope: &Scope) -> NativeExpand<usize> {
self.__expand_len_method(scope).into_expand(scope)
}
}
impl<T: CubeType> Iterator for Array<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
unexpanded!()
}
}
impl<T: CubePrimitive> Deref for Array<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
unexpanded!()
}
}
impl<T: CubePrimitive> DerefMut for Array<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unexpanded!()
}
}
impl<T: CubePrimitive> Deref for ArrayExpand<T> {
type Target = SliceExpand<T>;
fn deref(&self) -> &Self::Target {
unsafe { self.as_type_ref_unchecked() }
}
}
impl<T: CubePrimitive> DerefMut for ArrayExpand<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.as_type_mut_unchecked() }
}
}
impl<T: CubePrimitive> List<T> for Array<T> {}
impl<T: CubePrimitive> ListExpand<T> for ArrayExpand<T> {
fn __expand_len_method(&self, scope: &Scope) -> NativeExpand<usize> {
Array::<T>::__expand_len(scope, self).into_expand(scope)
}
}
impl<T: CubePrimitive> Vectorized for Array<T> {}
impl<T: CubePrimitive> VectorizedExpand for ArrayExpand<T> {
fn __expand_vector_size_method(&self, scope: &Scope) -> VectorSize {
let ty = inner_array_ty(scope, self.value(scope));
ty.deref(scope.ctx()).vector_size(scope.ctx())
}
}
pub(crate) fn inner_array_ty(scope: &Scope, value: Value) -> TypedHandle<ArrayType> {
let ctx = scope.ctx();
let ty = value.get_type(ctx).deref(ctx);
let SliceType { base_ty, .. } = *ty.downcast_ref().unwrap();
let base_ty = base_ty.deref(ctx);
let PointerType { inner, .. } = base_ty.downcast_ref().unwrap();
TypedHandle::from_handle(*inner, ctx).unwrap()
}