use super::common::{USizeConvertTo, bytes, bytes_mut, iota_slice};
use crate::{
bitmask,
constant::Const,
traits::{ArrayType, BitMaskType, SIMDMask, SIMDVector},
};
pub(crate) fn test_load_simd<T, const N: usize, V>(arch: V::Arch)
where
T: Default + std::marker::Copy + std::cmp::PartialEq + std::fmt::Debug + bytemuck::Pod,
usize: USizeConvertTo<T>,
Const<N>: ArrayType<T, Type = [T; N]>,
bitmask::BitMask<N, V::Arch>: SIMDMask<Arch = V::Arch>,
V: SIMDVector<Scalar = T, ConstLanes = Const<N>>,
{
let mut reference = [T::default(); N];
iota_slice(&mut reference);
let elsize: usize = std::mem::size_of::<T>();
let mut input = vec![0u8; elsize * 2 * N];
for i in 0..=N * elsize {
input.fill(0);
input[i..i + elsize * N].copy_from_slice(bytes(&reference));
let v = unsafe { V::load_simd(arch, input.as_ptr().add(i).cast::<T>()) };
let arr = v.to_array();
assert_eq!(arr, reference);
}
let mut reference = vec![T::default(); N + 1];
iota_slice(&mut reference);
for keep_first in 0..=N + 5 {
let kept = keep_first.min(N);
for sub in 0..(elsize + 1) {
let offset = elsize * (N - kept + 1) - sub;
let mut expected = [T::default(); N];
bytes_mut(&mut expected[..kept])
.copy_from_slice(&bytes(&reference)[offset..offset + kept * elsize]);
let ptr = unsafe { reference.as_ptr().byte_add(offset) };
let v = unsafe { V::load_simd_first(arch, ptr, keep_first) };
assert_eq!(
v.to_array(),
expected,
"Failed `load_simd_first` for keep_first = {}, sub = {}",
keep_first,
sub
);
let v = unsafe {
V::load_simd_masked_logical(arch, ptr, V::Mask::keep_first(arch, keep_first))
};
assert_eq!(
v.to_array(),
expected,
"Failed `load_simd_masked_logical` for keep_first = {}, sub = {}",
keep_first,
sub
);
let v = unsafe {
V::load_simd_masked(
arch,
ptr,
<Const<N> as BitMaskType<V::Arch>>::Type::keep_first(arch, keep_first),
)
};
assert_eq!(
v.to_array(),
expected,
"Failed `load_simd_masked` for keep_first = {}, sub = {}",
keep_first,
sub
);
}
}
}