//! 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 } }