46 lines
1.6 KiB
Rust
46 lines
1.6 KiB
Rust
//! u16 quantization: decoding stored feature values and encoding filter bounds.
|
|
|
|
use crate::consts::{NAN_U16, QUANT_SCALE};
|
|
|
|
/// Lightweight reference to quantization parameters for decoding u16 feature data.
|
|
pub struct QuantRef<'a> {
|
|
pub dequant_a: &'a [f32],
|
|
pub quant_min: &'a [f32],
|
|
pub quant_range: &'a [f32],
|
|
pub num_numeric: usize,
|
|
}
|
|
|
|
impl QuantRef<'_> {
|
|
/// Decode a raw u16 value back to f32.
|
|
#[inline]
|
|
pub fn decode(&self, feat_idx: usize, raw: u16) -> f32 {
|
|
if raw == NAN_U16 {
|
|
return f32::NAN;
|
|
}
|
|
if feat_idx >= self.num_numeric {
|
|
raw as f32
|
|
} else {
|
|
raw as f32 * self.dequant_a[feat_idx] + self.quant_min[feat_idx]
|
|
}
|
|
}
|
|
|
|
/// Encode a filter minimum bound to u16 (floors to include boundary values).
|
|
#[inline]
|
|
pub fn encode_min(&self, feat_idx: usize, value: f32) -> u16 {
|
|
if !value.is_finite() || self.quant_range[feat_idx] == 0.0 {
|
|
return 0;
|
|
}
|
|
let norm = (value - self.quant_min[feat_idx]) / self.quant_range[feat_idx];
|
|
(norm * QUANT_SCALE).floor().clamp(0.0, QUANT_SCALE) as u16
|
|
}
|
|
|
|
/// Encode a filter maximum bound to u16 (ceils to include boundary values).
|
|
#[inline]
|
|
pub fn encode_max(&self, feat_idx: usize, value: f32) -> u16 {
|
|
if !value.is_finite() || self.quant_range[feat_idx] == 0.0 {
|
|
return QUANT_SCALE as u16;
|
|
}
|
|
let norm = (value - self.quant_min[feat_idx]) / self.quant_range[feat_idx];
|
|
(norm * QUANT_SCALE).ceil().clamp(0.0, QUANT_SCALE) as u16
|
|
}
|
|
}
|