use crate::quantize::*;
#[test]
fn test_q4_0_q8_0_matvec_valid_small() {
let in_dim = 32;
let out_dim = 2;
let bytes_per_row = 18; let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; in_dim];
let result = fused_q4_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_ok());
let output = result.expect("test value should be present");
assert_eq!(output.len(), out_dim);
}
#[test]
fn test_q4_0_q8_0_matvec_weight_too_small() {
let in_dim = 32;
let out_dim = 4;
let weight_data = vec![0u8; 10]; let activations = vec![1.0f32; in_dim];
let result = fused_q4_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("too small") || err.contains("need"),
"got: {err}"
);
}
#[test]
fn test_q4_0_q8_0_matvec_activation_mismatch() {
let in_dim = 32;
let out_dim = 2;
let bytes_per_row = 18;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; 16];
let result = fused_q4_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("match") || err.contains("length"),
"got: {err}"
);
}
#[test]
fn test_q4_0_q8_0_matvec_large_parallel() {
let in_dim = 32;
let out_dim = 1024;
let bytes_per_row = 18;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![0.5f32; in_dim];
let result = fused_q4_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_ok());
let output = result.expect("test value should be present");
assert_eq!(output.len(), out_dim);
}
#[test]
fn test_q4_0_q8_0_matvec_multi_block() {
let in_dim = 64;
let out_dim = 4;
let blocks_per_row = 2;
let bytes_per_row = blocks_per_row * 18;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; in_dim];
let result = fused_q4_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_ok());
assert_eq!(result.expect("test value should be present").len(), out_dim);
}
#[test]
fn test_q4_0_q8_0_matvec_into_valid() {
let in_dim = 32;
let out_dim = 4;
let bytes_per_row = 18;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; in_dim];
let mut output = vec![0.0f32; out_dim];
let result =
fused_q4_0_q8_0_parallel_matvec_into(&weight_data, &activations, in_dim, &mut output);
assert!(result.is_ok());
}
#[test]
fn test_q4_0_q8_0_matvec_into_weight_too_small() {
let in_dim = 32;
let weight_data = vec![0u8; 10]; let activations = vec![1.0f32; in_dim];
let mut output = vec![0.0f32; 4];
let result =
fused_q4_0_q8_0_parallel_matvec_into(&weight_data, &activations, in_dim, &mut output);
assert!(result.is_err());
}
#[test]
fn test_q4_0_q8_0_matvec_into_activation_mismatch() {
let in_dim = 32;
let out_dim = 2;
let bytes_per_row = 18;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; 16]; let mut output = vec![0.0f32; out_dim];
let result =
fused_q4_0_q8_0_parallel_matvec_into(&weight_data, &activations, in_dim, &mut output);
assert!(result.is_err());
}
#[test]
fn test_q8_0_q8_0_matvec_valid_small() {
let in_dim = 32;
let out_dim = 2;
let bytes_per_row = 34; let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; in_dim];
let result = fused_q8_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_ok());
let output = result.expect("test value should be present");
assert_eq!(output.len(), out_dim);
}
#[test]
fn test_q8_0_q8_0_matvec_weight_too_small() {
let in_dim = 32;
let out_dim = 4;
let weight_data = vec![0u8; 20]; let activations = vec![1.0f32; in_dim];
let result = fused_q8_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("too small") || err.contains("need"),
"got: {err}"
);
}
#[test]
fn test_q8_0_q8_0_matvec_activation_mismatch() {
let in_dim = 32;
let out_dim = 2;
let bytes_per_row = 34;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; 16];
let result = fused_q8_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_err());
}
#[test]
fn test_q8_0_q8_0_matvec_multi_block() {
let in_dim = 64;
let out_dim = 4;
let blocks_per_row = 2;
let bytes_per_row = blocks_per_row * 34;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; in_dim];
let result = fused_q8_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_ok());
assert_eq!(result.expect("test value should be present").len(), out_dim);
}
#[test]
fn test_q8_0_q8_0_matvec_into_valid() {
let in_dim = 32;
let out_dim = 4;
let bytes_per_row = 34;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; in_dim];
let mut output = vec![0.0f32; out_dim];
let result = fused_q8_0_q8_0_parallel_matvec_into(
&weight_data,
&activations,
in_dim,
out_dim,
&mut output,
);
assert!(result.is_ok());
}
#[test]
fn test_q8_0_q8_0_matvec_into_weight_too_small() {
let in_dim = 32;
let out_dim = 4;
let weight_data = vec![0u8; 20]; let activations = vec![1.0f32; in_dim];
let mut output = vec![0.0f32; out_dim];
let result = fused_q8_0_q8_0_parallel_matvec_into(
&weight_data,
&activations,
in_dim,
out_dim,
&mut output,
);
assert!(result.is_err());
}
#[test]
fn test_q8_0_q8_0_matvec_into_activation_mismatch() {
let in_dim = 32;
let out_dim = 2;
let bytes_per_row = 34;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; 16]; let mut output = vec![0.0f32; out_dim];
let result = fused_q8_0_q8_0_parallel_matvec_into(
&weight_data,
&activations,
in_dim,
out_dim,
&mut output,
);
assert!(result.is_err());
}
#[test]
fn test_q8_0_q8_0_matvec_into_output_too_small() {
let in_dim = 32;
let out_dim = 4;
let bytes_per_row = 34;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![1.0f32; in_dim];
let mut output = vec![0.0f32; 2];
let result = fused_q8_0_q8_0_parallel_matvec_into(
&weight_data,
&activations,
in_dim,
out_dim,
&mut output,
);
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("too small") || err.contains("need"),
"got: {err}"
);
}
#[test]
fn test_extract_scale_min_block_0() {
let scales: [u8; 12] = [0x3F, 0x20, 0x10, 0x08, 0x3E, 0x1F, 0x0F, 0x07, 0, 0, 0, 0];
let (scale, min) = extract_scale_min(&scales, 0);
assert_eq!(scale, 63.0); assert_eq!(min, 62.0); }
#[test]
fn test_extract_scale_min_block_1() {
let scales: [u8; 12] = [0x3F, 0x20, 0x10, 0x08, 0x3E, 0x1F, 0x0F, 0x07, 0, 0, 0, 0];
let (scale, min) = extract_scale_min(&scales, 1);
assert_eq!(scale, 32.0); assert_eq!(min, 31.0); }
#[test]
fn test_extract_scale_min_block_4() {
let mut scales: [u8; 12] = [0; 12];
scales[0] = 0xC0; scales[4] = 0x80; scales[8] = 0x52; let (scale, min) = extract_scale_min(&scales, 4);
assert_eq!(scale, 50.0);
assert_eq!(min, 37.0);
}
#[test]
fn test_extract_scale_min_block_5() {
let mut scales: [u8; 12] = [0; 12];
scales[1] = 0x40; scales[5] = 0xC0; scales[9] = 0x31; let (scale, min) = extract_scale_min(&scales, 5);
assert_eq!(scale, 17.0);
assert_eq!(min, 51.0);
}
#[test]
fn test_extract_scale_min_block_6() {
let mut scales: [u8; 12] = [0; 12];
scales[2] = 0x80; scales[6] = 0x40; scales[10] = 0xAB; let (scale, min) = extract_scale_min(&scales, 6);
assert_eq!(scale, 43.0);
assert_eq!(min, 26.0);
}
#[test]
fn test_extract_scale_min_block_7() {
let mut scales: [u8; 12] = [0; 12];
scales[3] = 0xC0; scales[7] = 0x80; scales[11] = 0xFF; let (scale, min) = extract_scale_min(&scales, 7);
assert_eq!(scale, 63.0);
assert_eq!(min, 47.0);
}
#[test]
fn test_q4_0_q8_0_matvec_with_nonzero_weights() {
let in_dim = 32;
let out_dim = 2;
let bytes_per_row = 18;
let mut weight_data = vec![0u8; out_dim * bytes_per_row];
weight_data[0] = 0x00;
weight_data[1] = 0x3C;
for i in 2..18 {
weight_data[i] = 0x88; }
let activations = vec![1.0f32; in_dim];
let result = fused_q4_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_ok());
}
#[test]
fn test_q8_0_q8_0_matvec_with_nonzero_weights() {
let in_dim = 32;
let out_dim = 2;
let bytes_per_row = 34;
let mut weight_data = vec![0u8; out_dim * bytes_per_row];
weight_data[0] = 0x00;
weight_data[1] = 0x3C;
for i in 2..34 {
weight_data[i] = 10; }
let activations = vec![1.0f32; in_dim];
let result = fused_q8_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_ok());
}
#[test]
fn test_q4_0_matvec_sequential_threshold() {
let in_dim = 32;
let out_dim = 1023; let bytes_per_row = 18;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![0.5f32; in_dim];
let result = fused_q4_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_ok());
assert_eq!(result.expect("test value should be present").len(), out_dim);
}
#[test]
fn test_q4_0_matvec_at_threshold() {
let in_dim = 32;
let out_dim = 1024; let bytes_per_row = 18;
let weight_data = vec![0u8; out_dim * bytes_per_row];
let activations = vec![0.5f32; in_dim];
let result = fused_q4_0_q8_0_parallel_matvec(&weight_data, &activations, in_dim, out_dim);
assert!(result.is_ok());
assert_eq!(result.expect("test value should be present").len(), out_dim);
}
#[test]
fn test_extract_scale_min_all_zeros() {
let scales: [u8; 12] = [0; 12];
for block in 0..8 {
let (scale, min) = extract_scale_min(&scales, block);
assert_eq!(scale, 0.0);
assert_eq!(min, 0.0);
}
}
#[test]
fn test_extract_scale_min_all_max() {
let scales: [u8; 12] = [0xFF; 12];
let (scale, min) = extract_scale_min(&scales, 0);
assert_eq!(scale, 63.0);
assert_eq!(min, 63.0);
let (scale4, min4) = extract_scale_min(&scales, 4);
assert_eq!(scale4, 63.0);
assert_eq!(min4, 63.0);
}