use cubecl::ir::{ElemType, UIntKind};
use cubecl_common::quant::scheme::{QuantScheme, QuantStore};
pub fn block_dims(scheme: &QuantScheme, shape: &[usize]) -> Vec<usize> {
match scheme.block_size() {
Some(block) => block
.to_dim_vec(shape.len())
.into_iter()
.map(usize::from)
.collect(),
None => shape.to_vec(),
}
}
pub fn scales_shape(scheme: &QuantScheme, shape: &[usize]) -> Vec<usize> {
scales_grid(shape, &block_dims(scheme, shape))
}
pub fn scales_grid(shape: &[usize], block_dims: &[usize]) -> Vec<usize> {
assert_eq!(
shape.len(),
block_dims.len(),
"shape/block_dims rank mismatch"
);
shape
.iter()
.zip(block_dims)
.map(|(&dim, &block)| {
assert!(
block > 0 && dim.is_multiple_of(block),
"axis of {dim} elements does not divide into {block}-element blocks"
);
dim / block
})
.collect()
}
pub fn values_dtype(scheme: &QuantScheme) -> ElemType {
match scheme.store {
QuantStore::PackedU32(_) => ElemType::UInt(UIntKind::U32),
QuantStore::PackedNative(_) | QuantStore::Native => {
ElemType::from_quant_value(scheme.value)
}
}
}
pub fn values_shape(scheme: &QuantScheme, shape: &[usize]) -> Vec<usize> {
let mut packed = shape.to_vec();
match scheme.store {
QuantStore::PackedU32(_) | QuantStore::PackedNative(_) => {
let last = packed.len() - 1;
packed[last] /= scheme.num_quants();
}
QuantStore::Native => {}
}
packed
}
pub fn scales_dtype(scheme: &QuantScheme) -> ElemType {
ElemType::from_scale_dtype(scheme.scale_dtype())
}