use super::super::super::super::*;
#[test]
fn test_simd_exp_001_softmax_simd_correctness() {
let op = SoftmaxOp::new(8);
let input = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let result = op.execute(input.clone(), Backend::Avx2).unwrap();
let sum: f32 = result.iter().sum();
assert!((sum - 1.0).abs() < 1e-5, "Softmax sum should be 1.0, got {}", sum);
for i in 1..result.len() {
assert!(
result[i] > result[i - 1],
"Softmax should be monotonic: result[{}]={} <= result[{}]={}",
i,
result[i],
i - 1,
result[i - 1]
);
}
}
#[test]
fn test_simd_exp_002_simd_matches_scalar() {
let op = SoftmaxOp::new(16);
let input: Vec<f32> = (0..16).map(|i| i as f32 * 0.5 - 4.0).collect();
let scalar_result = op.execute(input.clone(), Backend::Scalar).unwrap();
let simd_result = op.execute(input.clone(), Backend::Avx2).unwrap();
for (i, (s, a)) in scalar_result.iter().zip(simd_result.iter()).enumerate() {
assert!((s - a).abs() < 1e-5, "Mismatch at index {}: scalar={}, simd={}", i, s, a);
}
}
#[test]
fn test_simd_exp_003_negative_values() {
let op = SoftmaxOp::new(4);
let input = vec![-10.0, -5.0, 0.0, 5.0];
let result = op.execute(input, Backend::Auto).unwrap();
let sum: f32 = result.iter().sum();
assert!((sum - 1.0).abs() < 1e-5);
assert!(result[3] > result[2] && result[2] > result[1] && result[1] > result[0]);
}
#[test]
fn test_simd_exp_004_numerical_stability() {
let op = SoftmaxOp::new(3);
let input = vec![1000.0, 1001.0, 1002.0];
let result = op.execute(input, Backend::Avx2).unwrap();
for &v in &result {
assert!(!v.is_nan(), "Softmax produced NaN");
assert!(!v.is_infinite(), "Softmax produced Inf");
}
let sum: f32 = result.iter().sum();
assert!((sum - 1.0).abs() < 1e-5);
}
#[test]
fn test_quant_q5k_001_basic_dequant() {
let block = BlockQ5K {
d: 1.0,
dmin: 0.0,
scales: [32; 12], qh: [0; 32],
qs: [0; 128],
};
let mut output = [0.0f32; 256];
block.dequantize(&mut output);
for &v in &output {
assert!((v - 0.0).abs() < 1e-3, "Expected near zero with zero scale, got {}", v);
}
}
#[test]
fn test_quant_q5k_002_empty_input() {
let op = DotQ5KOp::new(256);
let result = op.execute((vec![], vec![]), Backend::Scalar).unwrap();
assert_eq!(result, 0.0);
}
#[test]
fn test_quant_q6k_001_basic_dequant() {
let block = BlockQ6K {
ql: [0; 128],
qh: [0; 64],
scales: [0; 16], d: 1.0,
};
let mut output = [0.0f32; 256];
block.dequantize(&mut output);
for &v in &output {
assert!((v - 0.0).abs() < 1e-3, "Expected near zero with zero scale, got {}", v);
}
}
#[test]
fn test_quant_q6k_002_empty_input() {
let op = DotQ6KOp::new(256);
let result = op.execute((vec![], vec![]), Backend::Scalar).unwrap();
assert_eq!(result, 0.0);
}
#[test]
fn test_quant_block_sizes() {
assert_eq!(BlockQ5K::BLOCK_SIZE, 256);
assert_eq!(BlockQ6K::BLOCK_SIZE, 256);
}
#[test]
fn test_quant_q5k_op_name() {
let op = DotQ5KOp::new(256);
assert_eq!(op.name(), "dot_q5k");
}
#[test]
fn test_quant_q6k_op_name() {
let op = DotQ6KOp::new(256);
assert_eq!(op.name(), "dot_q6k");
}
#[test]
fn test_quant_q5k_tokens() {
let op = DotQ5KOp::new(512);
let block = BlockQ5K { d: 1.0, dmin: 0.0, scales: [32; 12], qh: [0; 32], qs: [0; 128] };
let input = (vec![block.clone(), block], vec![0.0f32; 512]);
assert_eq!(op.tokens(&input), 512); }
#[test]
fn test_quant_q6k_tokens() {
let op = DotQ6KOp::new(512);
let block = BlockQ6K { ql: [0; 128], qh: [0; 64], scales: [0; 16], d: 1.0 };
let input = (vec![block.clone(), block], vec![0.0f32; 512]);
assert_eq!(op.tokens(&input), 512); }
#[test]
fn test_simd_exp_005_backend_check() {
assert!(SoftmaxOp::is_simd_backend(Backend::Avx2));
assert!(SoftmaxOp::is_simd_backend(Backend::Avx512));
assert!(SoftmaxOp::is_simd_backend(Backend::Sse2));
assert!(SoftmaxOp::is_simd_backend(Backend::Neon));
assert!(SoftmaxOp::is_simd_backend(Backend::Auto));
assert!(!SoftmaxOp::is_simd_backend(Backend::Scalar));
assert!(!SoftmaxOp::is_simd_backend(Backend::Wasm));
}