use scirs2_core::ndarray::{array, Array1};
use scirs2_core::ndarray_ext::elementwise::lerp_simd;
use scirs2_core::ndarray_ext::elementwise::smoothstep_simd;
#[test]
fn test_lerp_simd_f32_basic() {
let a = array![0.0_f32, 10.0, -5.0, 100.0];
let b = array![10.0_f32, 20.0, 5.0, 200.0];
let result = lerp_simd(&a.view(), &b.view(), 0.0_f32);
assert!((result[0] - 0.0).abs() < 1e-6);
assert!((result[1] - 10.0).abs() < 1e-6);
assert!((result[2] - (-5.0)).abs() < 1e-6);
assert!((result[3] - 100.0).abs() < 1e-6);
let result = lerp_simd(&a.view(), &b.view(), 1.0_f32);
assert!((result[0] - 10.0).abs() < 1e-6);
assert!((result[1] - 20.0).abs() < 1e-6);
assert!((result[2] - 5.0).abs() < 1e-6);
assert!((result[3] - 200.0).abs() < 1e-6);
let result = lerp_simd(&a.view(), &b.view(), 0.5_f32);
assert!((result[0] - 5.0).abs() < 1e-6);
assert!((result[1] - 15.0).abs() < 1e-6);
assert!((result[2] - 0.0).abs() < 1e-6);
assert!((result[3] - 150.0).abs() < 1e-6);
}
#[test]
fn test_lerp_simd_f64_basic() {
let a = array![0.0_f64, 100.0, -50.0];
let b = array![100.0_f64, 200.0, 50.0];
let result = lerp_simd(&a.view(), &b.view(), 0.25_f64);
assert!((result[0] - 25.0).abs() < 1e-14);
assert!((result[1] - 125.0).abs() < 1e-14);
assert!((result[2] - (-25.0)).abs() < 1e-14);
let result = lerp_simd(&a.view(), &b.view(), 0.75_f64);
assert!((result[0] - 75.0).abs() < 1e-14);
assert!((result[1] - 175.0).abs() < 1e-14);
assert!((result[2] - 25.0).abs() < 1e-14);
}
#[test]
fn test_lerp_simd_empty() {
let a: Array1<f64> = array![];
let b: Array1<f64> = array![];
let result = lerp_simd(&a.view(), &b.view(), 0.5_f64);
assert_eq!(result.len(), 0);
}
#[test]
fn test_lerp_simd_large_array() {
let n = 10000;
let a = Array1::from_vec((0..n).map(|i| i as f64).collect());
let b = Array1::from_vec((0..n).map(|i| (i * 2) as f64).collect());
let result = lerp_simd(&a.view(), &b.view(), 0.5_f64);
assert_eq!(result.len(), n);
for i in [0, 100, 1000, 5000, 9999] {
let expected = 1.5 * i as f64;
assert!(
(result[i] - expected).abs() < 1e-10,
"lerp[{}] = {}, expected {}",
i,
result[i],
expected
);
}
}
#[test]
fn test_lerp_simd_extrapolation() {
let a = array![0.0_f64, 0.0];
let b = array![10.0_f64, 20.0];
let result = lerp_simd(&a.view(), &b.view(), -1.0_f64);
assert!((result[0] - (-10.0)).abs() < 1e-14);
assert!((result[1] - (-20.0)).abs() < 1e-14);
let result = lerp_simd(&a.view(), &b.view(), 2.0_f64);
assert!((result[0] - 20.0).abs() < 1e-14);
assert!((result[1] - 40.0).abs() < 1e-14);
}
#[test]
fn test_lerp_simd_formula_verification() {
let a = array![1.0_f64, 2.0, 3.0, 4.0, 5.0];
let b = array![11.0_f64, 12.0, 13.0, 14.0, 15.0];
let t = 0.3_f64;
let result = lerp_simd(&a.view(), &b.view(), t);
for i in 0..a.len() {
let expected = a[i] + t * (b[i] - a[i]);
assert!(
(result[i] - expected).abs() < 1e-14,
"Formula verification failed at index {}",
i
);
}
}
#[test]
fn test_lerp_simd_same_values() {
let a = array![5.0_f64, 5.0, 5.0];
let b = array![5.0_f64, 5.0, 5.0];
for t in [0.0, 0.25, 0.5, 0.75, 1.0] {
let result = lerp_simd(&a.view(), &b.view(), t);
for i in 0..a.len() {
assert!(
(result[i] - 5.0).abs() < 1e-14,
"lerp of identical values should be the same value"
);
}
}
}
#[test]
fn test_lerp_simd_animation_blending() {
let keyframe_0 = array![0.0_f64, 0.0, 0.0]; let keyframe_1 = array![10.0_f64, 5.0, 2.0];
for time in [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] {
let position = lerp_simd(&keyframe_0.view(), &keyframe_1.view(), time);
for i in 0..3 {
let expected = keyframe_0[i] + time * (keyframe_1[i] - keyframe_0[i]);
assert!(
(position[i] - expected).abs() < 1e-14,
"Animation interpolation at t={} failed",
time
);
}
}
}
#[test]
fn test_smoothstep_simd_f32_basic() {
let x = array![0.0_f32, 0.25, 0.5, 0.75, 1.0];
let result = smoothstep_simd(0.0_f32, 1.0_f32, &x.view());
assert!((result[0] - 0.0).abs() < 1e-6);
assert!((result[2] - 0.5).abs() < 1e-6);
assert!((result[4] - 1.0).abs() < 1e-6);
for i in 0..result.len() - 1 {
assert!(result[i] <= result[i + 1], "smoothstep should be monotonic");
}
}
#[test]
fn test_smoothstep_simd_f64_basic() {
let x = array![0.0_f64, 0.25, 0.5, 0.75, 1.0];
let result = smoothstep_simd(0.0_f64, 1.0_f64, &x.view());
for i in 0..x.len() {
let t = x[i];
let expected = t * t * (3.0 - 2.0 * t);
assert!(
(result[i] - expected).abs() < 1e-14,
"smoothstep[{}] = {}, expected {}",
i,
result[i],
expected
);
}
}
#[test]
fn test_smoothstep_simd_empty() {
let x: Array1<f64> = array![];
let result = smoothstep_simd(0.0_f64, 1.0_f64, &x.view());
assert_eq!(result.len(), 0);
}
#[test]
fn test_smoothstep_simd_clamping() {
let x = array![-1.0_f64, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0];
let result = smoothstep_simd(0.0_f64, 1.0_f64, &x.view());
assert!((result[0] - 0.0).abs() < 1e-14); assert!((result[1] - 0.0).abs() < 1e-14); assert!((result[2] - 0.0).abs() < 1e-14);
assert!((result[4] - 1.0).abs() < 1e-14); assert!((result[5] - 1.0).abs() < 1e-14); assert!((result[6] - 1.0).abs() < 1e-14); }
#[test]
fn test_smoothstep_simd_custom_edges() {
let x = array![0.0_f64, 2.5, 5.0, 7.5, 10.0];
let result = smoothstep_simd(0.0_f64, 10.0_f64, &x.view());
assert!((result[0] - 0.0).abs() < 1e-14);
assert!((result[2] - 0.5).abs() < 1e-14);
assert!((result[4] - 1.0).abs() < 1e-14);
}
#[test]
fn test_smoothstep_simd_large_array() {
let n = 10000;
let x = Array1::linspace(0.0, 1.0, n);
let result = smoothstep_simd(0.0_f64, 1.0_f64, &x.view());
assert_eq!(result.len(), n);
assert!((result[0] - 0.0).abs() < 1e-14);
let mid = n / 2;
let t_mid = x[mid];
let expected_mid = t_mid * t_mid * (3.0 - 2.0 * t_mid);
assert!((result[mid] - expected_mid).abs() < 1e-10);
assert!((result[n - 1] - 1.0).abs() < 1e-14);
}
#[test]
fn test_smoothstep_simd_derivative_at_edges() {
let eps = 1e-8_f64;
let x_near_0 = array![0.0, eps];
let x_near_1 = array![1.0 - eps, 1.0];
let result_0 = smoothstep_simd(0.0_f64, 1.0_f64, &x_near_0.view());
let result_1 = smoothstep_simd(0.0_f64, 1.0_f64, &x_near_1.view());
let deriv_near_0 = (result_0[1] - result_0[0]) / eps;
assert!(
deriv_near_0.abs() < 1e-5,
"Derivative at edge0 should be near 0, got {}",
deriv_near_0
);
let deriv_near_1 = (result_1[1] - result_1[0]) / eps;
assert!(
deriv_near_1.abs() < 1e-5,
"Derivative at edge1 should be near 0, got {}",
deriv_near_1
);
}
#[test]
fn test_smoothstep_simd_reversed_edges() {
let x = array![0.0_f64, 0.5, 1.0];
let result = smoothstep_simd(1.0_f64, 0.0_f64, &x.view());
assert!((result[0] - 1.0).abs() < 1e-14); assert!((result[2] - 0.0).abs() < 1e-14); }
#[test]
fn test_smoothstep_simd_shadow_transition() {
let distances = array![0.0_f64, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
let shadow_start = 2.0_f64;
let shadow_end = 5.0_f64;
let shadow_factor = smoothstep_simd(shadow_start, shadow_end, &distances.view());
assert!((shadow_factor[0] - 0.0).abs() < 1e-14);
assert!((shadow_factor[1] - 0.0).abs() < 1e-14);
assert!((shadow_factor[2] - 0.0).abs() < 1e-14);
assert!((shadow_factor[5] - 1.0).abs() < 1e-14);
assert!((shadow_factor[6] - 1.0).abs() < 1e-14);
assert!((shadow_factor[7] - 1.0).abs() < 1e-14);
assert!(shadow_factor[3] > 0.0 && shadow_factor[3] < 1.0);
assert!(shadow_factor[4] > 0.0 && shadow_factor[4] < 1.0);
}