use cubecl::prelude::*;
use cubecl_common::quant::scheme::{F32Grid, ScaleDtype};
use cubecl_core as cubecl;
#[cube]
pub fn round_up_to_dtype<F: Float>(scale: F, #[comptime] dtype: ScaleDtype) -> F {
#[comptime]
match dtype {
ScaleDtype::F32 => scale,
ScaleDtype::F16 | ScaleDtype::BF16 | ScaleDtype::UE4M3 => {
F::cast_from(step_up(f32::cast_from(scale), dtype))
}
ScaleDtype::UE8M0 => comptime!(unimplemented!("UE8M0 scales are not yet supported")),
}
}
#[cube]
fn step_up(scale: f32, #[comptime] dtype: ScaleDtype) -> f32 {
let grid = comptime!(dtype.f32_grid());
let max = comptime!(dtype.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)
}