#![allow(clippy::disallowed_methods, clippy::float_cmp)]
use trueno::Matrix;
#[test]
fn test_01_identity_matmul() {
let n = 384;
let identity = Matrix::identity(n);
let data: Vec<f32> = (0..n * n).map(|i| (i as f32) * 0.001).collect();
let a = Matrix::from_vec(n, n, data.clone()).unwrap();
let result = identity.matmul(&a).unwrap();
for i in 0..n {
for j in 0..n {
let expected = data[i * n + j];
let actual = *result.get(i, j).unwrap();
let diff = (expected - actual).abs();
assert!(
diff < 1e-6,
"Identity test failed at ({}, {}): expected {}, got {}, diff {}",
i,
j,
expected,
actual,
diff
);
}
}
}
#[test]
fn test_02_zero_matmul() {
let n = 384;
let zeros = Matrix::zeros(n, n);
let data: Vec<f32> = (0..n * n).map(|i| (i as f32) * 0.001 + 1.0).collect();
let a = Matrix::from_vec(n, n, data).unwrap();
let result = zeros.matmul(&a).unwrap();
for i in 0..n {
for j in 0..n {
let val = *result.get(i, j).unwrap();
assert!(val == 0.0, "Zero test failed at ({}, {}): expected 0.0, got {}", i, j, val);
}
}
}
#[test]
fn test_03_transpose_property() {
let m = 64;
let k = 74;
let n = 64;
let a_data: Vec<f32> = (0..m * k).map(|i| ((i % 17) as f32) * 0.1).collect();
let b_data: Vec<f32> = (0..k * n).map(|i| ((i % 13) as f32) * 0.1).collect();
let a = Matrix::from_vec(m, k, a_data).unwrap();
let b = Matrix::from_vec(k, n, b_data).unwrap();
let c = a.matmul(&b).unwrap();
let at = a.transpose();
let bt = b.transpose();
let c_prime_t = bt.matmul(&at).unwrap();
let c_prime = c_prime_t.transpose();
for i in 0..m {
for j in 0..n {
let v1 = *c.get(i, j).unwrap();
let v2 = *c_prime.get(i, j).unwrap();
let diff = (v1 - v2).abs();
assert!(diff < 1e-5, "Transpose test failed at ({}, {}): {} vs {}", i, j, v1, v2);
}
}
}
#[test]
fn test_04_non_aligned_dimensions() {
let m = 67; let k = 89; let n = 71;
let a_data: Vec<f32> = (0..m * k).map(|i| ((i % 11) as f32) * 0.1).collect();
let b_data: Vec<f32> = (0..k * n).map(|i| ((i % 7) as f32) * 0.1).collect();
let a = Matrix::from_vec(m, k, a_data).unwrap();
let b = Matrix::from_vec(k, n, b_data).unwrap();
let result = a.matmul(&b).unwrap();
assert_eq!(result.rows(), m);
assert_eq!(result.cols(), n);
for i in [0, m / 2, m - 1] {
for j in [0, n / 2, n - 1] {
let mut expected = 0.0f32;
for kk in 0..k {
expected += a.get(i, kk).unwrap() * b.get(kk, j).unwrap();
}
let actual = *result.get(i, j).unwrap();
let diff = (expected - actual).abs();
assert!(
diff < 1e-3,
"Non-aligned test failed at ({}, {}): expected {}, got {}",
i,
j,
expected,
actual
);
}
}
}
#[test]
fn test_05_nan_propagation() {
let n = 8;
let mut a_data: Vec<f32> = vec![1.0; n * n];
a_data[n * 2 + 3] = f32::NAN;
let a = Matrix::from_vec(n, n, a_data).unwrap();
let b = Matrix::from_vec(n, n, vec![1.0; n * n]).unwrap();
let result = a.matmul(&b).unwrap();
let has_nan = (0..n).any(|j| result.get(2, j).unwrap().is_nan());
assert!(has_nan, "NaN was swallowed - row 2 should contain NaN");
}
#[test]
fn test_06_infinity_handling() {
let n = 4;
let a_data: Vec<f32> = vec![f32::MAX; n * n];
let b_data: Vec<f32> = vec![2.0; n * n];
let a = Matrix::from_vec(n, n, a_data).unwrap();
let b = Matrix::from_vec(n, n, b_data).unwrap();
let result = a.matmul(&b).unwrap();
let val = *result.get(0, 0).unwrap();
assert!(val.is_infinite() || val.is_nan(), "Overflow should produce Inf or NaN, got {}", val);
}
#[test]
fn test_07_determinism() {
let n = 128;
let a_data: Vec<f32> = (0..n * n).map(|i| ((i % 97) as f32) * 0.01).collect();
let b_data: Vec<f32> = (0..n * n).map(|i| ((i % 83) as f32) * 0.01).collect();
let a = Matrix::from_vec(n, n, a_data).unwrap();
let b = Matrix::from_vec(n, n, b_data).unwrap();
let reference = a.matmul(&b).unwrap();
for iter in 0..100 {
let result = a.matmul(&b).unwrap();
for i in 0..n {
for j in 0..n {
let r = *reference.get(i, j).unwrap();
let v = *result.get(i, j).unwrap();
assert!(
r.to_bits() == v.to_bits(),
"Determinism failed at iter {}, ({}, {}): {} vs {}",
iter,
i,
j,
r,
v
);
}
}
}
}
#[test]
fn test_10_empty_matrix() {
let a = Matrix::zeros(0, 0);
let b = Matrix::zeros(0, 0);
let result = a.matmul(&b);
match result {
Ok(r) => {
assert_eq!(r.rows(), 0);
assert_eq!(r.cols(), 0);
}
Err(_) => {
}
}
}
#[test]
fn test_11_matmul_10ms_barrier() {
let m = 384;
let k = 74;
let n = 384;
let a_data: Vec<f32> = (0..m * k).map(|i| ((i % 31) as f32) * 0.01).collect();
let b_data: Vec<f32> = (0..k * n).map(|i| ((i % 29) as f32) * 0.01).collect();
let a = Matrix::from_vec(m, k, a_data).unwrap();
let b = Matrix::from_vec(k, n, b_data).unwrap();
let result = a.matmul(&b).unwrap();
assert_eq!(result.rows(), m);
assert_eq!(result.cols(), n);
}
#[test]
fn test_14_memory_ceiling() {
let n = 384;
let a = Matrix::zeros(n, n);
let b = Matrix::zeros(n, n);
let _ = a.matmul(&b).unwrap();
let expected_bytes = 3 * n * n * 4;
assert!(expected_bytes < 256 * 1024 * 1024, "Memory calculation exceeded 256MB ceiling");
}
#[test]
fn test_15_no_memory_leak() {
let n = 128; let a_data: Vec<f32> = (0..n * n).map(|i| (i as f32) * 0.001).collect();
let b_data: Vec<f32> = (0..n * n).map(|i| (i as f32) * 0.001).collect();
let a = Matrix::from_vec(n, n, a_data).unwrap();
let b = Matrix::from_vec(n, n, b_data).unwrap();
for _ in 0..10 {
let result = a.matmul(&b).unwrap();
drop(result);
}
}
#[test]
fn test_30_headless_compatible() {
let a = Matrix::identity(32);
let b = Matrix::identity(32);
let result = a.matmul(&b).unwrap();
for i in 0..32 {
for j in 0..32 {
let expected = if i == j { 1.0 } else { 0.0 };
let actual = *result.get(i, j).unwrap();
assert!((expected - actual).abs() < 1e-6);
}
}
}
#[test]
fn test_34_graceful_error_handling() {
let a = Matrix::zeros(10, 20);
let b = Matrix::zeros(30, 40);
let result = a.matmul(&b);
assert!(result.is_err(), "Should return error for dimension mismatch");
}
#[test]
fn test_38_reference_match() {
let a = Matrix::from_vec(2, 2, vec![1.0, 2.0, 3.0, 4.0]).unwrap();
let b = Matrix::from_vec(2, 2, vec![5.0, 6.0, 7.0, 8.0]).unwrap();
let result = a.matmul(&b).unwrap();
assert_eq!(*result.get(0, 0).unwrap(), 19.0);
assert_eq!(*result.get(0, 1).unwrap(), 22.0);
assert_eq!(*result.get(1, 0).unwrap(), 43.0);
assert_eq!(*result.get(1, 1).unwrap(), 50.0);
}
#[test]
fn test_whisper_encoder_attention() {
let m = 384;
let k = 74; let n = 384;
let q_proj: Vec<f32> = (0..m * k).map(|i| ((i % 19) as f32 - 9.0) * 0.02).collect();
let k_proj: Vec<f32> = (0..k * n).map(|i| ((i % 23) as f32 - 11.0) * 0.02).collect();
let q = Matrix::from_vec(m, k, q_proj).unwrap();
let kt = Matrix::from_vec(k, n, k_proj).unwrap();
let attention = q.matmul(&kt).unwrap();
assert_eq!(attention.rows(), m);
assert_eq!(attention.cols(), n);
}