use alloc::sync::Arc;
use core::{cell::UnsafeCell, marker::PhantomData};
use cubecl::prelude::*;
use cubecl_core::{
self as cubecl,
frontend::select,
ir::{ExpandValue, VectorSize},
unexpanded,
};
use crate::tensor::r#virtual::{VirtualTensor, VirtualTensorExpand};
use crate::tensor::{
ViewOperations, ViewOperationsExpand, ViewOperationsMut, ViewOperationsMutExpand,
layout::Coords1d,
};
use cubecl_core::prelude::barrier::Barrier;
#[derive(Clone, Copy)]
pub struct WriteOnly;
pub trait ErasedIo: Clone + Copy + Send + Sync + 'static {}
pub trait ErasedIoRead: ErasedIo {}
pub trait ErasedIoWrite: ErasedIo {}
impl ErasedIo for ReadOnly {}
impl ErasedIo for ReadWrite {}
impl ErasedIo for WriteOnly {}
impl ErasedIoRead for ReadOnly {}
impl ErasedIoRead for ReadWrite {}
impl ErasedIoWrite for ReadWrite {}
impl ErasedIoWrite for WriteOnly {}
pub struct ErasedTensor<E: Numeric, IO = ReadOnly> {
_e: PhantomData<E>,
_p: PhantomData<IO>,
}
pub struct ErasedTensorExpand<E: Numeric, IO> {
state: Arc<UnsafeCell<dyn ErasedTensorOperationsExpand<E>>>,
_p: PhantomData<IO>,
}
impl<E: Numeric, IO> Clone for ErasedTensor<E, IO> {
fn clone(&self) -> Self {
*self
}
}
impl<E: Numeric, IO> Copy for ErasedTensor<E, IO> {}
impl<E: Numeric, IO> Clone for ErasedTensorExpand<E, IO> {
fn clone(&self) -> Self {
Self {
state: self.state.clone(),
_p: PhantomData,
}
}
}
pub trait ErasedTensorOperationsExpand<E: Numeric> {
fn __expand_vector_size_method(&self, scope: &Scope) -> VectorSize;
fn __expand_lines_method(&self, scope: &Scope) -> NativeExpand<usize>;
fn __expand_read_line_method(
&self,
_scope: &Scope,
_index: NativeExpand<usize>,
) -> ExpandValue {
unimplemented!("ErasedTensor: this backing does not serve reads")
}
fn __expand_write_line_method(
&mut self,
_scope: &Scope,
_index: NativeExpand<usize>,
_value: ExpandValue,
) {
unimplemented!("ErasedTensor: this backing does not serve writes")
}
}
pub trait ReadsLines<E: Numeric>: ErasedTensorOperationsExpand<E> {}
pub trait WritesLines<E: Numeric>: ErasedTensorOperationsExpand<E> {}
pub trait ErasedBacking<E: Numeric, IO>: ErasedTensorOperationsExpand<E> {}
impl<E: Numeric, T: ReadsLines<E>> ErasedBacking<E, ReadOnly> for T {}
impl<E: Numeric, T: WritesLines<E>> ErasedBacking<E, WriteOnly> for T {}
impl<E: Numeric, T: ReadsLines<E> + WritesLines<E>> ErasedBacking<E, ReadWrite> for T {}
impl<E: Numeric, IO> ErasedTensorExpand<E, IO> {
pub fn new<S: ErasedBacking<E, IO> + 'static>(backing: S) -> Self {
Self {
state: Arc::new(UnsafeCell::new(backing)),
_p: PhantomData,
}
}
fn state_read(&self) -> &dyn ErasedTensorOperationsExpand<E> {
unsafe { &*self.state.get() }
}
#[allow(clippy::mut_from_ref)]
fn state_write(&self) -> &mut dyn ErasedTensorOperationsExpand<E> {
unsafe { &mut *self.state.get() }
}
fn check_width<N: Size>(&self, scope: &Scope, op: &str) {
let served = self.state_read().__expand_vector_size_method(scope);
let asked = <N as Size>::__expand_value(scope);
assert_eq!(
served, asked,
"ErasedTensor::{op}: the tensor takes {served}-wide lines and the {op} is {asked}-wide"
);
}
}
#[cube]
impl<E: Numeric, IO: ErasedIoRead> ErasedTensor<E, IO> {
#[allow(unused)]
pub fn read<N: Size>(&self, index: usize) -> Vector<E, N> {
intrinsic!(|scope| {
self.check_width::<N>(scope, "read");
self.state_read()
.__expand_read_line_method(scope, index)
.into()
})
}
}
#[cube]
impl<E: Numeric, IO: ErasedIoWrite> ErasedTensor<E, IO> {
#[allow(unused)]
pub fn write<N: Size>(&mut self, index: usize, value: Vector<E, N>) {
intrinsic!(|scope| {
self.check_width::<N>(scope, "write");
self.state_write()
.__expand_write_line_method(scope, index, value.into())
})
}
}
#[cube]
impl<E: Numeric, IO: ErasedIo> ErasedTensor<E, IO> {
#[allow(unused, clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
intrinsic!(|scope| self.state_read().__expand_lines_method(scope))
}
}
impl<E: Numeric, IO: ErasedIo> Vectorized for ErasedTensor<E, IO> {}
impl<E: Numeric, IO: ErasedIo> VectorizedExpand for ErasedTensorExpand<E, IO> {
fn __expand_vector_size_method(&self, scope: &Scope) -> VectorSize {
self.state_read().__expand_vector_size_method(scope)
}
}
impl<E: Numeric, N: Size, IO: Clone> ErasedTensorOperationsExpand<E>
for VirtualTensorExpand<E, N, IO>
{
fn __expand_vector_size_method(&self, scope: &Scope) -> VectorSize {
VectorizedExpand::__expand_vector_size_method(self, scope)
}
fn __expand_lines_method(&self, scope: &Scope) -> NativeExpand<usize> {
self.clone().__expand_len_method(scope)
}
fn __expand_read_line_method(&self, scope: &Scope, index: NativeExpand<usize>) -> ExpandValue {
Self::__expand_read_method(self, scope, index).expand
}
fn __expand_write_line_method(
&mut self,
scope: &Scope,
index: NativeExpand<usize>,
value: ExpandValue,
) {
self.state_write()
.__expand_write_method(scope, index, value.into())
}
}
impl<E: Numeric, N: Size, IO: Clone> ReadsLines<E> for VirtualTensorExpand<E, N, IO> {}
impl<E: Numeric, N: Size> WritesLines<E> for VirtualTensorExpand<E, N, ReadWrite> {}
impl<E: Numeric, N: Size> ErasedTensorOperationsExpand<E> for TensorExpand<Vector<E, N>> {
fn __expand_vector_size_method(&self, scope: &Scope) -> VectorSize {
VectorizedExpand::__expand_vector_size_method(self, scope)
}
fn __expand_lines_method(&self, scope: &Scope) -> NativeExpand<usize> {
self.__expand_len_method(scope)
}
fn __expand_read_line_method(&self, scope: &Scope, index: NativeExpand<usize>) -> ExpandValue {
unsafe {
self.__expand_get_unchecked_method(scope, index)
.__expand_deref_method(scope)
.expand
}
}
fn __expand_write_line_method(
&mut self,
scope: &Scope,
index: NativeExpand<usize>,
value: ExpandValue,
) {
unsafe {
self.__expand_get_unchecked_mut_method(scope, index)
.__expand_assign_method(scope, value.into())
};
}
}
impl<E: Numeric, N: Size> ReadsLines<E> for TensorExpand<Vector<E, N>> {}
impl<E: Numeric, N: Size> WritesLines<E> for TensorExpand<Vector<E, N>> {}
pub struct ErasedView<V, N: Size> {
view: V,
_n: PhantomData<N>,
}
impl<E: Numeric, N: Size, V> ErasedTensorOperationsExpand<E> for ErasedView<V, N>
where
V: ViewOperationsExpand<Vector<E, N>, Coords1d>,
{
fn __expand_vector_size_method(&self, _scope: &Scope) -> VectorSize {
<N as Size>::__expand_value(_scope)
}
fn __expand_lines_method(&self, scope: &Scope) -> NativeExpand<usize> {
self.view.__expand_shape_method(scope)
}
fn __expand_read_line_method(&self, scope: &Scope, index: NativeExpand<usize>) -> ExpandValue {
self.view.__expand_read_method(scope, index).expand
}
}
impl<E: Numeric, N: Size, V> ReadsLines<E> for ErasedView<V, N> where
V: ViewOperationsExpand<Vector<E, N>, Coords1d>
{
}
pub struct ErasedViewMut<V, N: Size> {
view: V,
_n: PhantomData<N>,
}
impl<E: Numeric, N: Size, V> ErasedTensorOperationsExpand<E> for ErasedViewMut<V, N>
where
V: ViewOperationsMutExpand<Vector<E, N>, Coords1d>,
{
fn __expand_vector_size_method(&self, scope: &Scope) -> VectorSize {
<N as Size>::__expand_value(scope)
}
fn __expand_lines_method(&self, scope: &Scope) -> NativeExpand<usize> {
<V as ViewOperationsExpand<Vector<E, N>, Coords1d>>::__expand_shape_method(
&self.view, scope,
)
}
fn __expand_read_line_method(&self, scope: &Scope, index: NativeExpand<usize>) -> ExpandValue {
<V as ViewOperationsExpand<Vector<E, N>, Coords1d>>::__expand_read_method(
&self.view, scope, index,
)
.expand
}
fn __expand_write_line_method(
&mut self,
scope: &Scope,
index: NativeExpand<usize>,
value: ExpandValue,
) {
self.view.__expand_write_method(scope, index, value.into())
}
}
impl<E: Numeric, N: Size, V> ReadsLines<E> for ErasedViewMut<V, N> where
V: ViewOperationsMutExpand<Vector<E, N>, Coords1d>
{
}
impl<E: Numeric, N: Size, V> WritesLines<E> for ErasedViewMut<V, N> where
V: ViewOperationsMutExpand<Vector<E, N>, Coords1d>
{
}
impl<E: Numeric, IO: ErasedIo> ErasedTensor<E, IO> {
pub fn of_view<V: CubeType, N: Size>(_view: V) -> Self {
unexpanded!()
}
pub fn __expand_of_view<V: CubeType, N: Size>(
_scope: &Scope,
view: V::ExpandType,
) -> ErasedTensorExpand<E, IO>
where
V::ExpandType: ViewOperationsExpand<Vector<E, N>, Coords1d> + 'static,
ErasedView<V::ExpandType, N>: ErasedBacking<E, IO>,
{
ErasedTensorExpand::new(ErasedView::<V::ExpandType, N> {
view,
_n: PhantomData,
})
}
pub fn of_view_mut<V: CubeType, N: Size>(_view: V) -> Self {
unexpanded!()
}
pub fn __expand_of_view_mut<V: CubeType, N: Size>(
_scope: &Scope,
view: V::ExpandType,
) -> ErasedTensorExpand<E, IO>
where
V::ExpandType: ViewOperationsMutExpand<Vector<E, N>, Coords1d> + 'static,
ErasedViewMut<V::ExpandType, N>: ErasedBacking<E, IO>,
{
ErasedTensorExpand::new(ErasedViewMut::<V::ExpandType, N> {
view,
_n: PhantomData,
})
}
pub fn of_tensor<N: Size>(_tensor: &Tensor<Vector<E, N>>) -> Self {
unexpanded!()
}
pub fn __expand_of_tensor<N: Size>(
_scope: &Scope,
tensor: &TensorExpand<Vector<E, N>>,
) -> ErasedTensorExpand<E, IO>
where
TensorExpand<Vector<E, N>>: ErasedBacking<E, IO>,
{
ErasedTensorExpand::new(ExpandTypeClone::clone_unchecked(tensor))
}
pub fn of_tensor_mut<N: Size>(_tensor: &mut Tensor<Vector<E, N>>) -> Self {
unexpanded!()
}
pub fn __expand_of_tensor_mut<N: Size>(
_scope: &Scope,
tensor: &mut TensorExpand<Vector<E, N>>,
) -> ErasedTensorExpand<E, IO>
where
TensorExpand<Vector<E, N>>: ErasedBacking<E, IO>,
{
ErasedTensorExpand::new(ExpandTypeClone::clone_unchecked(tensor))
}
pub fn of_virtual<N: Size, IO2: Clone>(_tensor: VirtualTensor<E, N, IO2>) -> Self {
unexpanded!()
}
pub fn __expand_of_virtual<N: Size, IO2: Clone + 'static>(
_scope: &Scope,
tensor: VirtualTensorExpand<E, N, IO2>,
) -> ErasedTensorExpand<E, IO>
where
VirtualTensorExpand<E, N, IO2>: ErasedBacking<E, IO>,
{
ErasedTensorExpand::new(tensor)
}
}
impl<E: Numeric, N: Size> From<VirtualTensorExpand<E, N, ReadWrite>>
for ErasedTensorExpand<E, ReadWrite>
{
fn from(tensor: VirtualTensorExpand<E, N, ReadWrite>) -> Self {
ErasedTensorExpand::new(tensor)
}
}
impl<E: Numeric, N: Size> From<VirtualTensorExpand<E, N, ReadOnly>>
for ErasedTensorExpand<E, ReadOnly>
{
fn from(tensor: VirtualTensorExpand<E, N, ReadOnly>) -> Self {
ErasedTensorExpand::new(tensor)
}
}
mod __cube_type {
use super::*;
impl<E: Numeric, IO: ErasedIo> CubeType for ErasedTensor<E, IO> {
type ExpandType = ErasedTensorExpand<E, IO>;
}
impl<E: Numeric, IO> IntoExpand for ErasedTensorExpand<E, IO> {
type Expand = ErasedTensorExpand<E, IO>;
fn into_expand(self, _: &Scope) -> Self::Expand {
self
}
}
impl<E: Numeric, IO> ExpandTypeClone for ErasedTensorExpand<E, IO> {
fn clone_unchecked(&self) -> Self {
self.clone()
}
}
impl<E: Numeric, IO> IntoMut for ErasedTensorExpand<E, IO> {
fn into_mut(self, _scope: &Scope) -> Self {
self
}
}
impl<E: Numeric, IO> CubeDebug for ErasedTensorExpand<E, IO> {}
impl<E: Numeric, IO> AsRefExpand for ErasedTensorExpand<E, IO> {
fn __expand_ref_method(&self, _: &Scope) -> &Self {
self
}
}
impl<E: Numeric, IO> AsMutExpand for ErasedTensorExpand<E, IO> {
fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
self
}
}
}
impl<E: Numeric, N: Size, IO: ErasedIo> ViewOperations<Vector<E, N>, Coords1d>
for ErasedTensor<E, IO>
{
}
impl<E: Numeric, N: Size, IO: ErasedIo> ViewOperationsExpand<Vector<E, N>, Coords1d>
for ErasedTensorExpand<E, IO>
{
fn __expand_read_method(
&self,
scope: &Scope,
pos: NativeExpand<usize>,
) -> <Vector<E, N> as CubeType>::ExpandType {
self.check_width::<N>(scope, "read");
self.state_read()
.__expand_read_line_method(scope, pos)
.into()
}
fn __expand_read_checked_method(
&self,
scope: &Scope,
pos: NativeExpand<usize>,
) -> <Vector<E, N> as CubeType>::ExpandType {
let zero = <Vector<E, N>>::__expand_cast_from(scope, 0.into());
<Self as ViewOperationsExpand<Vector<E, N>, Coords1d>>::__expand_read_masked_method(
self, scope, pos, zero,
)
}
fn __expand_read_masked_method(
&self,
scope: &Scope,
pos: NativeExpand<usize>,
mask_value: <Vector<E, N> as CubeType>::ExpandType,
) -> <Vector<E, N> as CubeType>::ExpandType {
let in_bounds =
<Self as ViewOperationsExpand<Vector<E, N>, Coords1d>>::__expand_is_in_bounds_method(
self, scope, pos,
);
let keep = usize::__expand_cast_from(scope, in_bounds);
let pos = pos.__expand_mul_method(scope, keep);
let value = <Self as ViewOperationsExpand<Vector<E, N>, Coords1d>>::__expand_read_method(
self, scope, pos,
);
select::expand::<Vector<E, N>>(scope, in_bounds, value, mask_value)
}
fn __expand_read_unchecked_method(
&self,
scope: &Scope,
pos: NativeExpand<usize>,
) -> <Vector<E, N> as CubeType>::ExpandType {
<Self as ViewOperationsExpand<Vector<E, N>, Coords1d>>::__expand_read_method(
self, scope, pos,
)
}
fn __expand_as_linear_slice_method(
&self,
_scope: &Scope,
_pos: NativeExpand<usize>,
_end: NativeExpand<usize>,
) -> &SliceExpand<Vector<E, N>> {
unimplemented!("ErasedTensor: no slice yet, see the module docs")
}
fn __expand_shape_method(&self, scope: &Scope) -> NativeExpand<usize> {
self.state_read().__expand_lines_method(scope)
}
fn __expand_is_in_bounds_method(
&self,
scope: &Scope,
pos: NativeExpand<usize>,
) -> NativeExpand<bool> {
let lines = self.state_read().__expand_lines_method(scope);
pos.__expand_lt_method(scope, &lines)
}
fn __expand_tensor_map_load_method(
&self,
_scope: &Scope,
_barrier: &NativeExpand<Barrier>,
_shared_memory: &mut SliceExpand<Vector<E, N>>,
_pos: NativeExpand<usize>,
) {
unimplemented!("ErasedTensor: not a tensor map")
}
}
impl<E: Numeric, N: Size, IO: ErasedIoWrite> ViewOperationsMut<Vector<E, N>, Coords1d>
for ErasedTensor<E, IO>
{
}
impl<E: Numeric, N: Size, IO: ErasedIoWrite> ViewOperationsMutExpand<Vector<E, N>, Coords1d>
for ErasedTensorExpand<E, IO>
{
fn __expand_write_method(
&self,
scope: &Scope,
pos: NativeExpand<usize>,
value: <Vector<E, N> as CubeType>::ExpandType,
) {
self.check_width::<N>(scope, "write");
self.state_write()
.__expand_write_line_method(scope, pos, value.into())
}
fn __expand_write_checked_method(
&self,
scope: &Scope,
pos: NativeExpand<usize>,
value: <Vector<E, N> as CubeType>::ExpandType,
) {
let in_bounds =
<Self as ViewOperationsExpand<Vector<E, N>, Coords1d>>::__expand_is_in_bounds_method(
self, scope, pos,
);
if_expand(scope, in_bounds, |scope| {
<Self as ViewOperationsMutExpand<Vector<E, N>, Coords1d>>::__expand_write_method(
self, scope, pos, value,
)
})
}
fn __expand_as_linear_slice_mut_method(
&self,
_scope: &Scope,
_pos: NativeExpand<usize>,
_end: NativeExpand<usize>,
) -> &mut SliceExpand<Vector<E, N>> {
unimplemented!("ErasedTensor: no slice yet, see the module docs")
}
fn __expand_tensor_map_store_method(
&self,
_scope: &Scope,
_shared_memory: &SliceExpand<Vector<E, N>>,
_pos: NativeExpand<usize>,
) {
unimplemented!("ErasedTensor: not a tensor map")
}
}