diff --git a/ci/big_quickcheck/src/lib.rs b/ci/big_quickcheck/src/lib.rs index 4db72f8f..4e0e798f 100644 --- a/ci/big_quickcheck/src/lib.rs +++ b/ci/big_quickcheck/src/lib.rs @@ -8,9 +8,10 @@ use num_bigint::{BigInt, BigUint}; use num_integer::Integer; -use num_traits::{Num, One, Signed, Zero}; -use quickcheck::{Gen, QuickCheck, TestResult}; +use num_traits::{Num, One, Signed, ToPrimitive, Zero}; +use quickcheck::{Arbitrary, Gen, QuickCheck, TestResult}; use quickcheck_macros::quickcheck; +use std::{fmt, ops::BitOr}; #[quickcheck] fn quickcheck_unsigned_eq_reflexive(a: BigUint) -> bool { @@ -357,3 +358,38 @@ fn quickcheck_modpow() { qc.quickcheck(test_modpow as fn(i128, u128, i128) -> TestResult); } + +#[derive(Clone, Copy)] +struct SparseU128(u128); + +impl fmt::Debug for SparseU128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SparseU128") + .field(&format_args!("{:#x}", self.0)) + .finish() + } +} + +// Generates a value with only a few bits set to test rounding +impl Arbitrary for SparseU128 { + fn arbitrary(gen: &mut Gen) -> Self { + let (a0, a1, a2, a3) = <_>::arbitrary(gen); + let value = [a0, a1, a2, a3] + .iter() + .map(|p: &u32| 1 << (p % 128)) + .fold(0, u128::bitor); + SparseU128(value) + } +} + +// Check for consistency of conversion to float with u128 + +#[quickcheck] +fn quickcheck_to_f32_through_u128(value: SparseU128) -> bool { + BigInt::from(value.0).to_f32() == Some(value.0 as f32) +} + +#[quickcheck] +fn quickcheck_to_f64_through_u128(value: SparseU128) -> bool { + BigInt::from(value.0).to_f64() == Some(value.0 as f64) +}