use cubecl_core::intrinsic;
use cubecl_core::{
self as cubecl,
ir::{dialect::memory::IndexOp, interfaces::TypedExt},
prelude::*,
};
use pliron::builtin::attributes::UnitAttr;
#[cube]
pub trait UnalignedVector<E: Scalar, N: Size>: CubeType {
fn unaligned_vector_read(&self, index: usize) -> Vector<E, N>;
fn unaligned_vector_write(&mut self, index: usize, value: Vector<E, N>);
}
type ArrayExpand<T> = NativeExpand<Array<T>>;
macro_rules! impl_unaligned_vector {
($type: ty) => {
#[cube]
impl<E: Scalar, N: Size> UnalignedVector<E, N> for $type {
fn unaligned_vector_read(&self, index: usize) -> Vector<E, N> {
unaligned_vector_read::<E, N>(self.as_slice(), index)
}
fn unaligned_vector_write(&mut self, index: usize, value: Vector<E, N>) {
unaligned_vector_write::<E, N>(self.as_mut_slice(), index, value)
}
}
};
}
impl_unaligned_vector!(Array<E>);
impl_unaligned_vector!(Tensor<E>);
impl_unaligned_vector!(Shared<[E]>);
#[cube]
fn unaligned_vector_read<E: Scalar, N: Size>(this: &[E], index: usize) -> Vector<E, N> {
intrinsic!(|scope| {
let list = this.__extract_list(scope);
if list.element_ty(scope.ctx()).vector_size(scope.ctx()) != 1 {
todo!("Unaligned reads are only allowed off scalar arrays for now");
}
let vector_size = N::__expand_value(scope);
let index = index.read_value(scope);
let index_op = IndexOp::new(scope.ctx_mut(), list, index, Some(UnitAttr));
let out = scope.register_with_result(&index_op);
let mut out: NativeExpand<Vector<E, N>> = out.into();
out.__expand_deref_method(scope)
})
}
#[cube]
fn unaligned_vector_write<E: Scalar, N: Size>(this: &mut [E], index: usize, value: Vector<E, N>) {
intrinsic!(|scope| {
let list = this.__extract_list(scope);
if list.element_ty(scope.ctx()).vector_size(scope.ctx()) != 1 {
todo!("Unaligned writes are only allowed off scalar arrays for now");
}
let vector_size = N::__expand_value(scope);
let index = index.read_value(scope);
let index_op = IndexOp::new(scope.ctx_mut(), list, index, Some(UnitAttr));
let out = scope.register_with_result(&index_op);
let mut out: NativeExpand<Vector<E, N>> = out.into();
out.__expand_assign_method(scope, value);
})
}