use core::marker::PhantomData;
use cubecl::ir::{ExpandValue, VectorSize};
use cubecl::prelude::*;
use cubecl::unexpanded;
use cubecl_std::tensor::{
ErasedTensor, ErasedTensorExpand, ErasedTensorOperationsExpand, WriteOnly, WritesLines,
};
use crate::kind::Write;
use crate::*;
#[cube]
pub(crate) fn adding_tile<E: Numeric, V: Size>(
arg: &TileArg<'_>,
partitioning: &Partitioning,
first: bool,
) -> Tile {
let space = comptime!(partitioning.clone());
let lines = arg.lines::<E, V>();
let geometry = RuntimeGeometry::of_tensor::<Vector<E, V>>(
lines,
comptime!(arg.spec.projection.physical_rank()),
);
GlobalOperand::sink(
adding_sink::<E, V>(lines, first),
geometry,
V::value(),
comptime!(space.space().clone()),
comptime!(arg.spec.clone()),
comptime!(Write::Exclusive(Schedule::Sequential)),
)
.tile::<E>(comptime!(space.levels().to_vec()))
}
#[allow(clippy::extra_unused_type_parameters)]
fn adding_sink<E: Numeric, N: Size>(
_values: &Tensor<Vector<E, N>>,
_first: bool,
) -> ErasedTensor<E, WriteOnly> {
unexpanded!()
}
mod adding_sink {
use super::*;
pub fn expand<E: Numeric, N: Size>(
_scope: &Scope,
values: &<Tensor<Vector<E, N>> as CubeType>::ExpandType,
first: NativeExpand<bool>,
) -> ErasedTensorExpand<E, WriteOnly> {
ErasedTensorExpand::new(AddingSink::<E, N> {
values: ExpandTypeClone::clone_unchecked(values),
first,
_n: PhantomData,
})
}
}
struct AddingSink<E: Numeric, N: Size> {
values: <Tensor<Vector<E, N>> as CubeType>::ExpandType,
first: NativeExpand<bool>,
_n: PhantomData<N>,
}
impl<E: Numeric, N: Size> ErasedTensorOperationsExpand<E> for AddingSink<E, N> {
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.values.__expand_buffer_len_method(scope)
}
fn __expand_write_line_method(
&mut self,
scope: &Scope,
index: NativeExpand<usize>,
value: ExpandValue,
) {
adding_line::expand::<E, N>(scope, &mut self.values, index, value.into(), self.first);
}
}
impl<E: Numeric, N: Size> WritesLines<E> for AddingSink<E, N> {}
#[cube]
fn adding_line<E: Numeric, N: Size>(
values: &mut Tensor<Vector<E, N>>,
index: usize,
value: Vector<E, N>,
first: bool,
) {
if first {
values[index] = value;
} else {
values[index] += value;
}
}