use cubecl::prelude::*;
use cubecl_common::quant::scheme::{F32Grid, QuantParam};
use cubecl_core as cubecl;
#[cube]
pub fn round_up_to_param<F: Float>(scale: F, #[comptime] param: QuantParam) -> F {
#[comptime]
match param {
QuantParam::F32 => scale,
QuantParam::F16 | QuantParam::BF16 | QuantParam::UE4M3 => {
F::cast_from(step_up(f32::cast_from(scale), param))
}
QuantParam::UE8M0 => comptime!(unimplemented!("UE8M0 scales are not yet supported")),
}
}
#[cube]
fn step_up(scale: f32, #[comptime] param: QuantParam) -> f32 {
let grid = comptime!(param.f32_grid());
let max = comptime!(param.max_representable());
if scale >= max {
max
} else if comptime!(grid.subnormals.is_some()) {
let subnormals = comptime!(grid.subnormals.unwrap());
let spacing = comptime!(subnormals.spacing);
if scale < comptime!(subnormals.min_normal) {
f32::ceil(scale / spacing) * spacing
} else {
round_up_on_grid(scale, grid)
}
} else {
round_up_on_grid(scale, grid)
}
}
#[cube]
fn round_up_on_grid(scale: f32, #[comptime] grid: F32Grid) -> f32 {
let bits = u32::reinterpret(scale);
let up_bits = (bits + comptime!(grid.round_up_bias())) & comptime!(grid.truncate_mask());
f32::reinterpret(up_bits)
}