rust/crates/core_simd/tests/swizzle_dyn.rs
Jubilee 4f0d8225fa
Implement dynamic byte-swizzle prototype (rust-lang/portable-simd#334)
This is meant to be an example that is used to test
a Rust intrinsic against, which will replace it.
The interface is fairly direct and doesn't address
more nuanced or interesting permutations one can do,
nevermind on types other than bytes.

The ultimate goal is for direct LLVM support for this.
2023-04-22 18:27:52 -07:00

75 lines
2.3 KiB
Rust

#![feature(portable_simd)]
use core::{fmt, ops::RangeInclusive};
use proptest;
use test_helpers::{self, biteq, make_runner, prop_assert_biteq};
fn swizzle_dyn_scalar_ver<const N: usize>(values: [u8; N], idxs: [u8; N]) -> [u8; N] {
let mut array = [0; N];
for (i, k) in idxs.into_iter().enumerate() {
if (k as usize) < N {
array[i] = values[k as usize];
};
}
array
}
test_helpers::test_lanes! {
fn swizzle_dyn<const N: usize>() {
match_simd_with_fallback(
&core_simd::simd::Simd::<u8, N>::swizzle_dyn,
&swizzle_dyn_scalar_ver,
&|_, _| true,
);
}
}
fn match_simd_with_fallback<Scalar, ScalarResult, Vector, VectorResult, const N: usize>(
fv: &dyn Fn(Vector, Vector) -> VectorResult,
fs: &dyn Fn([Scalar; N], [Scalar; N]) -> [ScalarResult; N],
check: &dyn Fn([Scalar; N], [Scalar; N]) -> bool,
) where
Scalar: Copy + fmt::Debug + SwizzleStrategy,
ScalarResult: Copy + biteq::BitEq + fmt::Debug + SwizzleStrategy,
Vector: Into<[Scalar; N]> + From<[Scalar; N]> + Copy,
VectorResult: Into<[ScalarResult; N]> + From<[ScalarResult; N]> + Copy,
{
test_swizzles_2(&|x: [Scalar; N], y: [Scalar; N]| {
proptest::prop_assume!(check(x, y));
let result_v: [ScalarResult; N] = fv(x.into(), y.into()).into();
let result_s: [ScalarResult; N] = fs(x, y);
crate::prop_assert_biteq!(result_v, result_s);
Ok(())
});
}
fn test_swizzles_2<A: fmt::Debug + SwizzleStrategy, B: fmt::Debug + SwizzleStrategy>(
f: &dyn Fn(A, B) -> proptest::test_runner::TestCaseResult,
) {
let mut runner = make_runner();
runner
.run(
&(A::swizzled_strategy(), B::swizzled_strategy()),
|(a, b)| f(a, b),
)
.unwrap();
}
pub trait SwizzleStrategy {
type Strategy: proptest::strategy::Strategy<Value = Self>;
fn swizzled_strategy() -> Self::Strategy;
}
impl SwizzleStrategy for u8 {
type Strategy = RangeInclusive<u8>;
fn swizzled_strategy() -> Self::Strategy {
0..=64
}
}
impl<T: fmt::Debug + SwizzleStrategy, const N: usize> SwizzleStrategy for [T; N] {
type Strategy = test_helpers::array::UniformArrayStrategy<T::Strategy, Self>;
fn swizzled_strategy() -> Self::Strategy {
Self::Strategy::new(T::swizzled_strategy())
}
}