use crate::quantize::*;
#[test]
fn test_dequantize_q4_1_single_block() {
let mut data = vec![0u8; 20];
let scale_f16 = 0x3C00u16; data[0..2].copy_from_slice(&scale_f16.to_le_bytes());
data[2..4].copy_from_slice(&0u16.to_le_bytes());
let result = dequantize_q4_1(&data);
assert!(result.is_ok());
let values = result.expect("test value should be present");
assert_eq!(values.len(), 32);
for v in &values {
assert!(v.abs() < 1e-3, "Expected ~0.0, got {}", v);
}
}
#[test]
fn test_dequantize_q4_1_with_min_offset() {
let mut data = vec![0u8; 20];
let scale_f16 = 0x3C00u16; let min_f16 = 0x4000u16; data[0..2].copy_from_slice(&scale_f16.to_le_bytes());
data[2..4].copy_from_slice(&min_f16.to_le_bytes());
let result = dequantize_q4_1(&data).expect("test value should be present");
for v in &result {
assert!((v - 2.0).abs() < 0.1, "Expected ~2.0, got {}", v);
}
}
#[test]
fn test_dequantize_q4_1_multiple_blocks() {
let data = vec![0u8; 20 * 3]; let result = dequantize_q4_1(&data);
assert!(result.is_ok());
assert_eq!(result.expect("test value should be present").len(), 32 * 3);
}
#[test]
fn test_dequantize_q4_1_invalid_size() {
let data = vec![0u8; 19]; let result = dequantize_q4_1(&data);
assert!(result.is_err());
}
#[test]
fn test_dequantize_q4_1_invalid_size_21() {
let data = vec![0u8; 21];
let result = dequantize_q4_1(&data);
assert!(result.is_err());
}
#[test]
fn test_dequantize_q4_1_empty() {
let data: Vec<u8> = vec![];
let result = dequantize_q4_1(&data);
assert!(result.is_ok());
assert!(result.expect("test value should be present").is_empty());
}
#[test]
fn test_dequantize_q5_0_single_block() {
let mut data = vec![0u8; 22];
let scale_f16 = 0x3C00u16; data[0..2].copy_from_slice(&scale_f16.to_le_bytes());
let result = dequantize_q5_0(&data);
assert!(result.is_ok());
let values = result.expect("test value should be present");
assert_eq!(values.len(), 32);
for v in &values {
assert!((v - (-16.0)).abs() < 0.5, "Expected ~-16.0, got {}", v);
}
}
#[test]
fn test_dequantize_q5_0_multiple_blocks() {
let data = vec![0u8; 22 * 2];
let result = dequantize_q5_0(&data);
assert!(result.is_ok());
assert_eq!(result.expect("test value should be present").len(), 32 * 2);
}
#[test]
fn test_dequantize_q5_0_invalid_size() {
let data = vec![0u8; 21]; let result = dequantize_q5_0(&data);
assert!(result.is_err());
}
#[test]
fn test_dequantize_q5_0_invalid_size_23() {
let data = vec![0u8; 23];
let result = dequantize_q5_0(&data);
assert!(result.is_err());
}
#[test]
fn test_dequantize_q5_0_empty() {
let result = dequantize_q5_0(&[]);
assert!(result.is_ok());
assert!(result.expect("test value should be present").is_empty());
}
#[test]
fn test_dequantize_q5_1_single_block() {
let mut data = vec![0u8; 24];
let scale_f16 = 0x3C00u16; let min_f16 = 0x4000u16; data[0..2].copy_from_slice(&scale_f16.to_le_bytes());
data[2..4].copy_from_slice(&min_f16.to_le_bytes());
let result = dequantize_q5_1(&data);
assert!(result.is_ok());
let values = result.expect("test value should be present");
assert_eq!(values.len(), 32);
for v in &values {
assert!((v - 2.0).abs() < 0.5, "Expected ~2.0, got {}", v);
}
}
#[test]
fn test_dequantize_q5_1_multiple_blocks() {
let data = vec![0u8; 24 * 4];
let result = dequantize_q5_1(&data);
assert!(result.is_ok());
assert_eq!(result.expect("test value should be present").len(), 32 * 4);
}
#[test]
fn test_dequantize_q5_1_invalid_size() {
let data = vec![0u8; 23];
let result = dequantize_q5_1(&data);
assert!(result.is_err());
}
#[test]
fn test_dequantize_q5_1_invalid_size_25() {
let data = vec![0u8; 25];
let result = dequantize_q5_1(&data);
assert!(result.is_err());
}
#[test]
fn test_dequantize_q5_1_empty() {
let result = dequantize_q5_1(&[]);
assert!(result.is_ok());
assert!(result.expect("test value should be present").is_empty());
}
#[test]
fn test_dequantize_q2_k_single_block() {
let mut data = vec![0u8; 84];
let d_f16 = 0x3C00u16; data[80..82].copy_from_slice(&d_f16.to_le_bytes());
data[82..84].copy_from_slice(&0u16.to_le_bytes()); let result = dequantize_q2_k(&data);
assert!(result.is_ok());
let values = result.expect("test value should be present");
assert_eq!(values.len(), 256); }
#[test]
fn test_dequantize_q2_k_ggml_golden() {
fn reference(scales: &[u8], qs: &[u8], d: f32, dmin: f32) -> Vec<f32> {
let mut y = Vec::with_capacity(256);
let mut is = 0usize;
for group in 0..2 {
let chunk = &qs[group * 32..group * 32 + 32];
let mut shift = 0u8;
for _ in 0..4 {
let sc = scales[is];
is += 1;
let dl = d * f32::from(sc & 0x0F);
let ml = dmin * f32::from(sc >> 4);
for &q in &chunk[0..16] {
y.push(dl * f32::from((q >> shift) & 0x03) - ml);
}
let sc = scales[is];
is += 1;
let dl = d * f32::from(sc & 0x0F);
let ml = dmin * f32::from(sc >> 4);
for &q in &chunk[16..32] {
y.push(dl * f32::from((q >> shift) & 0x03) - ml);
}
shift += 2;
}
}
y
}
let scales: Vec<u8> = (0u8..16).map(|i| i.wrapping_mul(9).wrapping_add(5)).collect();
let qs: Vec<u8> = (0u8..64).map(|i| i.wrapping_mul(7).wrapping_add(1)).collect();
let mut data = Vec::with_capacity(84);
data.extend_from_slice(&scales);
data.extend_from_slice(&qs);
data.extend_from_slice(&0x3C00u16.to_le_bytes()); data.extend_from_slice(&0x3800u16.to_le_bytes()); let expected = reference(&scales, &qs, 1.0, 0.5);
let got = dequantize_q2_k(&data).expect("dequant");
assert_eq!(got.len(), 256);
for (i, (g, e)) in got.iter().zip(expected.iter()).enumerate() {
assert!(
(g - e).abs() < 1e-6,
"Q2_K elem {i}: got {g}, want {e} (ggml ordering)"
);
}
}
#[test]
fn test_dequantize_q2_k_multiple_blocks() {
let data = vec![0u8; 84 * 2];
let result = dequantize_q2_k(&data);
assert!(result.is_ok());
assert_eq!(result.expect("test value should be present").len(), 256 * 2);
}
#[test]
fn test_dequantize_q2_k_invalid_size() {
let data = vec![0u8; 83]; let result = dequantize_q2_k(&data);
assert!(result.is_err());
}
#[test]
fn test_dequantize_q2_k_invalid_size_85() {
let data = vec![0u8; 85];
let result = dequantize_q2_k(&data);
assert!(result.is_err());
}
#[test]
fn test_dequantize_q2_k_empty() {
let result = dequantize_q2_k(&[]);
assert!(result.is_ok());
assert!(result.expect("test value should be present").is_empty());
}
#[test]
fn test_dequantize_q2_k_with_nonzero_scales() {
let mut data = vec![0u8; 84];
for i in 0..16 {
data[i] = 0x11; }
let d_f16 = 0x3C00u16; data[80..82].copy_from_slice(&d_f16.to_le_bytes());
let dmin_f16 = 0x3800u16; data[82..84].copy_from_slice(&dmin_f16.to_le_bytes());
let result = dequantize_q2_k(&data);
assert!(result.is_ok());
let values = result.expect("test value should be present");
assert_eq!(values.len(), 256);
let has_nonzero = values.iter().any(|&v| v.abs() > 1e-6);
assert!(
has_nonzero,
"Expected some non-zero values with non-zero scales"
);
}
#[test]
fn test_dequantize_q4_1_nibble_pattern() {
let mut data = vec![0u8; 20];
let scale_f16 = 0x3C00u16; data[0..2].copy_from_slice(&scale_f16.to_le_bytes());
data[2..4].copy_from_slice(&0u16.to_le_bytes()); data[4] = 0xAB;
let result = dequantize_q4_1(&data).expect("test value should be present");
assert!((result[0] - 11.0).abs() < 0.5, "Got {}", result[0]);
assert!((result[16] - 10.0).abs() < 0.5, "Got {}", result[16]);
}
#[test]
fn test_dequantize_q5_0_with_high_bits() {
let mut data = vec![0u8; 22];
let scale_f16 = 0x3C00u16; data[0..2].copy_from_slice(&scale_f16.to_le_bytes());
data[2..6].copy_from_slice(&1u32.to_le_bytes());
let result = dequantize_q5_0(&data).expect("test value should be present");
assert!(result[0].abs() < 0.5, "Got {}", result[0]);
}
#[test]
fn test_all_dequant_empty_input_empty_output() {
assert!(dequantize_q4_1(&[]).expect("test value should be present").is_empty());
assert!(dequantize_q5_0(&[]).expect("test value should be present").is_empty());
assert!(dequantize_q5_1(&[]).expect("test value should be present").is_empty());
assert!(dequantize_q2_k(&[]).expect("test value should be present").is_empty());
}
#[test]
fn test_all_dequant_single_byte_errors() {
assert!(dequantize_q4_1(&[0]).is_err());
assert!(dequantize_q5_0(&[0]).is_err());
assert!(dequantize_q5_1(&[0]).is_err());
assert!(dequantize_q2_k(&[0]).is_err());
}