use super::super::*;
#[test]
fn test_f16_to_f32_nan() {
let nan_val = f16_to_f32(0x7C01);
assert!(nan_val.is_nan(), "0x7C01 should be NaN");
let neg_nan = f16_to_f32(0xFC01);
assert!(neg_nan.is_nan(), "0xFC01 should be NaN");
}
#[test]
fn test_f16_to_f32_negative_normal() {
let val = f16_to_f32(0xC000);
assert!((val - (-2.0)).abs() < 1e-3, "Expected -2.0, got {}", val);
let val = f16_to_f32(0xB800);
assert!((val - (-0.5)).abs() < 1e-3, "Expected -0.5, got {}", val);
}
#[test]
fn test_f16_to_f32_smallest_normal() {
let val = f16_to_f32(0x0400);
assert!(val > 0.0 && val < 0.001, "Expected small normal, got {}", val);
}
#[test]
fn test_f16_to_f32_largest_normal() {
let val = f16_to_f32(0x7BFF);
assert!((val - 65504.0).abs() < 100.0, "Expected ~65504, got {}", val);
}
#[test]
fn test_f16_to_f32_negative_subnormal() {
let val = f16_to_f32(0x8001);
assert!(val < 0.0 && val > -1e-4, "Expected small negative, got {}", val);
}
#[test]
fn test_f16_to_f32_half() {
let val = f16_to_f32(0x3800);
assert!((val - 0.5).abs() < 1e-6, "Expected 0.5, got {}", val);
}
#[test]
fn test_f16_to_f32_largest_subnormal() {
let largest_subnormal = f16_to_f32(0x03FF);
let smallest_normal = f16_to_f32(0x0400);
assert!(largest_subnormal > 0.0);
assert!(
largest_subnormal < smallest_normal,
"Largest subnormal {} should be less than smallest normal {}",
largest_subnormal,
smallest_normal
);
}
#[test]
#[allow(deprecated)]
fn test_colmajor_sparse_input() {
let in_dim = 256;
let out_dim = 2;
let mut q6k_data = Vec::new();
for _ in 0..out_dim {
q6k_data.extend_from_slice(&[0x33u8; 128]); q6k_data.extend_from_slice(&[0x00u8; 64]); q6k_data.extend_from_slice(&[0x01u8; 16]); q6k_data.extend_from_slice(&[0x00, 0x3C]); }
let mut input = vec![0.0f32; in_dim];
input[0] = 1.0;
let output = matmul_q6k_f32_colmajor(&q6k_data, &input, out_dim, in_dim);
assert_eq!(output.len(), out_dim);
assert!(output[0].is_finite());
}
#[test]
#[allow(deprecated)]
fn test_colmajor_all_zero_input() {
let in_dim = 256;
let out_dim = 2;
let mut q6k_data = Vec::new();
for _ in 0..out_dim {
q6k_data.extend_from_slice(&[0xFFu8; 128]); q6k_data.extend_from_slice(&[0xFFu8; 64]); q6k_data.extend_from_slice(&[0x7Fu8; 16]); q6k_data.extend_from_slice(&[0x00, 0x3C]); }
let input = vec![0.0f32; in_dim];
let output = matmul_q6k_f32_colmajor(&q6k_data, &input, out_dim, in_dim);
assert_eq!(output.len(), out_dim);
for val in &output {
assert_eq!(*val, 0.0, "All-zero input should produce zero output");
}
}
#[test]
fn test_q6k_scalar_vs_dispatch_small() {
let in_dim = 256;
let out_dim = 2;
let mut q6k_data = Vec::new();
for row in 0..out_dim {
for i in 0..128 {
q6k_data.push(((row * 13 + i) % 256) as u8);
}
for i in 0..64 {
q6k_data.push(((row * 7 + i) % 256) as u8);
}
q6k_data.extend_from_slice(&[0x03u8; 16]);
q6k_data.extend_from_slice(&[0x66, 0x2E]); }
let input: Vec<f32> = (0..in_dim).map(|i| ((i as f32) * 0.013).sin()).collect();
let scalar = matmul_q6k_f32_scalar(&q6k_data, &input, out_dim, in_dim);
let dispatch = matmul_q6k_f32_dispatch(&q6k_data, &input, out_dim, in_dim);
for (i, (s, d)) in scalar.iter().zip(dispatch.iter()).enumerate() {
let diff = (s - d).abs();
assert!(diff < 1e-3, "Row {}: scalar={} vs dispatch={}, diff={}", i, s, d, diff);
}
}
#[test]
fn test_matmul_q6k_f32_public_api() {
let in_dim = 256;
let out_dim = 3;
let mut q6k_data = Vec::new();
for _ in 0..out_dim {
q6k_data.extend_from_slice(&[0x22u8; 128]); q6k_data.extend_from_slice(&[0x11u8; 64]); q6k_data.extend_from_slice(&[0x04u8; 16]); q6k_data.extend_from_slice(&[0x00, 0x3C]); }
let input = vec![0.5f32; in_dim];
let result = matmul_q6k_f32(&q6k_data, &input, out_dim, in_dim);
assert_eq!(result.len(), out_dim);
for val in &result {
assert!(val.is_finite());
}
}
#[test]
fn test_q6k_small_input_dim() {
let in_dim = 16; let out_dim = 1;
let mut q6k_data = Vec::new();
q6k_data.extend_from_slice(&[0x55u8; 128]); q6k_data.extend_from_slice(&[0x00u8; 64]); q6k_data.extend_from_slice(&[0x01u8; 16]); q6k_data.extend_from_slice(&[0x00, 0x3C]);
let input = vec![1.0f32; in_dim];
let output = matmul_q6k_f32_scalar(&q6k_data, &input, out_dim, in_dim);
assert_eq!(output.len(), 1);
assert!(output[0].is_finite());
}
#[test]
#[allow(deprecated)]
fn test_colmajor_unaligned_output_dim() {
let ne0 = 300; let ne1 = 2;
let blocks_per_col = (ne0 + SUPER_BLOCK_SIZE - 1) / SUPER_BLOCK_SIZE; let col_bytes = blocks_per_col * SUPER_BLOCK_BYTES;
let mut q6k_data = Vec::new();
for _ in 0..ne1 {
for _ in 0..blocks_per_col {
q6k_data.extend_from_slice(&[0x22u8; 128]); q6k_data.extend_from_slice(&[0x00u8; 64]); q6k_data.extend_from_slice(&[0x01u8; 16]); q6k_data.extend_from_slice(&[0x00, 0x3C]); }
}
assert_eq!(q6k_data.len(), ne1 * col_bytes);
let input = vec![1.0f32; ne1];
let output = matmul_q6k_f32_colmajor(&q6k_data, &input, ne0, ne1);
assert_eq!(output.len(), ne0);
for val in &output {
assert!(val.is_finite());
}
}
#[test]
fn test_compute_chunk_scalar_truncated_data() {
use super::super::gemv::compute_chunk_scalar;
let in_dim = 512; let out_dim = 1;
let num_blocks_per_row = 2;
let row_bytes = num_blocks_per_row * SUPER_BLOCK_BYTES;
let mut q6k_data = Vec::new();
q6k_data.extend_from_slice(&[0x11u8; 128]); q6k_data.extend_from_slice(&[0x00u8; 64]); q6k_data.extend_from_slice(&[0x01u8; 16]); q6k_data.extend_from_slice(&[0x00, 0x3C]); q6k_data.extend_from_slice(&[0x00u8; 100]);
let input = vec![1.0f32; in_dim];
let mut chunk = vec![0.0f32; 1];
compute_chunk_scalar(
&q6k_data,
&input,
&mut chunk,
0,
out_dim,
in_dim,
num_blocks_per_row,
row_bytes,
);
assert!(chunk[0].is_finite());
}
#[test]
fn test_q6k_constants() {
assert_eq!(SUPER_BLOCK_SIZE, 256);
assert_eq!(SUPER_BLOCK_BYTES, 210);
assert_eq!(128 + 64 + 16 + 2, SUPER_BLOCK_BYTES);
}
#[test]
fn test_q6k_negative_input() {
let in_dim = 256;
let out_dim = 2;
let mut q6k_data = Vec::new();
for _ in 0..out_dim {
q6k_data.extend_from_slice(&[0x55u8; 128]); q6k_data.extend_from_slice(&[0x00u8; 64]); q6k_data.extend_from_slice(&[0x01u8; 16]); q6k_data.extend_from_slice(&[0x00, 0x3C]); }
let input: Vec<f32> = (0..in_dim).map(|i| -(i as f32) * 0.01).collect();
let output = matmul_q6k_f32(&q6k_data, &input, out_dim, in_dim);
assert_eq!(output.len(), out_dim);
for val in &output {
assert!(val.is_finite());
}
}
#[test]
fn test_q6k_identical_rows_produce_same_output() {
let in_dim = 256;
let out_dim = 4;
let mut q6k_data = Vec::new();
for _ in 0..out_dim {
q6k_data.extend_from_slice(&[0x42u8; 128]); q6k_data.extend_from_slice(&[0x11u8; 64]); q6k_data.extend_from_slice(&[0x05u8; 16]); q6k_data.extend_from_slice(&[0x66, 0x2E]); }
let input: Vec<f32> = (0..in_dim).map(|i| (i as f32) * 0.005).collect();
let output = matmul_q6k_f32_scalar(&q6k_data, &input, out_dim, in_dim);
for i in 1..out_dim {
assert!(
(output[0] - output[i]).abs() < 1e-6,
"Row 0 ({}) != Row {} ({})",
output[0],
i,
output[i]
);
}
}
#[test]
fn test_q6k_zero_d_scale() {
let in_dim = 256;
let out_dim = 1;
let mut q6k_data = Vec::new();
q6k_data.extend_from_slice(&[0xFFu8; 128]); q6k_data.extend_from_slice(&[0xFFu8; 64]); q6k_data.extend_from_slice(&[0x7Fu8; 16]); q6k_data.extend_from_slice(&[0x00, 0x00]);
let input = vec![1.0f32; in_dim];
let output = matmul_q6k_f32_scalar(&q6k_data, &input, out_dim, in_dim);
assert_eq!(output[0], 0.0, "Zero d-scale should produce zero output");
}