use super::*;
use ::ndarray::Array1;
use super::*;
use ::ndarray::arr1;
#[test]
fn test_simd_unified_ops_f32() {
let a = arr1(&[1.0f32, 2.0, 3.0, 4.0]);
let b = arr1(&[5.0f32, 6.0, 7.0, 8.0]);
let sum = f32::simd_add(&a.view(), &b.view());
assert_eq!(sum, arr1(&[6.0f32, 8.0, 10.0, 12.0]));
let product = f32::simd_mul(&a.view(), &b.view());
assert_eq!(product, arr1(&[5.0f32, 12.0, 21.0, 32.0]));
let dot = f32::simd_dot(&a.view(), &b.view());
assert_eq!(dot, 70.0);
}
#[test]
fn test_platform_capabilities() {
let caps = PlatformCapabilities::detect();
println!("{}", caps.summary());
}
#[test]
fn test_auto_optimizer() {
let optimizer = AutoOptimizer::new();
assert!(!optimizer.should_use_gpu(100));
let large_size = 100000;
if optimizer.capabilities.gpu_available {
assert!(optimizer.should_use_gpu(large_size));
}
}
#[test]
fn test_simd_unified_ops_variance_std() {
let a = arr1(&[2.0f64, 4.0, 6.0, 8.0, 10.0]);
let variance = f64::simd_variance(&a.view());
let std = f64::simd_std(&a.view());
assert!((variance - 10.0).abs() < 1e-10);
assert!((std - 10.0f64.sqrt()).abs() < 1e-10);
}
#[test]
fn test_simd_unified_ops_norms() {
let a = arr1(&[3.0f64, -4.0]);
let l1 = f64::simd_norm_l1(&a.view());
assert!((l1 - 7.0).abs() < 1e-10);
let l2 = f64::simd_norm(&a.view());
assert!((l2 - 5.0).abs() < 1e-10);
let linf = f64::simd_norm_linf(&a.view());
assert!((linf - 4.0).abs() < 1e-10);
}
#[test]
fn test_simd_unified_ops_cosine_similarity() {
let a = arr1(&[1.0f64, 0.0, 0.0]);
let b = arr1(&[0.0f64, 1.0, 0.0]);
let c = arr1(&[1.0f64, 0.0, 0.0]);
let sim_ab = f64::simd_cosine_similarity(&a.view(), &b.view());
assert!(sim_ab.abs() < 1e-10);
let sim_ac = f64::simd_cosine_similarity(&a.view(), &c.view());
assert!((sim_ac - 1.0).abs() < 1e-10);
}
#[test]
fn test_simd_unified_ops_distances() {
let a = arr1(&[0.0f64, 0.0, 0.0]);
let b = arr1(&[3.0f64, 4.0, 0.0]);
let euclidean = f64::simd_distance_euclidean(&a.view(), &b.view());
assert!((euclidean - 5.0).abs() < 1e-10);
let manhattan = f64::simd_distance_manhattan(&a.view(), &b.view());
assert!((manhattan - 7.0).abs() < 1e-10);
let chebyshev = f64::simd_distance_chebyshev(&a.view(), &b.view());
assert!((chebyshev - 4.0).abs() < 1e-10);
}
#[test]
fn test_simd_unified_ops_weighted() {
let values = arr1(&[1.0f64, 2.0, 3.0, 4.0]);
let weights = arr1(&[0.1f64, 0.2, 0.3, 0.4]);
let weighted_sum = f64::simd_weighted_sum(&values.view(), &weights.view());
assert!((weighted_sum - 3.0).abs() < 1e-10);
let weighted_mean = f64::simd_weighted_mean(&values.view(), &weights.view());
assert!((weighted_mean - 3.0).abs() < 1e-10);
}
#[test]
fn test_simd_unified_ops_argmin() {
let a = arr1(&[3.0f64, 1.0, 4.0, 1.5, 2.0]);
let result = f64::simd_argmin(&a.view());
assert_eq!(result, Some(1));
let a_f32 = arr1(&[5.0f32, 2.0, 8.0, 1.0, 3.0]);
let result_f32 = f32::simd_argmin(&a_f32.view());
assert_eq!(result_f32, Some(3));
let empty: Array1<f64> = arr1(&[]);
assert_eq!(f64::simd_argmin(&empty.view()), None);
}
#[test]
fn test_simd_unified_ops_argmax() {
let a = arr1(&[3.0f64, 1.0, 4.0, 1.5, 2.0]);
let result = f64::simd_argmax(&a.view());
assert_eq!(result, Some(2));
let a_f32 = arr1(&[5.0f32, 2.0, 8.0, 1.0, 3.0]);
let result_f32 = f32::simd_argmax(&a_f32.view());
assert_eq!(result_f32, Some(2));
let empty: Array1<f64> = arr1(&[]);
assert_eq!(f64::simd_argmax(&empty.view()), None);
}
#[test]
fn test_simd_unified_ops_clip() {
let a = arr1(&[1.0f64, 2.0, 3.0, 4.0, 5.0]);
let result = f64::simd_clip(&a.view(), 2.0, 4.0);
let expected = arr1(&[2.0f64, 2.0, 3.0, 4.0, 4.0]);
assert_eq!(result, expected);
let a_f32 = arr1(&[-1.0f32, 0.0, 0.5, 1.0, 1.5]);
let result_f32 = f32::simd_clip(&a_f32.view(), 0.0, 1.0);
let expected_f32 = arr1(&[0.0f32, 0.0, 0.5, 1.0, 1.0]);
assert_eq!(result_f32, expected_f32);
}
#[test]
fn test_simd_unified_ops_log_sum_exp() {
let a = arr1(&[1.0f64, 2.0, 3.0]);
let result = f64::simd_log_sum_exp(&a.view());
let expected = (1.0f64.exp() + 2.0f64.exp() + 3.0f64.exp()).ln();
assert!((result - expected).abs() < 1e-10);
let a_f32 = arr1(&[1.0f32, 2.0, 3.0]);
let result_f32 = f32::simd_log_sum_exp(&a_f32.view());
let expected_f32 = (1.0f32.exp() + 2.0f32.exp() + 3.0f32.exp()).ln();
assert!((result_f32 - expected_f32).abs() < 1e-5);
let large = arr1(&[1000.0f64, 1000.1, 1000.2]);
let result_large = f64::simd_log_sum_exp(&large.view());
assert!(result_large.is_finite());
let empty: Array1<f64> = arr1(&[]);
let result_empty = f64::simd_log_sum_exp(&empty.view());
assert!(result_empty.is_infinite() && result_empty < 0.0);
}
#[test]
fn test_simd_unified_ops_softmax_via_log_sum_exp() {
let logits = arr1(&[2.0f64, 1.0, 0.1]);
let lse = f64::simd_log_sum_exp(&logits.view());
let probs: Vec<f64> = logits.iter().map(|&x| (x - lse).exp()).collect();
let sum: f64 = probs.iter().sum();
assert!((sum - 1.0).abs() < 1e-10);
for p in &probs {
assert!(*p > 0.0 && *p <= 1.0);
}
}
#[test]
fn test_simd_unified_ops_softmax() {
let a = arr1(&[1.0f64, 2.0, 3.0]);
let result = f64::simd_softmax(&a.view());
let sum: f64 = result.iter().sum();
assert!((sum - 1.0).abs() < 1e-10);
let a_f32 = arr1(&[1.0f32, 2.0, 3.0]);
let result_f32 = f32::simd_softmax(&a_f32.view());
let sum_f32: f32 = result_f32.iter().sum();
assert!((sum_f32 - 1.0).abs() < 1e-5);
}
#[test]
fn test_simd_unified_ops_cumsum() {
let a = arr1(&[1.0f64, 2.0, 3.0, 4.0]);
let result = f64::simd_cumsum(&a.view());
let expected = arr1(&[1.0f64, 3.0, 6.0, 10.0]);
assert_eq!(result, expected);
let a_f32 = arr1(&[1.0f32, 2.0, 3.0, 4.0]);
let result_f32 = f32::simd_cumsum(&a_f32.view());
let expected_f32 = arr1(&[1.0f32, 3.0, 6.0, 10.0]);
assert_eq!(result_f32, expected_f32);
let empty: Array1<f64> = arr1(&[]);
let result_empty = f64::simd_cumsum(&empty.view());
assert!(result_empty.is_empty());
}
#[test]
fn test_simd_unified_ops_cumprod() {
let a = arr1(&[1.0f64, 2.0, 3.0, 4.0]);
let result = f64::simd_cumprod(&a.view());
let expected = arr1(&[1.0f64, 2.0, 6.0, 24.0]);
assert_eq!(result, expected);
let a_f32 = arr1(&[1.0f32, 2.0, 3.0, 4.0]);
let result_f32 = f32::simd_cumprod(&a_f32.view());
let expected_f32 = arr1(&[1.0f32, 2.0, 6.0, 24.0]);
assert_eq!(result_f32, expected_f32);
let with_zero = arr1(&[1.0f64, 2.0, 0.0, 4.0]);
let result_zero = f64::simd_cumprod(&with_zero.view());
let expected_zero = arr1(&[1.0f64, 2.0, 0.0, 0.0]);
assert_eq!(result_zero, expected_zero);
}
#[test]
fn test_simd_unified_ops_diff() {
let a = arr1(&[1.0f64, 3.0, 6.0, 10.0, 15.0]);
let result = f64::simd_diff(&a.view());
let expected = arr1(&[2.0f64, 3.0, 4.0, 5.0]);
assert_eq!(result, expected);
let a_f32 = arr1(&[1.0f32, 3.0, 6.0, 10.0]);
let result_f32 = f32::simd_diff(&a_f32.view());
let expected_f32 = arr1(&[2.0f32, 3.0, 4.0]);
assert_eq!(result_f32, expected_f32);
let single = arr1(&[5.0f64]);
let result_single = f64::simd_diff(&single.view());
assert!(result_single.is_empty());
}
#[test]
fn test_simd_unified_ops_abs() {
let a = arr1(&[-1.0f64, 2.0, -3.0, 4.0, -5.0]);
let result = f64::simd_abs(&a.view());
let expected = arr1(&[1.0f64, 2.0, 3.0, 4.0, 5.0]);
assert_eq!(result, expected);
let a_f32 = arr1(&[-2.0f32, -1.0, 3.0]);
let result_f32 = f32::simd_abs(&a_f32.view());
let expected_f32 = arr1(&[2.0f32, 1.0, 3.0]);
assert_eq!(result_f32, expected_f32);
}
#[test]
fn test_simd_unified_ops_sign() {
let a = arr1(&[-5.0f64, 0.0, 3.0, -1.0, 0.0, 2.0]);
let result = f64::simd_sign(&a.view());
let expected = arr1(&[-1.0f64, 0.0, 1.0, -1.0, 0.0, 1.0]);
assert_eq!(result, expected);
let a_f32 = arr1(&[1.0f32, -1.0, 0.0]);
let result_f32 = f32::simd_sign(&a_f32.view());
let expected_f32 = arr1(&[1.0f32, -1.0, 0.0]);
assert_eq!(result_f32, expected_f32);
}
#[test]
fn test_simd_unified_ops_relu() {
let a = arr1(&[-2.0f64, -1.0, 0.0, 1.0, 2.0]);
let result = f64::simd_relu(&a.view());
let expected = arr1(&[0.0f64, 0.0, 0.0, 1.0, 2.0]);
assert_eq!(result, expected);
let a_f32 = arr1(&[-1.0f32, 0.0, 5.0]);
let result_f32 = f32::simd_relu(&a_f32.view());
let expected_f32 = arr1(&[0.0f32, 0.0, 5.0]);
assert_eq!(result_f32, expected_f32);
}
#[test]
fn test_simd_unified_ops_leaky_relu() {
let a = arr1(&[-2.0f64, -1.0, 0.0, 1.0, 2.0]);
let result = f64::simd_leaky_relu(&a.view(), 0.1);
let expected = arr1(&[-0.2f64, -0.1, 0.0, 1.0, 2.0]);
for (r, e) in result.iter().zip(expected.iter()) {
assert!((r - e).abs() < 1e-10);
}
let a_f32 = arr1(&[-10.0f32, 0.0, 10.0]);
let result_f32 = f32::simd_leaky_relu(&a_f32.view(), 0.01);
let expected_f32 = arr1(&[-0.1f32, 0.0, 10.0]);
for (r, e) in result_f32.iter().zip(expected_f32.iter()) {
assert!((r - e).abs() < 1e-6);
}
}
#[test]
fn test_simd_unified_ops_normalize() {
let a = arr1(&[3.0f64, 4.0]);
let result = f64::simd_normalize(&a.view());
assert!((result[0] - 0.6).abs() < 1e-10);
assert!((result[1] - 0.8).abs() < 1e-10);
let norm: f64 = result.iter().map(|x| x * x).sum::<f64>().sqrt();
assert!((norm - 1.0).abs() < 1e-10);
let a_f32 = arr1(&[3.0f32, 4.0]);
let result_f32 = f32::simd_normalize(&a_f32.view());
assert!((result_f32[0] - 0.6).abs() < 1e-6);
assert!((result_f32[1] - 0.8).abs() < 1e-6);
}
#[test]
fn test_simd_unified_ops_standardize() {
let a = arr1(&[2.0f64, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0]);
let result = f64::simd_standardize(&a.view());
let mean: f64 = result.iter().sum::<f64>() / result.len() as f64;
assert!(mean.abs() < 1e-10, "Mean should be ~0, got {}", mean);
let variance: f64 = result.iter().map(|x| x * x).sum::<f64>() / (result.len() - 1) as f64;
let std = variance.sqrt();
assert!((std - 1.0).abs() < 1e-10, "Std should be ~1, got {}", std);
let a_f32 = arr1(&[1.0f32, 2.0, 3.0, 4.0, 5.0]);
let result_f32 = f32::simd_standardize(&a_f32.view());
let mean_f32: f32 = result_f32.iter().sum::<f32>() / result_f32.len() as f32;
assert!(mean_f32.abs() < 1e-5);
}