Add documentation

This commit is contained in:
Caleb Zulawski 2021-02-13 15:58:44 -05:00
parent 714ad639b3
commit 8c378d3027
8 changed files with 36 additions and 126 deletions

View file

@ -1,120 +0,0 @@
pub(crate) trait BitEq {
fn biteq(&self, other: &Self) -> bool;
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result;
}
macro_rules! impl_biteq {
{ integer impl BitEq for $($type:ty,)* } => {
$(
impl BitEq for $type {
fn biteq(&self, other: &Self) -> bool {
self == other
}
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{:?} ({:x})", self, self)
}
}
)*
};
{ float impl BitEq for $($type:ty,)* } => {
$(
impl BitEq for $type {
fn biteq(&self, other: &Self) -> bool {
self.to_bits() == other.to_bits()
}
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{:?} ({:x})", self, self.to_bits())
}
}
)*
};
{ vector impl BitEq for $($type:ty,)* } => {
$(
impl BitEq for $type {
fn biteq(&self, other: &Self) -> bool {
let a: &[_] = self.as_ref();
let b: &[_] = other.as_ref();
if a.len() == b.len() {
a.iter().zip(b.iter()).fold(true, |value, (left, right)| {
value && left.biteq(right)
})
} else {
false
}
}
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
#[repr(transparent)]
struct Wrapper<'a, T: BitEq>(&'a T);
impl<T: BitEq> core::fmt::Debug for Wrapper<'_, T> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
self.0.fmt(f)
}
}
let slice: &[_] = self.as_ref();
f.debug_list()
.entries(slice.iter().map(|x| Wrapper(x)))
.finish()
}
}
)*
};
}
impl_biteq! {
integer impl BitEq for
u8, u16, u32, u64, u128, usize,
i8, i16, i32, i64, i128, isize,
}
impl_biteq! {
float impl BitEq for f32, f64,
}
impl_biteq! {
vector impl BitEq for
core_simd::u8x8, core_simd::u8x16, core_simd::u8x32, core_simd::u8x64,
core_simd::i8x8, core_simd::i8x16, core_simd::i8x32, core_simd::i8x64,
core_simd::u16x4, core_simd::u16x8, core_simd::u16x16, core_simd::u16x32,
core_simd::i16x4, core_simd::i16x8, core_simd::i16x16, core_simd::i16x32,
core_simd::u32x2, core_simd::u32x4, core_simd::u32x8, core_simd::u32x16,
core_simd::i32x2, core_simd::i32x4, core_simd::i32x8, core_simd::i32x16,
core_simd::u64x2, core_simd::u64x4, core_simd::u64x8,
core_simd::i64x2, core_simd::i64x4, core_simd::i64x8,
core_simd::u128x2, core_simd::u128x4,
core_simd::i128x2, core_simd::i128x4,
core_simd::usizex2, core_simd::usizex4, core_simd::usizex8,
core_simd::isizex2, core_simd::isizex4, core_simd::isizex8,
core_simd::f32x2, core_simd::f32x4, core_simd::f32x8, core_simd::f32x16,
core_simd::f64x2, core_simd::f64x4, core_simd::f64x8,
}
pub(crate) struct BitEqWrapper<'a, T>(pub(crate) &'a T);
impl<T: BitEq> PartialEq for BitEqWrapper<'_, T> {
fn eq(&self, other: &Self) -> bool {
self.0.biteq(other.0)
}
}
impl<T: BitEq> core::fmt::Debug for BitEqWrapper<'_, T> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
self.0.fmt(f)
}
}
macro_rules! assert_biteq {
{ $a:expr, $b:expr } => {
{
use helpers::biteq::BitEqWrapper;
let a = $a;
let b = $b;
assert_eq!(BitEqWrapper(&a), BitEqWrapper(&b));
}
}
}

View file

@ -1,2 +0,0 @@
#[macro_use]
pub mod biteq;

View file

@ -1,7 +1,3 @@
#[macro_use]
#[path = "../helpers/mod.rs"]
mod helpers;
#[macro_use]
mod mask_macros;

View file

@ -1,3 +1,6 @@
/// Implements a test on a unary operation using proptest.
///
/// Compares the vector operation to the equivalent scalar operation.
#[macro_export]
macro_rules! impl_unary_op_test {
{ $vector:ty, $scalar:ty, $trait:ident :: $fn:ident, $scalar_fn:expr } => {
@ -16,6 +19,9 @@ macro_rules! impl_unary_op_test {
};
}
/// Implements a test on a binary operation using proptest.
///
/// Compares the vector operation to the equivalent scalar operation.
#[macro_export]
macro_rules! impl_binary_op_test {
{ $vector:ty, $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $scalar_fn:expr } => {
@ -70,6 +76,12 @@ macro_rules! impl_binary_op_test {
};
}
/// Implements a test on a binary operation using proptest.
///
/// Like `impl_binary_op_test`, but allows providing a function for rejecting particular inputs
/// (like the `proptest_assume` macro).
///
/// Compares the vector operation to the equivalent scalar operation.
#[macro_export]
macro_rules! impl_binary_checked_op_test {
{ $vector:ty, $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $scalar_fn:expr, $check_fn:expr } => {
@ -124,6 +136,7 @@ macro_rules! impl_binary_checked_op_test {
};
}
/// Implement tests for signed integers.
#[macro_export]
macro_rules! impl_signed_tests {
{ $vector:ident, $scalar:tt } => {
@ -191,6 +204,8 @@ macro_rules! impl_signed_tests {
impl_binary_op_test!(Vector<LANES>, Scalar, Add::add, AddAssign::add_assign, Scalar::wrapping_add);
impl_binary_op_test!(Vector<LANES>, Scalar, Sub::sub, SubAssign::sub_assign, Scalar::wrapping_sub);
impl_binary_op_test!(Vector<LANES>, Scalar, Mul::mul, MulAssign::mul_assign, Scalar::wrapping_mul);
// Exclude Div and Rem panicking cases
impl_binary_checked_op_test!(Vector<LANES>, Scalar, Div::div, DivAssign::div_assign, Scalar::wrapping_div, |x, y| y != 0 && !(x == Scalar::MIN && y == -1));
impl_binary_checked_op_test!(Vector<LANES>, Scalar, Rem::rem, RemAssign::rem_assign, Scalar::wrapping_rem, |x, y| y != 0 && !(x == Scalar::MIN && y == -1));
@ -202,6 +217,7 @@ macro_rules! impl_signed_tests {
}
}
/// Implement tests for unsigned integers.
#[macro_export]
macro_rules! impl_unsigned_tests {
{ $vector:ident, $scalar:tt } => {
@ -220,6 +236,8 @@ macro_rules! impl_unsigned_tests {
impl_binary_op_test!(Vector<LANES>, Scalar, Add::add, AddAssign::add_assign, Scalar::wrapping_add);
impl_binary_op_test!(Vector<LANES>, Scalar, Sub::sub, SubAssign::sub_assign, Scalar::wrapping_sub);
impl_binary_op_test!(Vector<LANES>, Scalar, Mul::mul, MulAssign::mul_assign, Scalar::wrapping_mul);
// Exclude Div and Rem panicking cases
impl_binary_checked_op_test!(Vector<LANES>, Scalar, Div::div, DivAssign::div_assign, Scalar::wrapping_div, |_, y| y != 0);
impl_binary_checked_op_test!(Vector<LANES>, Scalar, Rem::rem, RemAssign::rem_assign, Scalar::wrapping_rem, |_, y| y != 0);
@ -231,6 +249,7 @@ macro_rules! impl_unsigned_tests {
}
}
/// Implement tests for floating point numbers.
#[macro_export]
macro_rules! impl_float_tests {
{ $vector:ident, $scalar:tt, $int_scalar:tt } => {

View file

@ -1,3 +1,5 @@
//! Generic-length array strategy.
// Adapted from proptest's array code
// Copyright 2017 Jason Lingle

View file

@ -1,3 +1,5 @@
//! Compare numeric types by exact bit value.
pub trait BitEq {
fn biteq(&self, other: &Self) -> bool;
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result;

View file

@ -6,6 +6,9 @@ pub mod wasm;
#[macro_use]
pub mod biteq;
/// Specifies the default strategy for testing a type.
///
/// This strategy should be what "makes sense" to test.
pub trait DefaultStrategy {
type Strategy: proptest::strategy::Strategy<Value = Self>;
fn default_strategy() -> Self::Strategy;
@ -74,6 +77,7 @@ impl<T: core::fmt::Debug + DefaultStrategy, const LANES: usize> DefaultStrategy
}
}
/// Test a function that takes a single value.
pub fn test_1<A: core::fmt::Debug + DefaultStrategy>(
f: &dyn Fn(A) -> proptest::test_runner::TestCaseResult,
) {
@ -81,6 +85,7 @@ pub fn test_1<A: core::fmt::Debug + DefaultStrategy>(
runner.run(&A::default_strategy(), f).unwrap();
}
/// Test a function that takes two values.
pub fn test_2<A: core::fmt::Debug + DefaultStrategy, B: core::fmt::Debug + DefaultStrategy>(
f: &dyn Fn(A, B) -> proptest::test_runner::TestCaseResult,
) {
@ -92,6 +97,7 @@ pub fn test_2<A: core::fmt::Debug + DefaultStrategy, B: core::fmt::Debug + Defau
.unwrap();
}
/// Test a unary vector function against a unary scalar function, applied elementwise.
#[inline(never)]
pub fn test_unary_elementwise<Scalar, ScalarResult, Vector, VectorResult, const LANES: usize>(
fv: &dyn Fn(Vector) -> VectorResult,
@ -118,6 +124,7 @@ pub fn test_unary_elementwise<Scalar, ScalarResult, Vector, VectorResult, const
});
}
/// Test a binary vector function against a binary scalar function, applied elementwise.
#[inline(never)]
pub fn test_binary_elementwise<
Scalar1,
@ -154,6 +161,7 @@ pub fn test_binary_elementwise<
});
}
/// Test a binary vector-scalar function against a binary scalar function, applied elementwise.
#[inline(never)]
pub fn test_binary_scalar_rhs_elementwise<
Scalar1,
@ -188,6 +196,7 @@ pub fn test_binary_scalar_rhs_elementwise<
});
}
/// Test a binary vector-scalar function against a binary scalar function, applied elementwise.
#[inline(never)]
pub fn test_binary_scalar_lhs_elementwise<
Scalar1,
@ -222,6 +231,7 @@ pub fn test_binary_scalar_lhs_elementwise<
});
}
/// Expand a const-generic test into separate tests for each possible lane count.
#[macro_export]
macro_rules! test_lanes {
{
@ -282,6 +292,7 @@ macro_rules! test_lanes {
}
}
/// Expand a const-generic `#[should_panic]` test into separate tests for each possible lane count.
#[macro_export]
macro_rules! test_lanes_panic {
{

View file

@ -1,3 +1,5 @@
//! Strategies for `u128` and `i128`, since proptest doesn't provide them for the wasm target.
macro_rules! impl_num {
{ $name:ident } => {
pub(crate) mod $name {