use num_traits::Zero as _;
use lightweight_simd::*;
#[test]
fn alignment_and_size() {
use core::mem::{align_of, size_of};
assert_eq!(align_of::<f64x8>(), 64);
assert_eq!(size_of::<f64x8>(), 64);
assert_eq!(align_of::<f64x4>(), 32);
assert_eq!(align_of::<f64x2>(), 16);
assert_eq!(align_of::<f64x16>(), 64); assert_eq!(size_of::<f64x16>(), 128);
assert_eq!(align_of::<f32x16>(), 64);
assert_eq!(align_of::<f32x4>(), 16);
assert_eq!(align_of::<f32x2>(), 8);
assert_eq!(align_of::<i64x8>(), 64);
assert_eq!(align_of::<i32x8>(), 32);
assert_eq!(align_of::<i16x4>(), 8);
assert_eq!(align_of::<i8x64>(), 64);
assert_eq!(align_of::<mask8>(), 1);
assert_eq!(align_of::<Aligned64<f64, 2>>(), 64);
assert_eq!(size_of::<Aligned64<f64, 2>>(), 64);
}
#[test]
fn array_alignment() {
let v: Vec<f64x8> = vec![f64x8::zero(); 16];
assert_eq!(v.as_ptr() as usize % 64, 0);
let w: Vec<f32x4> = vec![f32x4::zero(); 16];
assert_eq!(w.as_ptr() as usize % 16, 0);
}
#[test]
fn ops_equivalence() {
let a = f64x8::from_fn(|i| i as f64 * 0.5 + 1.0);
let b = f64x8::from_fn(|i| i as f64 * 0.25 - 2.0);
let got = (a * b).mul_add(a, b) + b * 2.0 - a;
let a2: Simd<f64, 8> = a.into();
let b2 = b.to_simd();
let want = (a2 * b2).mul_add(a2, b2) + b2 * 2.0 - a2;
assert_eq!(got.to_array(), want.to_array());
assert_eq!(got.reduce_sum(), want.reduce_sum());
let mut c = a;
c += b;
c -= b;
c *= b;
c /= b;
let mut d = a2;
d += b2;
d -= b2;
d *= b2;
d /= b2;
assert_eq!(c.to_simd(), d);
assert_eq!((-c).reduce_sum(), (-d).reduce_sum());
}
#[test]
fn conversions() {
let s: Simd<f32, 4> = Simd::from_fn(|i| i as f32);
let a: f32x4 = s.into();
let back: Simd<f32, 4> = a.into();
assert_eq!(back, s);
assert_eq!(f32x4::from([1.0, 2.0, 3.0, 4.0]).reduce_sum(), 10.0);
assert_eq!(a.to_simd(), s);
}
#[test]
fn mask_select_on_aligned() {
let a = f64x8::splat(1.0);
let b = f64x8::splat(2.0);
let m: Simd<bool, 8> = Simd::from_fn(|i| i % 2 == 0);
assert_eq!(a.mask_select(m, b).reduce_sum(), 12.0);
let m2 = a.simd_lt(b);
assert_eq!(m2.to_array(), [true; 8]);
assert!(m2.all_true());
assert_eq!(a.simd_eq(a).to_array(), [true; 8]);
assert_eq!(Simd::<f64, 8>::splat(1.0).mask_select(m, Simd::splat(2.0)).reduce_sum(), 12.0);
}
#[test]
fn float_and_memory_delegation() {
let v = f64x4::from([4.0, 9.0, 0.25, 2.25]);
assert_eq!(v.sqrt().to_array(), [2.0, 3.0, 0.5, 1.5]);
let mut buf = [0.0f64; 4];
v.sqrt().store_slice(&mut buf);
assert_eq!(buf, [2.0, 3.0, 0.5, 1.5]);
let padded = f64x4::from_slice_pad(&[1.0, 2.0]);
assert_eq!(padded.reduce_sum(), 3.0);
assert_eq!(f64x4::from([1.5, 2.5, -1.5, -2.5]).round_ties_even().to_array(), [2.0, 2.0, -2.0, -2.0]);
}
#[test]
fn common_traits() {
assert!(f64x8::zero().is_zero());
assert_eq!(i64x4::one().reduce_product(), 1);
assert_eq!(f64x4::default(), f64x4::zero());
let z: f64x4 = num_traits::Zero::zero();
assert!(z.is_zero());
let v = i64x4::from([1, 2, 3, 4]);
assert_eq!((v << 2).to_array(), [4, 8, 12, 16]);
assert_eq!((v & v).to_simd(), v.to_simd());
}
#[test]
fn uninit_scratch_aligned() {
let mut v = unsafe { f64x8::uninit() };
v.fill(1.5);
assert_eq!(v.reduce_sum(), 12.0);
}
#[cfg(feature = "complex")]
#[test]
fn complex_alignment() {
assert_eq!(core::mem::align_of::<lightweight_simd::c64x2>(), 32);
assert_eq!(core::mem::align_of::<lightweight_simd::c64x4>(), 64);
}
#[cfg(feature = "half")]
#[test]
fn half_alignment() {
assert_eq!(core::mem::align_of::<lightweight_simd::f16x2>(), 4);
assert_eq!(core::mem::align_of::<lightweight_simd::f16x32>(), 64);
assert_eq!(core::mem::align_of::<lightweight_simd::bf16x8>(), 16);
}