#[test]
fn test_fused_q4k_tiled_matvec_large() {
use crate::quantize::fused_q4k_tiled_matvec;
let in_dim = 512;
let out_dim = 128;
let bytes_per_row = 2 * 144;
let mut weight_data = Vec::with_capacity(out_dim * bytes_per_row);
for row in 0..out_dim {
for sb in 0..2 {
let d = 1.0 + (row as f32) * 0.01 + (sb as f32) * 0.001;
weight_data.extend_from_slice(&half::f16::from_f32(d).to_bits().to_le_bytes());
weight_data.extend_from_slice(&half::f16::from_f32(0.0).to_bits().to_le_bytes());
for i in 0..12 {
weight_data.push(((row * 3 + sb * 5 + i) % 64) as u8);
}
for i in 0..128 {
weight_data.push(((row * 7 + sb * 11 + i) % 256) as u8);
}
}
}
let activations: Vec<f32> = (0..in_dim).map(|i| (i as f32 * 0.005).cos()).collect();
let mut reference = Vec::with_capacity(out_dim);
for row in 0..out_dim {
let row_start = row * bytes_per_row;
let row_data = &weight_data[row_start..row_start + bytes_per_row];
let dot = fused_q4k_dot_simd(row_data, &activations).expect("test");
reference.push(dot);
}
let tiled =
fused_q4k_tiled_matvec(&weight_data, &activations, in_dim, out_dim, None).expect("test");
assert_eq!(tiled.len(), out_dim);
for i in 0..out_dim {
assert_ulp_eq(
tiled[i],
reference[i],
8,
&format!("tiled_matvec_large output {}", i),
);
}
}
#[test]
fn test_fused_q4k_tiled_matvec_custom_tile_size() {
use crate::quantize::fused_q4k_tiled_matvec;
let in_dim = 256;
let out_dim = 100;
let mut weight_data = Vec::with_capacity(out_dim * 144);
for row in 0..out_dim {
let d = 1.0 + (row as f32) * 0.02;
weight_data.extend_from_slice(&half::f16::from_f32(d).to_bits().to_le_bytes());
weight_data.extend_from_slice(&half::f16::from_f32(0.1).to_bits().to_le_bytes());
for i in 0..12 {
weight_data.push(((row + i) % 64) as u8);
}
for i in 0..128 {
weight_data.push(((row * 2 + i) % 256) as u8);
}
}
let activations: Vec<f32> = (0..in_dim).map(|i| i as f32 * 0.01).collect();
let tile_sizes = [1, 8, 16, 32, 64, 100, 128];
let reference =
fused_q4k_tiled_matvec(&weight_data, &activations, in_dim, out_dim, Some(1)).expect("test");
for &tile_size in &tile_sizes[1..] {
let result =
fused_q4k_tiled_matvec(&weight_data, &activations, in_dim, out_dim, Some(tile_size))
.expect("test");
assert_eq!(result.len(), out_dim);
for i in 0..out_dim {
assert_ulp_eq(
result[i],
reference[i],
4,
&format!("tile_size={} output {}", tile_size, i),
);
}
}
}
#[test]
fn test_fused_q4k_tiled_matvec_error_handling() {
use crate::quantize::fused_q4k_tiled_matvec;
let small_data = vec![0u8; 100];
let activations = vec![0.0f32; 256];
assert!(fused_q4k_tiled_matvec(&small_data, &activations, 256, 4, None).is_err());
let weight_data = vec![0u8; 4 * 144];
let bad_activations = vec![0.0f32; 128];
assert!(fused_q4k_tiled_matvec(&weight_data, &bad_activations, 256, 4, None).is_err());
}
#[test]
fn test_fused_q4k_parallel_matvec_basic() {
use crate::quantize::fused_q4k_parallel_matvec;
let in_dim = 256;
let out_dim = 64;
let mut weight_data = Vec::with_capacity(out_dim * 144);
for row in 0..out_dim {
let d = 0.5 + (row as f32) * 0.01;
weight_data.extend_from_slice(&half::f16::from_f32(d).to_bits().to_le_bytes());
weight_data.extend_from_slice(&half::f16::from_f32(0.05).to_bits().to_le_bytes());
for i in 0..12 {
weight_data.push(((row * 7 + i) % 64) as u8);
}
for i in 0..128 {
weight_data.push(((row * 13 + i) % 256) as u8);
}
}
let activations: Vec<f32> = (0..in_dim).map(|i| (i as f32 * 0.01).sin()).collect();
let mut reference = Vec::with_capacity(out_dim);
for row in 0..out_dim {
let row_start = row * 144;
let row_data = &weight_data[row_start..row_start + 144];
let dot = fused_q4k_dot_simd(row_data, &activations).expect("test");
reference.push(dot);
}
let parallel =
fused_q4k_parallel_matvec(&weight_data, &activations, in_dim, out_dim).expect("test");
assert_eq!(parallel.len(), out_dim);
for i in 0..out_dim {
let rel_err = if reference[i].abs() > 1e-6 {
(parallel[i] - reference[i]).abs() / reference[i].abs()
} else {
(parallel[i] - reference[i]).abs()
};
assert!(
rel_err < 0.002,
"parallel_matvec output {}: actual={}, expected={}, rel_err={:.4}% > 0.2%",
i, parallel[i], reference[i], rel_err * 100.0
);
}
}
#[test]
fn test_fused_q4k_parallel_matvec_large() {
use crate::quantize::fused_q4k_parallel_matvec;
let in_dim = 512;
let out_dim = 256;
let bytes_per_row = 2 * 144;
let mut weight_data = Vec::with_capacity(out_dim * bytes_per_row);
for row in 0..out_dim {
for sb in 0..2 {
let d = 1.0 + (row as f32) * 0.005 + (sb as f32) * 0.001;
weight_data.extend_from_slice(&half::f16::from_f32(d).to_bits().to_le_bytes());
weight_data.extend_from_slice(&half::f16::from_f32(0.0).to_bits().to_le_bytes());
for i in 0..12 {
weight_data.push(((row * 3 + sb * 5 + i) % 64) as u8);
}
for i in 0..128 {
weight_data.push(((row * 7 + sb * 11 + i) % 256) as u8);
}
}
}
let activations: Vec<f32> = (0..in_dim).map(|i| (i as f32 * 0.003).cos()).collect();
let mut reference = Vec::with_capacity(out_dim);
for row in 0..out_dim {
let row_start = row * bytes_per_row;
let row_data = &weight_data[row_start..row_start + bytes_per_row];
let dot = fused_q4k_dot_simd(row_data, &activations).expect("test");
reference.push(dot);
}
let parallel =
fused_q4k_parallel_matvec(&weight_data, &activations, in_dim, out_dim).expect("test");
assert_eq!(parallel.len(), out_dim);
for i in 0..out_dim {
let rel_err = if reference[i].abs() > 1e-6 {
(parallel[i] - reference[i]).abs() / reference[i].abs()
} else {
(parallel[i] - reference[i]).abs()
};
assert!(
rel_err < 0.002,
"parallel_matvec_large output {}: actual={}, expected={}, rel_err={:.4}% > 0.2%",
i, parallel[i], reference[i], rel_err * 100.0
);
}
}
#[test]
fn test_fused_q5k_parallel_matvec_basic() {
use crate::quantize::fused_q5k_parallel_matvec;
let in_dim = 256;
let out_dim = 32;
let bytes_per_row = 176;
let mut weight_data = Vec::with_capacity(out_dim * bytes_per_row);
for row in 0..out_dim {
let d = 0.5 + (row as f32) * 0.02;
weight_data.extend_from_slice(&half::f16::from_f32(d).to_bits().to_le_bytes());
weight_data.extend_from_slice(&half::f16::from_f32(0.05).to_bits().to_le_bytes());
for i in 0..12 {
weight_data.push(((row * 5 + i) % 64) as u8);
}
for i in 0..32 {
weight_data.push(((row * 3 + i) % 256) as u8);
}
for i in 0..128 {
weight_data.push(((row * 11 + i) % 256) as u8);
}
}
let activations: Vec<f32> = (0..in_dim).map(|i| (i as f32 * 0.01).sin()).collect();
let mut reference = Vec::with_capacity(out_dim);
for row in 0..out_dim {
let row_start = row * bytes_per_row;
let row_data = &weight_data[row_start..row_start + bytes_per_row];
let dot = fused_q5k_dot_simd(row_data, &activations).expect("test");
reference.push(dot);
}
let parallel =
fused_q5k_parallel_matvec(&weight_data, &activations, in_dim, out_dim).expect("test");
assert_eq!(parallel.len(), out_dim);
for i in 0..out_dim {
assert_ulp_eq(
parallel[i],
reference[i],
4,
&format!("q5k_parallel output {}", i),
);
}
}
#[test]
fn test_fused_q6k_parallel_matvec_basic() {
use crate::quantize::fused_q6k_parallel_matvec;
let in_dim = 256;
let out_dim = 32;
let bytes_per_row = 210;
let mut weight_data = Vec::with_capacity(out_dim * bytes_per_row);
for row in 0..out_dim {
for i in 0..128 {
weight_data.push(((row * 7 + i) % 256) as u8);
}
for i in 0..64 {
weight_data.push(((row * 3 + i) % 256) as u8);
}
for i in 0..16 {
weight_data.push(((row + i) % 128) as u8);
}
let d = 0.5 + (row as f32) * 0.02;
weight_data.extend_from_slice(&half::f16::from_f32(d).to_bits().to_le_bytes());
}
let activations: Vec<f32> = (0..in_dim).map(|i| (i as f32 * 0.01).sin()).collect();
let mut reference = Vec::with_capacity(out_dim);
for row in 0..out_dim {
let row_start = row * bytes_per_row;
let row_data = &weight_data[row_start..row_start + bytes_per_row];
let dot = fused_q6k_dot_simd(row_data, &activations).expect("test");
reference.push(dot);
}
let parallel =
fused_q6k_parallel_matvec(&weight_data, &activations, in_dim, out_dim).expect("test");
assert_eq!(parallel.len(), out_dim);
for i in 0..out_dim {
assert_ulp_eq(
parallel[i],
reference[i],
4,
&format!("q6k_parallel output {}", i),
);
}
}
#[test]
fn test_fused_parallel_matvec_error_handling() {
use crate::quantize::fused_q4k_parallel_matvec;
let small_data = vec![0u8; 100];
let activations = vec![0.0f32; 256];
assert!(fused_q4k_parallel_matvec(&small_data, &activations, 256, 4).is_err());
let weight_data = vec![0u8; 4 * 144];
let bad_activations = vec![0.0f32; 128];
assert!(fused_q4k_parallel_matvec(&weight_data, &bad_activations, 256, 4).is_err());
}