use super::{CubeDebug, CubePrimitive, CubeType, IntoMut, NativeExpand, SliceExpand};
use crate::{self as cubecl, prelude::*};
use crate::{
ir::{self, Instruction},
unexpanded,
};
use core::marker::PhantomData;
use cubecl_macros::{comptime_type, cube, intrinsic};
use cubecl_ir::{CoopMma, Scope, StorageType, Value, VectorSize};
pub use ir::{MatrixIdent, MatrixLayout};
#[derive(Clone, Copy)]
pub struct Plane;
#[derive(Clone, Copy)]
pub struct Cube;
pub trait MatrixScope: Copy {
const SCOPE: ir::MatrixScope;
}
impl MatrixScope for Plane {
const SCOPE: ir::MatrixScope = ir::MatrixScope::Plane;
}
impl MatrixScope for Cube {
const SCOPE: cubecl_ir::MatrixScope = ir::MatrixScope::Cube;
}
#[derive(Copy, Clone)]
pub struct Matrix<C: CubeType, S: MatrixScope = Plane> {
_c: PhantomData<C>,
_s: PhantomData<S>,
}
#[derive(Copy, Clone)]
pub struct MmaDefinition<A: CubeType, B: CubeType, CD: CubeType> {
_a: PhantomData<A>,
_b: PhantomData<B>,
_cd: PhantomData<CD>,
}
pub struct MatrixExpand<C: CubeType, S: MatrixScope> {
elem: Value,
ident: MatrixIdent,
_c: PhantomData<C>,
_s: PhantomData<S>,
}
#[derive(Debug)]
pub struct MmaDefinitionExpand<A: CubeType, B: CubeType, CD: CubeType> {
pub m: usize,
pub n: usize,
pub k: usize,
pub a_type: StorageType,
pub b_type: StorageType,
pub cd_type: StorageType,
pub scales_factor: Option<usize>,
pub scales_type: Option<StorageType>,
_a: PhantomData<A>,
_b: PhantomData<B>,
_cd: PhantomData<CD>,
}
impl<C: CubeType, S: MatrixScope> Clone for MatrixExpand<C, S> {
fn clone(&self) -> Self {
Self {
elem: self.elem,
ident: self.ident,
_c: self._c,
_s: self._s,
}
}
}
impl<C: CubeType, S: MatrixScope> ExpandTypeClone for MatrixExpand<C, S> {
fn clone_unchecked(&self) -> Self {
self.clone()
}
}
impl<A: CubeType, B: CubeType, CD: CubeType> ExpandTypeClone for MmaDefinitionExpand<A, B, CD> {
fn clone_unchecked(&self) -> Self {
*self
}
}
impl<C: CubeType, S: MatrixScope> AsRefExpand for MatrixExpand<C, S> {
fn __expand_ref_method(&self, _scope: &Scope) -> &Self {
self
}
}
impl<C: CubeType, S: MatrixScope> AsMutExpand for MatrixExpand<C, S> {
fn __expand_ref_mut_method(&mut self, _scope: &Scope) -> &mut Self {
self
}
}
impl<A: CubeType, B: CubeType, CD: CubeType> AsRefExpand for MmaDefinitionExpand<A, B, CD> {
fn __expand_ref_method(&self, _scope: &Scope) -> &Self {
self
}
}
impl<A: CubeType, B: CubeType, CD: CubeType> AsMutExpand for MmaDefinitionExpand<A, B, CD> {
fn __expand_ref_mut_method(&mut self, _scope: &Scope) -> &mut Self {
self
}
}
impl<A: CubeType, B: CubeType, CD: CubeType> Copy for MmaDefinitionExpand<A, B, CD> {}
impl<A: CubeType, B: CubeType, CD: CubeType> Clone for MmaDefinitionExpand<A, B, CD> {
fn clone(&self) -> Self {
*self
}
}
impl<C: CubeType, S: MatrixScope> CubeType for Matrix<C, S> {
type ExpandType = MatrixExpand<C, S>;
}
impl<A: CubeType, B: CubeType, CD: CubeType> CubeType for MmaDefinition<A, B, CD> {
type ExpandType = MmaDefinitionExpand<A, B, CD>;
}
impl<C: CubeType, S: MatrixScope> IntoExpand for MatrixExpand<C, S> {
type Expand = Self;
fn into_expand(self, _: &Scope) -> Self::Expand {
self
}
}
impl<C: CubeType, S: MatrixScope> IntoMut for MatrixExpand<C, S> {
fn into_mut(self, _scope: &Scope) -> Self {
self
}
}
impl<C: CubeType, S: MatrixScope> CubeDebug for MatrixExpand<C, S> {
fn set_debug_name(&self, scope: &Scope, name: &'static str) {
scope.update_value_name(self.elem, name);
}
}
impl<A: CubeType, B: CubeType, CD: CubeType> IntoExpand for MmaDefinitionExpand<A, B, CD> {
type Expand = Self;
fn into_expand(self, _: &Scope) -> Self::Expand {
self
}
}
impl<A: CubeType, B: CubeType, CD: CubeType> IntoMut for MmaDefinitionExpand<A, B, CD> {
fn into_mut(self, _scope: &Scope) -> Self {
self
}
}
impl<A: CubeType, B: CubeType, CD: CubeType> CubeDebug for MmaDefinitionExpand<A, B, CD> {}
#[cube]
impl<C: CubePrimitive, S: MatrixScope> Matrix<C, S> {
pub unsafe fn uninitialized(
#[comptime] ident: MatrixIdent,
#[comptime] m: usize,
#[comptime] n: usize,
#[comptime] k: usize,
layout: MatrixLayout,
) -> Self {
intrinsic!(|scope| {
let elem = C::__expand_as_type(scope).storage_type();
let elem = scope.create_local_mut(Type::Matrix(ir::MatrixType::new(
ident,
m,
n,
k,
elem,
layout,
S::SCOPE,
)));
MatrixExpand {
elem,
ident,
_c: PhantomData,
_s: PhantomData,
}
})
}
pub fn from_value(
#[comptime] ident: MatrixIdent,
#[comptime] m: usize,
#[comptime] n: usize,
#[comptime] k: usize,
layout: MatrixLayout,
value: C,
) -> Self
where
C: Scalar,
{
let mut mat = unsafe { Self::uninitialized(ident, m, n, k, layout) };
fill(&mut mat, value);
mat
}
pub fn from_slice(
#[comptime] ident: MatrixIdent,
#[comptime] m: usize,
#[comptime] n: usize,
#[comptime] k: usize,
layout: MatrixLayout,
value: &[C],
stride: u32,
) -> Self {
let mut mat = unsafe { Self::uninitialized(ident, m, n, k, layout) };
if comptime![ident == MatrixIdent::Accumulator] {
load_with_layout(&mut mat, value, stride, layout);
} else {
load(&mut mat, value, stride);
}
mat
}
pub fn from_tensor(
#[comptime] ident: MatrixIdent,
#[comptime] m: usize,
#[comptime] n: usize,
#[comptime] k: usize,
value: &TensorView<C>,
) -> Self {
let mut mat = unsafe { Self::uninitialized(ident, m, n, k, MatrixLayout::Undefined) };
load_tensor(&mut mat, value);
mat
}
}
#[cube]
impl<A: Scalar, B: Scalar, CD: Scalar> MmaDefinition<A, B, CD> {
pub fn new(#[comptime] m: usize, #[comptime] n: usize, #[comptime] k: usize) -> Self {
intrinsic!(|scope| {
let a_type = A::__expand_as_type(scope).storage_type();
let b_type = B::__expand_as_type(scope).storage_type();
let cd_type = CD::__expand_as_type(scope).storage_type();
MmaDefinitionExpand {
m,
n,
k,
a_type,
b_type,
cd_type,
scales_factor: None,
scales_type: None,
_a: PhantomData,
_b: PhantomData,
_cd: PhantomData,
}
})
}
pub fn new_scaled<S: CubePrimitive>(
#[comptime] m: usize,
#[comptime] n: usize,
#[comptime] k: usize,
#[comptime] scale_factor: usize,
) -> Self {
intrinsic!(|scope| {
let a_type = A::__expand_as_type(scope).storage_type();
let b_type = B::__expand_as_type(scope).storage_type();
let cd_type = CD::__expand_as_type(scope).storage_type();
MmaDefinitionExpand {
m,
n,
k,
a_type,
b_type,
cd_type,
scales_factor: Some(scale_factor),
scales_type: Some(S::__expand_as_type(scope).storage_type()),
_a: PhantomData,
_b: PhantomData,
_cd: PhantomData,
}
})
}
#[allow(unused)]
pub fn num_elems(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(usize) {
intrinsic!(|scope| {
match ident {
MatrixIdent::A => (self.m * self.k) / self.a_type.packing_factor(),
MatrixIdent::B => (self.k * self.n) / self.b_type.packing_factor(),
MatrixIdent::Accumulator => (self.m * self.n) / self.cd_type.packing_factor(),
}
})
}
#[allow(unused)]
pub fn elems_per_lane(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(usize) {
intrinsic!(|scope| {
let elems = self.__expand_num_elems_method(scope, ident);
let plane_dim = scope.state().target_properties.mma.const_plane_size as usize;
let duplication = match ident {
MatrixIdent::A => scope.state().target_properties.mma.register_duplication_a,
MatrixIdent::B => scope.state().target_properties.mma.register_duplication_b,
MatrixIdent::Accumulator => {
scope.state().target_properties.mma.register_duplication_acc
}
};
(elems * duplication) / plane_dim
})
}
#[allow(unused)]
pub fn vectors_per_lane(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(usize) {
intrinsic!(|scope| {
let elems = self.clone().__expand_elems_per_lane_method(scope, ident);
let vector_size = self.__expand_vector_size_method(scope, ident);
elems / vector_size
})
}
#[allow(unused)]
pub fn vector_layout(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(MatrixLayout) {
intrinsic!(|scope| {
match ident {
MatrixIdent::A => scope.state().target_properties.mma.register_layout_a,
MatrixIdent::B => scope.state().target_properties.mma.register_layout_b,
MatrixIdent::Accumulator => scope.state().target_properties.mma.register_layout_acc,
}
})
}
pub fn vector_size(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(VectorSize) {
intrinsic!(|scope| {
let storage = match ident {
MatrixIdent::A => self.a_type,
MatrixIdent::B => self.b_type,
MatrixIdent::Accumulator => self.cd_type,
};
let matrix = cubecl_ir::MatrixType {
ident,
m: self.m,
n: self.n,
k: self.k,
storage: storage,
layout: MatrixLayout::ColMajor,
scope: ir::MatrixScope::Plane,
};
scope
.state()
.target_properties
.mma
.contiguous_elements
.apply(ident, matrix)
})
}
pub fn position_of_nth(
&self,
lane_id: u32,
elem_idx: u32,
#[comptime] ident: MatrixIdent,
) -> (u32, u32) {
intrinsic!(|scope| {
let lane_id: Value = lane_id.into();
let elem_idx: Value = elem_idx.into();
let ty = match ident {
MatrixIdent::A => self.a_type,
MatrixIdent::B => self.b_type,
MatrixIdent::Accumulator => self.cd_type,
};
let layout = match ident {
MatrixIdent::A => scope.state().target_properties.mma.register_layout_a,
MatrixIdent::B => scope.state().target_properties.mma.register_layout_b,
MatrixIdent::Accumulator => scope.state().target_properties.mma.register_layout_acc,
};
let matrix = cubecl_ir::MatrixType {
ident,
m: self.m,
n: self.n,
k: self.k,
storage: ty,
layout,
scope: ir::MatrixScope::Plane,
};
let row = scope.create_value(u32::__expand_as_type(scope));
let col = scope.create_value(u32::__expand_as_type(scope));
scope.register(Instruction::new(
CoopMma::RowIndex {
lane_id,
i: elem_idx,
matrix,
},
row,
));
scope.register(Instruction::new(
CoopMma::ColIndex {
lane_id,
i: elem_idx,
matrix,
},
col,
));
(row.into(), col.into())
})
}
pub fn scales_index(&self, lane_id: u32, #[comptime] ident: MatrixIdent) -> u32 {
let quad_id = lane_id / 4;
let t_id = lane_id % 4;
match ident {
MatrixIdent::A => quad_id + (t_id % 2) * 8,
MatrixIdent::B => quad_id,
MatrixIdent::Accumulator => panic!("Accumulator doesn't have scales"),
}
}
pub fn scales_count(&self) -> comptime_type!(usize) {
intrinsic!(|_| {
self.scales_factor
.expect("Can't retrieve scales count for matrix with no scales")
})
}
pub fn scales_vector_size(&self) -> comptime_type!(VectorSize) {
intrinsic!(|scope| {
let elem = self
.scales_type
.expect("Can't retrieve scales vector size for matrix with no scales");
scope.state().target_properties.mma.register_size_bits / elem.size_bits()
})
}
pub fn load_matrix<E: CubePrimitive, NO: Size>(
&self,
row: &[E],
#[comptime] ident: MatrixIdent,
#[comptime] num_matrices: usize,
#[comptime] transpose: bool,
) -> Array<Vector<E::Scalar, NO>> {
intrinsic!(|scope| {
let slice_vector_size = row.expand.vector_size();
let ptr = unsafe { *row.__expand_as_ptr_method(scope) }.expand;
let out = Array::__expand_new(scope, num_matrices);
scope.register(Instruction::new(
CoopMma::LoadMatrix {
ptr,
factor: num_matrices,
transpose,
},
out.__extract_list(scope),
));
out
})
}
pub fn load_matrix_inplace<E: Scalar, N: Size>(
&self,
row: &[E],
fragment: &mut Array<Vector<E, N>>,
#[comptime] ident: MatrixIdent,
#[comptime] num_matrices: usize,
#[comptime] transpose: bool,
) {
intrinsic!(|scope| {
let vector_size = self.__expand_vector_size_method(scope, ident);
let slice_vector_size = row.expand.vector_size();
let ptr = unsafe { *row.__expand_as_ptr_method(scope) }.expand;
let fragment = fragment.__extract_list(scope);
scope.register(Instruction::new(
CoopMma::LoadMatrix {
ptr,
factor: num_matrices,
transpose,
},
fragment,
));
})
}
pub fn store_matrix<E: CubePrimitive, N: Size>(
&self,
row: &mut [E],
registers: &Array<Vector<E::Scalar, N>>,
#[comptime] ident: MatrixIdent,
#[comptime] num_matrices: usize,
#[comptime] transpose: bool,
) {
intrinsic!(|scope| {
let vector_size = self.__expand_vector_size_method(scope, ident);
let registers = registers.__extract_list(scope);
let destination = unsafe { *row.__expand_as_ptr_method(scope) }.expand;
scope.register(Instruction::no_out(CoopMma::StoreMatrix {
registers,
destination,
factor: num_matrices,
transpose,
}));
})
}
#[allow(unused)]
pub fn execute<NA: Size, NB: Size, NC: Size>(
&self,
registers_a: &Array<Vector<A, NA>>,
registers_b: &Array<Vector<B, NB>>,
registers_c: &Array<Vector<CD, NC>>,
) -> Array<Vector<CD, NC>> {
intrinsic!(|scope| {
let acc_elems = self
.clone()
.__expand_elems_per_lane_method(scope, MatrixIdent::Accumulator);
let acc_vector_size = self
.clone()
.__expand_vector_size_method(scope, MatrixIdent::Accumulator);
let num_registers = acc_elems / acc_vector_size;
let registers_d = Array::__expand_new(scope, num_registers);
let registers_a = registers_a.__extract_list(scope);
let registers_b = registers_b.__extract_list(scope);
let registers_c = registers_c.__extract_list(scope);
let matrix = cubecl_ir::MatrixType {
ident: MatrixIdent::A,
m: self.m,
n: self.n,
k: self.k,
storage: self.a_type,
layout: MatrixLayout::ColMajor,
scope: ir::MatrixScope::Plane,
};
scope.register(Instruction::new(
CoopMma::ExecuteManual {
matrix,
registers_a,
registers_b,
registers_c,
},
registers_d.__extract_list(scope),
));
registers_d
})
}
#[allow(unused)]
pub fn execute_inplace<NA: Size, NB: Size, NC: Size>(
&self,
registers_a: &Array<Vector<A, NA>>,
registers_b: &Array<Vector<B, NB>>,
registers_c: &mut Array<Vector<CD, NC>>,
) {
intrinsic!(|scope| {
let acc_elems = self
.clone()
.__expand_elems_per_lane_method(scope, MatrixIdent::Accumulator);
let acc_vector_size = self
.clone()
.__expand_vector_size_method(scope, MatrixIdent::Accumulator);
let num_registers = acc_elems / acc_vector_size;
let registers_a = registers_a.__extract_list(scope);
let registers_b = registers_b.__extract_list(scope);
let registers_c = registers_c.__extract_list(scope);
let matrix = cubecl_ir::MatrixType {
ident: MatrixIdent::A,
m: self.m,
n: self.n,
k: self.k,
storage: self.a_type,
layout: MatrixLayout::ColMajor,
scope: ir::MatrixScope::Plane,
};
scope.register(Instruction::new(
CoopMma::ExecuteManual {
matrix,
registers_a,
registers_b,
registers_c,
},
registers_c,
));
})
}
#[allow(unused)]
pub fn execute_scaled<S: Scalar, NA: Size, NB: Size, NC: Size, NS: Size>(
&self,
registers_a: &Array<Vector<A, NA>>,
registers_b: &Array<Vector<B, NB>>,
registers_c: &Array<Vector<CD, NC>>,
scales_a: Vector<S, NS>,
scales_b: Vector<S, NS>,
) -> Array<Vector<CD, NC>> {
intrinsic!(|scope| {
let acc_elems = self
.clone()
.__expand_elems_per_lane_method(scope, MatrixIdent::Accumulator);
let acc_vector_size = self
.clone()
.__expand_vector_size_method(scope, MatrixIdent::Accumulator);
let num_registers = acc_elems / acc_vector_size;
let registers_d = Array::__expand_new(scope, num_registers);
let registers_a = registers_a.__extract_list(scope);
let registers_b = registers_b.__extract_list(scope);
let registers_c = registers_c.__extract_list(scope);
let matrix = cubecl_ir::MatrixType {
ident: MatrixIdent::A,
m: self.m,
n: self.n,
k: self.k,
storage: self.a_type,
layout: MatrixLayout::ColMajor,
scope: ir::MatrixScope::Plane,
};
scope.register(Instruction::new(
CoopMma::ExecuteScaled {
matrix,
registers_a,
registers_b,
registers_c,
scales_a: scales_a.expand,
scales_b: scales_b.expand,
scales_factor: self
.scales_factor
.expect("Can't execute scaled on matrix with no scales"),
},
registers_d.__extract_list(scope),
));
registers_d
})
}
}
#[allow(unused_variables)]
pub fn fill<C: Scalar, S: MatrixScope>(mat: &mut Matrix<C, S>, value: C) {
unexpanded!()
}
pub mod fill {
use super::*;
pub fn expand<C: Scalar, S: MatrixScope>(
scope: &Scope,
mat: &mut MatrixExpand<C, S>,
value: NativeExpand<C>,
) {
let value: Value = value.into();
scope.register(Instruction::new(ir::CoopMma::Fill { value }, mat.elem));
}
}
#[allow(unused_variables)]
pub fn load<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
mat: &mut Matrix<C, S>,
value: &[V],
stride: u32,
) {
unexpanded!()
}
pub mod load {
use super::*;
pub fn expand<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
scope: &Scope,
mat: &mut MatrixExpand<C, S>,
value: &SliceExpand<V>,
stride: NativeExpand<u32>,
) {
let stride: Value = stride.into();
assert_ne!(
mat.ident,
MatrixIdent::Accumulator,
"Loading accumulator requires explicit layout. Use `load_with_layout` instead."
);
let ptr = unsafe { *value.__expand_as_ptr_method(scope) }.expand;
scope.register(Instruction::new(
ir::CoopMma::Load {
ptr,
stride,
layout: None,
},
mat.elem,
));
}
}
#[allow(unused_variables)]
pub fn load_tensor<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
mat: &mut Matrix<C, S>,
value: &TensorView<V>,
) {
unexpanded!()
}
pub mod load_tensor {
use super::*;
pub fn expand<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
scope: &Scope,
mat: &mut MatrixExpand<C, S>,
value: &TensorViewExpand<V>,
) {
assert_ne!(
mat.ident,
MatrixIdent::Accumulator,
"Loading accumulator requires explicit layout. Use `load_with_layout` instead."
);
let buffer = value.buffer.__extract_list(scope);
scope.register(Instruction::new(
ir::CoopMma::LoadTensor {
buffer,
layout: value.layout.expand,
view: match &value.view {
ComptimeOptionExpand::None => None,
ComptimeOptionExpand::Some(view) => Some(view.expand),
},
},
mat.elem,
));
}
}
#[allow(unused_variables)]
pub fn load_with_layout<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
mat: &mut Matrix<C, S>,
value: &[V],
stride: u32,
layout: MatrixLayout,
) {
unexpanded!()
}
pub mod load_with_layout {
use super::*;
pub fn expand<C: CubeType, V: CubePrimitive, S: MatrixScope>(
scope: &Scope,
mat: &mut MatrixExpand<C, S>,
value: &SliceExpand<V>,
stride: NativeExpand<u32>,
layout: MatrixLayout,
) {
let stride: Value = stride.into();
let ptr = unsafe { *value.__expand_as_ptr_method(scope) }.expand;
scope.register(Instruction::new(
ir::CoopMma::Load {
ptr,
stride,
layout: Some(layout),
},
mat.elem,
));
}
}
#[allow(unused_variables)]
pub fn store<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
output: &mut [O],
mat: &Matrix<C, S>,
stride: u32,
layout: MatrixLayout,
) {
unexpanded!()
}
pub mod store {
use super::*;
pub fn expand<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
scope: &Scope,
output: &mut SliceExpand<O>,
mat: &MatrixExpand<C, S>,
stride: NativeExpand<u32>,
layout: MatrixLayout,
) {
let stride: Value = stride.into();
let destination = unsafe { *output.__expand_as_ptr_method(scope) }.expand;
scope.register(Instruction::no_out(ir::CoopMma::Store {
mat: mat.elem,
stride,
destination,
layout,
}));
}
}
#[allow(unused_variables)]
pub fn store_tensor<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
output: &mut TensorView<O>,
mat: &Matrix<C, S>,
) {
unexpanded!()
}
pub mod store_tensor {
use super::*;
pub fn expand<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
scope: &Scope,
output: &mut TensorViewExpand<O>,
mat: &MatrixExpand<C, S>,
) {
let buffer = output.buffer.__extract_list(scope);
scope.register(Instruction::new(
ir::CoopMma::StoreTensor {
mat: mat.elem,
layout: output.layout.expand,
view: match &output.view {
ComptimeOptionExpand::None => None,
ComptimeOptionExpand::Some(view) => Some(view.expand),
},
},
buffer,
));
}
}
#[allow(unused_variables)]
pub fn execute<
A: CubePrimitive,
B: CubePrimitive,
C: CubePrimitive,
D: CubePrimitive,
S: MatrixScope,
>(
mat_a: &Matrix<A, S>,
mat_b: &Matrix<B, S>,
mat_c: &Matrix<C, S>,
mat_d: &Matrix<D, S>,
) {
unexpanded!()
}
pub mod execute {
use super::*;
pub fn expand<
A: CubePrimitive,
B: CubePrimitive,
C: CubePrimitive,
D: CubePrimitive,
S: MatrixScope,
>(
scope: &Scope,
mat_a: &MatrixExpand<A, S>,
mat_b: &MatrixExpand<B, S>,
mat_c: &MatrixExpand<C, S>,
mat_d: &MatrixExpand<D, S>,
) {
scope.register(Instruction::new(
ir::CoopMma::Execute {
mat_a: mat_a.elem,
mat_b: mat_b.elem,
mat_c: mat_c.elem,
},
mat_d.elem,
));
}
}
#[allow(unused_variables)]
pub fn cast<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
input: &Matrix<C, S>,
) -> Matrix<O, S> {
unexpanded!()
}
pub mod cast {
use super::*;
pub fn expand<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
scope: &Scope,
input: &MatrixExpand<C, S>,
) -> MatrixExpand<O, S> {
let ident = input.ident;
if core::any::TypeId::of::<C>() == core::any::TypeId::of::<O>() {
return MatrixExpand {
elem: input.elem,
ident,
_c: PhantomData,
_s: PhantomData,
};
}
let input = input.elem;
let input_mat = match input.ty.unwrap_ptr() {
ir::Type::Matrix(mat) => mat,
_ => unreachable!(),
};
let elem = O::__expand_as_type(scope).storage_type();
let elem = scope.create_local_mut(Type::Matrix(ir::MatrixType::new(
ident,
input_mat.m,
input_mat.n,
input_mat.k,
elem,
MatrixLayout::Undefined,
input_mat.scope,
)));
let output = MatrixExpand {
ident,
elem,
_c: PhantomData,
_s: PhantomData,
};
scope.register(Instruction::new(ir::CoopMma::Cast { input }, output.elem));
output
}
}
#[allow(unused_variables)]
pub fn cast_with_ident<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
input: &Matrix<C, S>,
ident: MatrixIdent,
) -> Matrix<O, S> {
unexpanded!()
}
pub mod cast_with_ident {
use super::*;
pub fn expand<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
scope: &Scope,
input: MatrixExpand<C, S>,
ident: MatrixIdent,
) -> MatrixExpand<O, S> {
if core::any::TypeId::of::<C>() == core::any::TypeId::of::<O>() && ident == input.ident {
return MatrixExpand {
elem: input.elem,
ident,
_c: PhantomData,
_s: PhantomData,
};
}
let input = input.elem;
let input_mat = match input.ty.unwrap_ptr() {
ir::Type::Matrix(mat) => mat,
_ => unreachable!(),
};
let elem = O::__expand_as_type(scope).storage_type();
let elem = scope.create_local_mut(Type::Matrix(ir::MatrixType::new(
ident,
input_mat.m,
input_mat.n,
input_mat.k,
elem,
MatrixLayout::Undefined,
input_mat.scope,
)));
let output = MatrixExpand {
ident,
elem,
_c: PhantomData,
_s: PhantomData,
};
scope.register(Instruction::new(ir::CoopMma::Cast { input }, output.elem));
output
}
}
impl CubeType for MatrixLayout {
type ExpandType = Self;
}
impl IntoExpand for MatrixLayout {
type Expand = Self;
fn into_expand(self, _scope: &Scope) -> Self::Expand {
self
}
}
impl ExpandTypeClone for MatrixLayout {
fn clone_unchecked(&self) -> Self {
*self
}
}
impl IntoMut for MatrixLayout {
fn into_mut(self, _scope: &Scope) -> Self {
self
}
}
impl CubeDebug for MatrixLayout {}
impl AsRefExpand for MatrixLayout {
fn __expand_ref_method(&self, _: &Scope) -> &Self {
self
}
}
impl AsMutExpand for MatrixLayout {
fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
self
}
}
#[allow(unused_variables)]
pub fn execute_elementwise_op<A: CubePrimitive, S: MatrixScope>(
matrix_in: &Matrix<A, S>,
matrix_out: &Matrix<A, S>,
op: impl Fn(u32, u32, A::Scalar) -> A::Scalar,
) {
unexpanded!()
}
pub mod execute_elementwise_op {
use alloc::vec;
use super::*;
pub fn expand<A: CubePrimitive, S: MatrixScope>(
scope: &Scope,
matrix_in: &MatrixExpand<A, S>,
matrix_out: &MatrixExpand<A, S>,
mut op: impl FnMut(
&Scope,
NativeExpand<u32>,
NativeExpand<u32>,
NativeExpand<A::Scalar>,
) -> NativeExpand<A::Scalar>,
) {
let row = scope.create_value(u32::__expand_as_type(scope));
let col = scope.create_value(u32::__expand_as_type(scope));
let elem = scope.create_value(A::Scalar::__expand_as_type(scope));
let mut closure_scope = scope.child();
let return_value = op(&mut closure_scope, row.into(), col.into(), elem.into());
closure_scope.return_value = Some(return_value.expand);
let op = scope.create_function(vec![row, col, elem], closure_scope);
scope.register(Instruction::new(
ir::CoopMma::ExecuteElementwise {
matrix: matrix_in.elem,
op,
},
matrix_out.elem,
));
}
}