use crate::error::Result;
use crate::scale::Scale;
use crate::tensor::Quantized;
use crate::{adaptive, asymmetric, symmetric};
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Scheme {
Symmetric {
bits: u32,
block: usize,
},
Asymmetric {
bits: u32,
block: usize,
},
Adaptive {
block: usize,
tolerance: f32,
},
}
impl Scheme {
pub const Q8_32: Self = Self::Symmetric { bits: 8, block: 32 };
pub const Q4_32: Self = Self::Symmetric { bits: 4, block: 32 };
pub fn quantize<S: Scale>(self, values: &[f32]) -> Result<Quantized<S>> {
match self {
Self::Symmetric { bits, block } => symmetric::quantize_with::<S>(values, bits, block),
Self::Asymmetric { bits, block } => asymmetric::quantize_with::<S>(values, bits, block),
Self::Adaptive { block, tolerance } => {
adaptive::quantize_with::<S>(values, block, tolerance)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn scheme_enum_matches_direct_call() {
let w = [0.42_f32, -0.10, 0.70, -0.50];
let via = Scheme::Symmetric { bits: 8, block: 4 }
.quantize::<f32>(&w)
.unwrap();
let direct = symmetric::quantize::<f32, 8, 4>(&w).unwrap();
assert_eq!(via.dequantize(), direct.dequantize());
}
}