3 #[cfg(target_arch = "wasm32")]
9 /// Specifies the default strategy for testing a type.
11 /// This strategy should be what "makes sense" to test.
12 pub trait DefaultStrategy {
13 type Strategy: proptest::strategy::Strategy<Value = Self>;
14 fn default_strategy() -> Self::Strategy;
17 macro_rules! impl_num {
19 impl DefaultStrategy for $type {
20 type Strategy = proptest::num::$type::Any;
21 fn default_strategy() -> Self::Strategy {
22 proptest::num::$type::ANY
41 #[cfg(not(target_arch = "wasm32"))]
42 impl DefaultStrategy for u128 {
43 type Strategy = proptest::num::u128::Any;
44 fn default_strategy() -> Self::Strategy {
45 proptest::num::u128::ANY
49 #[cfg(not(target_arch = "wasm32"))]
50 impl DefaultStrategy for i128 {
51 type Strategy = proptest::num::i128::Any;
52 fn default_strategy() -> Self::Strategy {
53 proptest::num::i128::ANY
57 #[cfg(target_arch = "wasm32")]
58 impl DefaultStrategy for u128 {
59 type Strategy = crate::wasm::u128::Any;
60 fn default_strategy() -> Self::Strategy {
61 crate::wasm::u128::ANY
65 #[cfg(target_arch = "wasm32")]
66 impl DefaultStrategy for i128 {
67 type Strategy = crate::wasm::i128::Any;
68 fn default_strategy() -> Self::Strategy {
69 crate::wasm::i128::ANY
73 impl<T: core::fmt::Debug + DefaultStrategy, const LANES: usize> DefaultStrategy for [T; LANES] {
74 type Strategy = crate::array::UniformArrayStrategy<T::Strategy, Self>;
75 fn default_strategy() -> Self::Strategy {
76 Self::Strategy::new(T::default_strategy())
81 pub fn make_runner() -> proptest::test_runner::TestRunner {
85 pub fn make_runner() -> proptest::test_runner::TestRunner {
86 // Only run a few tests on Miri
87 proptest::test_runner::TestRunner::new(proptest::test_runner::Config::with_cases(4))
90 /// Test a function that takes a single value.
91 pub fn test_1<A: core::fmt::Debug + DefaultStrategy>(
92 f: &dyn Fn(A) -> proptest::test_runner::TestCaseResult,
94 let mut runner = make_runner();
95 runner.run(&A::default_strategy(), f).unwrap();
98 /// Test a function that takes two values.
99 pub fn test_2<A: core::fmt::Debug + DefaultStrategy, B: core::fmt::Debug + DefaultStrategy>(
100 f: &dyn Fn(A, B) -> proptest::test_runner::TestCaseResult,
102 let mut runner = make_runner();
104 .run(&(A::default_strategy(), B::default_strategy()), |(a, b)| {
110 /// Test a function that takes two values.
112 A: core::fmt::Debug + DefaultStrategy,
113 B: core::fmt::Debug + DefaultStrategy,
114 C: core::fmt::Debug + DefaultStrategy,
116 f: &dyn Fn(A, B, C) -> proptest::test_runner::TestCaseResult,
118 let mut runner = make_runner();
122 A::default_strategy(),
123 B::default_strategy(),
124 C::default_strategy(),
126 |(a, b, c)| f(a, b, c),
131 /// Test a unary vector function against a unary scalar function, applied elementwise.
133 pub fn test_unary_elementwise<Scalar, ScalarResult, Vector, VectorResult, const LANES: usize>(
134 fv: &dyn Fn(Vector) -> VectorResult,
135 fs: &dyn Fn(Scalar) -> ScalarResult,
136 check: &dyn Fn([Scalar; LANES]) -> bool,
138 Scalar: Copy + Default + core::fmt::Debug + DefaultStrategy,
139 ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
140 Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy,
141 VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
143 test_1(&|x: [Scalar; LANES]| {
144 proptest::prop_assume!(check(x));
145 let result_1: [ScalarResult; LANES] = fv(x.into()).into();
146 let result_2: [ScalarResult; LANES] = {
147 let mut result = [ScalarResult::default(); LANES];
148 for (i, o) in x.iter().zip(result.iter_mut()) {
153 crate::prop_assert_biteq!(result_1, result_2);
158 /// Test a unary vector function against a unary scalar function, applied elementwise.
160 pub fn test_unary_mask_elementwise<Scalar, Vector, Mask, const LANES: usize>(
161 fv: &dyn Fn(Vector) -> Mask,
162 fs: &dyn Fn(Scalar) -> bool,
163 check: &dyn Fn([Scalar; LANES]) -> bool,
165 Scalar: Copy + Default + core::fmt::Debug + DefaultStrategy,
166 Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy,
167 Mask: Into<[bool; LANES]> + From<[bool; LANES]> + Copy,
169 test_1(&|x: [Scalar; LANES]| {
170 proptest::prop_assume!(check(x));
171 let result_1: [bool; LANES] = fv(x.into()).into();
172 let result_2: [bool; LANES] = {
173 let mut result = [false; LANES];
174 for (i, o) in x.iter().zip(result.iter_mut()) {
179 crate::prop_assert_biteq!(result_1, result_2);
184 /// Test a binary vector function against a binary scalar function, applied elementwise.
186 pub fn test_binary_elementwise<
195 fv: &dyn Fn(Vector1, Vector2) -> VectorResult,
196 fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult,
197 check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES]) -> bool,
199 Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy,
200 Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy,
201 ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
202 Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy,
203 Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy,
204 VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
206 test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| {
207 proptest::prop_assume!(check(x, y));
208 let result_1: [ScalarResult; LANES] = fv(x.into(), y.into()).into();
209 let result_2: [ScalarResult; LANES] = {
210 let mut result = [ScalarResult::default(); LANES];
211 for ((i1, i2), o) in x.iter().zip(y.iter()).zip(result.iter_mut()) {
216 crate::prop_assert_biteq!(result_1, result_2);
221 /// Test a binary vector-scalar function against a binary scalar function, applied elementwise.
223 pub fn test_binary_scalar_rhs_elementwise<
231 fv: &dyn Fn(Vector, Scalar2) -> VectorResult,
232 fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult,
233 check: &dyn Fn([Scalar1; LANES], Scalar2) -> bool,
235 Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy,
236 Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy,
237 ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
238 Vector: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy,
239 VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
241 test_2(&|x: [Scalar1; LANES], y: Scalar2| {
242 proptest::prop_assume!(check(x, y));
243 let result_1: [ScalarResult; LANES] = fv(x.into(), y).into();
244 let result_2: [ScalarResult; LANES] = {
245 let mut result = [ScalarResult::default(); LANES];
246 for (i, o) in x.iter().zip(result.iter_mut()) {
251 crate::prop_assert_biteq!(result_1, result_2);
256 /// Test a binary vector-scalar function against a binary scalar function, applied elementwise.
258 pub fn test_binary_scalar_lhs_elementwise<
266 fv: &dyn Fn(Scalar1, Vector) -> VectorResult,
267 fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult,
268 check: &dyn Fn(Scalar1, [Scalar2; LANES]) -> bool,
270 Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy,
271 Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy,
272 ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
273 Vector: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy,
274 VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
276 test_2(&|x: Scalar1, y: [Scalar2; LANES]| {
277 proptest::prop_assume!(check(x, y));
278 let result_1: [ScalarResult; LANES] = fv(x, y.into()).into();
279 let result_2: [ScalarResult; LANES] = {
280 let mut result = [ScalarResult::default(); LANES];
281 for (i, o) in y.iter().zip(result.iter_mut()) {
286 crate::prop_assert_biteq!(result_1, result_2);
291 /// Test a ternary vector function against a ternary scalar function, applied elementwise.
293 pub fn test_ternary_elementwise<
304 fv: &dyn Fn(Vector1, Vector2, Vector3) -> VectorResult,
305 fs: &dyn Fn(Scalar1, Scalar2, Scalar3) -> ScalarResult,
306 check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES], [Scalar3; LANES]) -> bool,
308 Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy,
309 Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy,
310 Scalar3: Copy + Default + core::fmt::Debug + DefaultStrategy,
311 ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
312 Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy,
313 Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy,
314 Vector3: Into<[Scalar3; LANES]> + From<[Scalar3; LANES]> + Copy,
315 VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
318 &|x: [Scalar1; LANES], y: [Scalar2; LANES], z: [Scalar3; LANES]| {
319 proptest::prop_assume!(check(x, y, z));
320 let result_1: [ScalarResult; LANES] = fv(x.into(), y.into(), z.into()).into();
321 let result_2: [ScalarResult; LANES] = {
322 let mut result = [ScalarResult::default(); LANES];
323 for ((i1, (i2, i3)), o) in
324 x.iter().zip(y.iter().zip(z.iter())).zip(result.iter_mut())
326 *o = fs(*i1, *i2, *i3);
330 crate::prop_assert_biteq!(result_1, result_2);
336 /// Expand a const-generic test into separate tests for each possible lane count.
338 macro_rules! test_lanes {
340 $(fn $test:ident<const $lanes:ident: usize>() $body:tt)*
346 fn implementation<const $lanes: usize>()
348 core_simd::LaneCount<$lanes>: core_simd::SupportedLaneCount,
351 #[cfg(target_arch = "wasm32")]
352 wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
355 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
357 implementation::<1>();
361 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
363 implementation::<2>();
367 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
369 implementation::<4>();
373 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
374 #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
376 implementation::<8>();
380 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
381 #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
383 implementation::<16>();
387 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
388 #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
390 implementation::<32>();
394 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
395 #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow
397 implementation::<64>();
404 /// Expand a const-generic `#[should_panic]` test into separate tests for each possible lane count.
406 macro_rules! test_lanes_panic {
408 $(fn $test:ident<const $lanes:ident: usize>() $body:tt)*
414 fn implementation<const $lanes: usize>()
416 core_simd::LaneCount<$lanes>: core_simd::SupportedLaneCount,
422 implementation::<1>();
428 implementation::<2>();
434 implementation::<4>();
440 implementation::<8>();
446 implementation::<16>();
452 implementation::<32>();
458 implementation::<64>();