#![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(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() { match_simd_with_fallback( &core_simd::simd::Simd::::swizzle_dyn, &swizzle_dyn_scalar_ver, &|_, _| true, ); } } fn match_simd_with_fallback( 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( 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; fn swizzled_strategy() -> Self::Strategy; } impl SwizzleStrategy for u8 { type Strategy = RangeInclusive; fn swizzled_strategy() -> Self::Strategy { 0..=64 } } impl SwizzleStrategy for [T; N] { type Strategy = test_helpers::array::UniformArrayStrategy; fn swizzled_strategy() -> Self::Strategy { Self::Strategy::new(T::swizzled_strategy()) } }