use scirs2_core::ndarray::Array2;
use scirs2_core::simd_ops::functions::SimdUnifiedOps;
use scirs2_core::simd_ops::matmul::{simd_dot_product_f32, simd_matrix_multiply_f32};
#[test]
fn test_simd_gemm_integration() {
let n = 128;
let a = Array2::<f32>::from_elem((n, n), 1.0);
let b = Array2::<f32>::from_elem((n, n), 2.0);
let mut c = Array2::<f32>::zeros((n, n));
f32::simd_gemm(1.0, &a.view(), &b.view(), 0.0, &mut c);
let expected = 2.0 * n as f32;
for val in c.iter() {
assert!(
(*val - expected).abs() < 1e-2,
"Expected {}, got {}",
expected,
val
);
}
}
#[test]
fn test_simd_dot_product_integration() {
let a = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let b = vec![6.0, 7.0, 8.0, 9.0, 10.0];
let result = simd_dot_product_f32(&a, &b);
assert!((result - 130.0).abs() < 1e-5);
}
#[test]
fn test_matrix_multiply_correctness() {
let sizes = vec![4, 8, 16, 32, 64, 128];
for n in sizes {
let a = vec![1.0f32; n * n];
let b = vec![2.0f32; n * n];
let mut c = vec![0.0f32; n * n];
simd_matrix_multiply_f32(n, n, n, 1.0, &a, &b, 0.0, &mut c);
let expected = 2.0 * n as f32;
for val in &c {
assert!(
(*val - expected).abs() < 1e-2,
"Size {}: Expected {}, got {}",
n,
expected,
val
);
}
}
}
#[test]
fn test_matrix_multiply_identity() {
let n = 64;
let a: Vec<f32> = (0..n * n).map(|i| i as f32).collect();
let mut b = vec![0.0f32; n * n];
for i in 0..n {
b[i * n + i] = 1.0;
}
let mut c = vec![0.0f32; n * n];
simd_matrix_multiply_f32(n, n, n, 1.0, &a, &b, 0.0, &mut c);
for i in 0..n * n {
assert!(
(c[i] - a[i]).abs() < 1e-4,
"Mismatch at index {}: expected {}, got {}",
i,
a[i],
c[i]
);
}
}
#[test]
fn test_matrix_multiply_transpose() {
let m = 32;
let k = 32;
let a: Vec<f32> = (0..m * k).map(|i| (i % 10) as f32).collect();
let mut a_t = vec![0.0f32; k * m];
for i in 0..m {
for j in 0..k {
a_t[j * m + i] = a[i * k + j];
}
}
let mut c = vec![0.0f32; m * m];
simd_matrix_multiply_f32(m, k, m, 1.0, &a, &a_t, 0.0, &mut c);
for i in 0..m {
for j in i..m {
assert!(
(c[i * m + j] - c[j * m + i]).abs() < 1e-4,
"Matrix is not symmetric at ({}, {})",
i,
j
);
}
}
}
#[test]
fn test_rectangular_matrices() {
let m = 3;
let k = 4;
let n = 5;
let a: Vec<f32> = (1..=12).map(|i| i as f32).collect();
let b: Vec<f32> = (1..=20).map(|i| i as f32).collect();
let mut c = vec![0.0f32; m * n];
simd_matrix_multiply_f32(m, k, n, 1.0, &a, &b, 0.0, &mut c);
assert!(
(c[0] - 110.0).abs() < 1e-4,
"C[0,0] expected 110.0, got {}",
c[0]
);
}
#[test]
fn test_alpha_beta_scaling() {
let m = 4;
let k = 4;
let n = 4;
let a = vec![2.0f32; m * k];
let b = vec![3.0f32; k * n];
let mut c = vec![1.0f32; m * n];
simd_matrix_multiply_f32(m, k, n, 0.5, &a, &b, 2.0, &mut c);
for val in &c {
assert!((*val - 14.0).abs() < 1e-4, "Expected 14.0, got {}", val);
}
}
#[test]
fn test_zero_beta() {
let n = 32;
let a = vec![1.0f32; n * n];
let b = vec![1.0f32; n * n];
let mut c = vec![999.0f32; n * n];
simd_matrix_multiply_f32(n, n, n, 1.0, &a, &b, 0.0, &mut c);
let expected = n as f32;
for val in &c {
assert!(
(*val - expected).abs() < 1e-3,
"Expected {}, got {}",
expected,
val
);
}
}
#[test]
fn test_performance_benchmark() {
let n = 256;
let a = vec![1.0f32; n * n];
let b = vec![1.0f32; n * n];
let mut c = vec![0.0f32; n * n];
let start = std::time::Instant::now();
simd_matrix_multiply_f32(n, n, n, 1.0, &a, &b, 0.0, &mut c);
let elapsed = start.elapsed();
assert!(
elapsed.as_millis() < 500,
"Matrix multiply took too long: {:?}",
elapsed
);
let expected = n as f32;
for val in &c {
assert!(
(*val - expected).abs() < 1e-2,
"Expected {}, got {}",
expected,
val
);
}
}