From f06c78db5394e149316dfbb210aff6d6f0969a6c Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 25 Jun 2026 10:56:12 -0600 Subject: [PATCH 1/4] update and expand BoxedUint proptests Signed-off-by: Andrew Whitehead --- tests/boxed_uint.rs | 111 ++++++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 36 deletions(-) diff --git a/tests/boxed_uint.rs b/tests/boxed_uint.rs index 8398ecf8..c42b0654 100644 --- a/tests/boxed_uint.rs +++ b/tests/boxed_uint.rs @@ -6,14 +6,16 @@ mod common; use common::to_biguint; +use core::ops::Range; use crypto_bigint::{ BitOps, BoxedUint, CheckedAdd, Choice, ConcatenatingMul, ConcatenatingSquare, Gcd, Integer, - Limb, NonZero, Odd, Resize, + Limb, NonZero, Odd, Resize, Word, }; use num_bigint::BigUint; use num_integer::Integer as _; use num_modular::ModularUnaryOps; use num_traits::{Zero, identities::One}; +use proptest::collection::vec as propvec; use proptest::prelude::*; #[allow(clippy::cast_possible_truncation)] @@ -29,16 +31,42 @@ fn reduce(x: &BoxedUint, n: &NonZero) -> BoxedUint { x.rem_vartime(n) } -prop_compose! { - /// Generate a random `BoxedUint`. - fn uint()(mut bytes in any::>()) -> BoxedUint { - let extra = bytes.len() % Limb::BYTES; - let bytes_precision = bytes.len() - extra; - bytes.truncate(bytes_precision); - #[allow(clippy::cast_possible_truncation)] - BoxedUint::from_be_slice(&bytes, bytes_precision as u32 * 8).unwrap() - } +fn uint() -> impl Strategy { + sizeduint(1..8192) } + +fn sizeduint(bits_range: Range) -> impl Strategy { + let min_limbs = bits_range.start.max(1).div_ceil(Limb::BITS) as usize; + let max_limbs = bits_range.end.div_ceil(Limb::BITS) as usize; + let random_words = || propvec(any::(), min_limbs..max_limbs); + + let random = random_words().prop_map(BoxedUint::from_words); + let zero = bits_range.clone().prop_map(BoxedUint::zero_with_precision); + let single_bit = (bits_range.clone(), any::()).prop_map(|(bits, bit)| { + let mut uint = BoxedUint::zero_with_precision(bits); + uint.set_bit_vartime(bit % bits, true); + uint + }); + let low_bits = (random_words(), any::()).prop_map(|(words, bit)| { + let mut uint = BoxedUint::from_words(words); + uint.wrapping_shr_assign(bit); + uint + }); + let high_bits = (random_words(), any::()).prop_map(|(words, bit)| { + let mut uint = BoxedUint::from_words(words); + uint.wrapping_shl_assign(bit); + uint + }); + + prop_oneof![ + 6 => random, + 1 => zero, + 2 => single_bit, + 2 => low_bits, + 2 => high_bits, + ] +} + prop_compose! { /// Generate a pair of random `BoxedUint`s with the same precision. fn uint_pair()(a in uint(), b in uint()) -> (BoxedUint, BoxedUint) { @@ -46,14 +74,14 @@ prop_compose! { (a.resize(bits_precision), b.resize(bits_precision)) } } + prop_compose! { /// Generate a random odd modulus. - fn modulus()(n in uint()) -> Odd { + fn modulus()(mut n in uint()) -> Odd { if n.is_even().into() { - n.wrapping_add(Limb::ONE) - } else { - n - }.to_odd().expect("odd by construction") + n.wrapping_add_assign(Limb::ONE); + } + n.to_odd().expect("odd by construction") } } @@ -87,7 +115,7 @@ proptest! { } #[test] - fn checked_div((a, b) in uint_pair()) { + fn checked_div(a in uint(), b in uint()) { let actual = a.checked_div(&b); if b.is_zero().into() { @@ -132,7 +160,7 @@ proptest! { } #[test] - fn div_exact((a, mut b) in uint_pair()) { + fn div_exact(a in uint(), mut b in uint()) { if b.is_zero().into() { b = b.wrapping_add(Limb::ONE); } @@ -150,6 +178,7 @@ proptest! { } #[test] + // TODO: expand to f in uint(), g in uint() fn gcd((f, g) in uint_pair()) { let f_bi = to_biguint(&f); let g_bi = to_biguint(&g); @@ -220,11 +249,10 @@ proptest! { } #[test] - fn wrapping_pow(a in uint(), b in uint()) { + fn wrapping_pow(a in uint(), b in sizeduint(1..1024)) { let a_bi = to_biguint(&a); let b_bi = to_biguint(&b); let p_bi = to_biguint(&BoxedUint::max(a.bits_precision())) + 1u32; - println!("a: {a}, b: {b}, p: {p_bi}"); let expected = to_uint(a_bi.modpow(&b_bi, &p_bi)); @@ -234,7 +262,7 @@ proptest! { } #[test] - fn pow_mod(a in uint(), b in uint(), n in modulus()) { + fn pow_mod(a in uint(), b in sizeduint(1..1024), n in modulus()) { let a = reduce(&a, n.as_nz_ref()); let a_bi = to_biguint(&a); @@ -291,29 +319,29 @@ proptest! { } #[test] - fn rem((a, b) in uint_pair()) { - if bool::from(!b.is_zero()) { - let a_bi = to_biguint(&a); - let b_bi = to_biguint(&b); + fn rem(a in uint(), b in uint()) { + prop_assume!(b.is_nonzero().to_bool_vartime()); + + let a_bi = to_biguint(&a); + let b_bi = to_biguint(&b); - let expected = a_bi % b_bi; - let actual = a.rem(&NonZero::new(b).unwrap()); + let expected = a_bi % b_bi; + let actual = a.rem(&NonZero::new(b).unwrap()); - prop_assert_eq!(expected, to_biguint(&actual)); - } + prop_assert_eq!(expected, to_biguint(&actual)); } #[test] - fn rem_vartime((a, b) in uint_pair()) { - if bool::from(!b.is_zero()) { - let a_bi = to_biguint(&a); - let b_bi = to_biguint(&b); + fn rem_vartime(a in uint(), b in uint()) { + prop_assume!(b.is_nonzero().to_bool_vartime()); - let expected = a_bi % b_bi; - let actual = a.rem_vartime(&NonZero::new(b).unwrap()); + let a_bi = to_biguint(&a); + let b_bi = to_biguint(&b); - prop_assert_eq!(expected, to_biguint(&actual)); - } + let expected = a_bi % b_bi; + let actual = a.rem_vartime(&NonZero::new(b).unwrap()); + + prop_assert_eq!(expected, to_biguint(&actual)); } #[test] @@ -409,4 +437,15 @@ proptest! { let b = BoxedUint::from_le_slice_vartime(&a_bytes); prop_assert_eq!(a, b); } + + #[test] + fn floor_sqrt(a in uint()) { + let root = a.floor_sqrt(); + prop_assert_eq!(&root, &a.floor_sqrt_vartime()); + let checked_square = root.checked_square().into_option(); + prop_assert!(checked_square.is_some()); + prop_assert!(checked_square.unwrap() <= a); + let rtp = (root + Limb::ONE).saturating_square(); + prop_assert!(rtp > a || a.wrapping_add(Limb::ONE).is_zero().to_bool_vartime()); + } } From 922ac366b59a1b51ba21ddb754b86a6754454537 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 25 Jun 2026 10:57:56 -0600 Subject: [PATCH 2/4] update UintRef::div_exact, div_exact_vartime to handle edge cases around zero-valued limbs Signed-off-by: Andrew Whitehead --- src/uint/ref_type/div.rs | 122 +++++++++++++++++++++++++-------------- tests/uint.rs | 11 +--- 2 files changed, 81 insertions(+), 52 deletions(-) diff --git a/src/uint/ref_type/div.rs b/src/uint/ref_type/div.rs index 3cc467e3..2205b098 100644 --- a/src/uint/ref_type/div.rs +++ b/src/uint/ref_type/div.rs @@ -606,30 +606,28 @@ impl UintRef { /// If the divisor is zero. #[inline(always)] pub(crate) const fn div_exact(&mut self, rhs: &mut UintRef) -> Choice { - let x_prec = self.bits_precision(); let y_bits = rhs.bits(); assert!(y_bits > 0, "zero divisor"); - let tz = rhs.trailing_zeros(); - // Track whether there are more zeros in the divisor than bits in the dividend - let excess_z = Choice::from_u32_lt(x_prec, tz); - let tz = excess_z.select_u32(tz, x_prec); + let x_tz = self.trailing_zeros(); + let x_zero = Choice::from_u32_eq(x_tz, self.bits_precision()); + let y_tz = rhs.trailing_zeros(); // Shift the divisor such that it is odd - rhs.shr_assign(tz); + rhs.shr_assign(y_tz); - // Check that the dividend evenly divides by 2^tz, and shift it to match the divisor - let div2s_exact = self.ensure_trailing_zeros(tz).and(excess_z.not()); - self.unbounded_shr_assign(tz); + // Check that the dividend evenly divides by 2^y+tz, and shift it to match the divisor + let div2s_exact = Choice::from_u32_le(y_tz, x_tz).or(x_zero); + self.unbounded_shr_assign(y_tz); let y = Odd::new_ref_unchecked(rhs); let y_inv = y.invert_mod_limb(); - let ywords = bitlen::to_limbs(y_bits - tz); + let ywords = bitlen::to_limbs(y_bits - y_tz); let is_exact = Self::div_exact_odd_with_inverse::(self, y, y_inv, ywords).and(div2s_exact); // Restore the divisor - rhs.shl_assign(tz); + rhs.shl_assign(y_tz); is_exact } @@ -643,32 +641,28 @@ impl UintRef { /// If the divisor is zero. #[inline(always)] pub(crate) const fn div_exact_vartime(&mut self, rhs: &mut UintRef) -> Choice { - let x_prec = self.bits_precision(); let y_bits = rhs.bits_vartime(); assert!(y_bits > 0, "zero divisor"); - let tz = rhs.trailing_zeros_vartime(); - if tz > x_prec { - // The divisor exceeds the dividend precision. Short circuit based on public - // information (the divisor and the input size in limbs) - return Choice::FALSE; - } - // Reduce the divisor to its populated limbs and shift it such that it is odd - let rhs = rhs.leading_mut(bitlen::to_limbs(y_bits)); - rhs.unbounded_shr_assign_vartime(tz); + let x_tz = self.trailing_zeros(); + let x_zero = Choice::from_u32_eq(x_tz, self.bits_precision()); + let y_tz = rhs.trailing_zeros_vartime(); + + // Shift the divisor to be odd + rhs.unbounded_shr_assign_vartime(y_tz); - // Check that the dividend evenly divides by 2^tz, and shift it to match the divisor - let div2s_exact = self.ensure_trailing_zeros(tz); - self.unbounded_shr_assign_vartime(tz); + // Check that the dividend evenly divides by 2^y_tz, and shift it to match the divisor + let div2s_exact = Choice::from_u32_le(y_tz, x_tz).or(x_zero); + self.unbounded_shr_assign_vartime(y_tz); - let ywords = bitlen::to_limbs(y_bits - tz); - let y = Odd::new_ref_unchecked(rhs.leading(ywords)); + let ywords = bitlen::to_limbs(y_bits - y_tz); + let y = Odd::new_ref_unchecked(rhs.leading_mut(ywords)); let y_inv = y.invert_mod_limb(); let is_exact = Self::div_exact_odd_with_inverse::(self, y, y_inv, ywords).and(div2s_exact); // Restore the divisor - rhs.unbounded_shl_assign_vartime(tz); + rhs.unbounded_shl_assign_vartime(y_tz); is_exact } @@ -696,6 +690,7 @@ impl UintRef { let y = y.as_ref(); let yc = y.nlimbs(); let mut meta_carry = Limb::ZERO; + let mut zero_hi = Choice::TRUE; let mut xi = 0; while xi < xc { @@ -703,15 +698,18 @@ impl UintRef { // This loop is a no-op once there are fewer words remaining than the size of the divisor let done = usize_lt(y_remain, ywords); if VARTIME && done.to_bool_vartime() { - // Set the upper limbs to zero - x.trailing_mut(xi).fill(Limb::ZERO); + zero_hi = x.trailing(xi).is_zero(); break; } // Compute the quotient limb that will clear the low dividend limb - let quo = Limb::select(x.limbs[xi].wrapping_mul(y_inv), Limb::ZERO, done); + let quo = Limb::select(x.limbs[xi].wrapping_mul(y_inv), x.limbs[xi], done); x.limbs[xi] = quo; + if !VARTIME { + zero_hi = zero_hi.and(Limb::select(Limb::ZERO, quo, done).is_zero()); + } + let (_, mut carry) = quo.widening_mul(y.limbs[0]); let mut sub; let mut borrow = Limb::ZERO; @@ -735,20 +733,60 @@ impl UintRef { xi += 1; } - meta_carry.is_zero() + meta_carry.is_zero().and(zero_hi) } +} - // Check that `self` can be cleanly divided by 2^zs: the bottom zs bits are zero. - #[inline(always)] - const fn ensure_trailing_zeros(&self, zs: u32) -> Choice { - let z_words = (zs >> Limb::LOG2_BITS) as usize; - let z_bits = zs & (Limb::BITS - 1); - if z_words >= self.nlimbs() { - self.is_zero() - } else { - self.leading(z_words) - .is_zero() - .and(self.limbs[z_words].restrict_bits(z_bits).is_zero()) +#[cfg(test)] +mod tests { + use crate::{U64, U128, U192, Uint}; + + #[test] + fn div_exact_inexact() { + fn check(lhs: Uint, rhs: Uint, exact: bool) { + let (mut q, mut r) = (lhs, rhs); + let actual = q + .as_mut_uint_ref() + .div_exact(r.as_mut_uint_ref()) + .to_bool_vartime(); + assert_eq!(actual, exact, "{lhs} / {rhs}: exact={actual}"); + let (mut q, mut r) = (lhs, rhs); + let actual = q + .as_mut_uint_ref() + .div_exact_vartime(r.as_mut_uint_ref()) + .to_bool_vartime(); + assert_eq!(actual, exact, "{lhs} / {rhs}: exact={actual}"); } + + check( + U64::from_be_hex("0000000000000010"), + U64::from_be_hex("0000000000000010"), + true, + ); + check( + U64::from_be_hex("0000000000000010"), + U128::from_be_hex("00000000000000000000000000000001"), + true, + ); + check( + U64::from_be_hex("0000000000000000"), + U128::from_be_hex("10000000000000000000000000000000"), + true, + ); + check( + U64::from_be_hex("0000000000000001"), + U64::from_be_hex("0000000000000010"), + false, + ); + check( + U64::from_be_hex("0000000000000001"), + U128::from_be_hex("00000000000000100000000000000000"), + false, + ); + check( + U192::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000"), + U192::from_be_hex("000000000000000100000000000000003ACEDC010F13471D"), + false, + ); } } diff --git a/tests/uint.rs b/tests/uint.rs index aee42e53..f82285ae 100644 --- a/tests/uint.rs +++ b/tests/uint.rs @@ -8,7 +8,7 @@ mod common; use common::to_biguint; use core::mem; use crypto_bigint::{ - Encoding, Limb, NonZero, Odd, U128, U256, U512, U4096, U8192, Uint, Word, + Encoding, Limb, NonZero, Odd, U256, U512, U4096, U8192, Uint, Word, modular::{FixedMontyForm, FixedMontyParams}, }; use num_bigint::BigUint; @@ -617,12 +617,3 @@ proptest! { prop_assert_eq!(expected, actual); } } - -#[test] -fn div_exact_wide_power_of_two_divisor_is_inexact() { - let lhs = U128::ONE; - let rhs = NonZero::new(U256::ONE << U128::BITS).unwrap(); - - assert!(bool::from(lhs.div_exact(&rhs).is_none())); - assert!(bool::from(lhs.div_exact_vartime(&rhs).is_none())); -} From 87224457ad53c1485fddc0cfc4aa18dbd1f52878 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 25 Jun 2026 12:12:19 -0600 Subject: [PATCH 3/4] reduce frequency of large BoxedUints in proptests Signed-off-by: Andrew Whitehead --- tests/boxed_uint.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tests/boxed_uint.rs b/tests/boxed_uint.rs index c42b0654..803b3e7c 100644 --- a/tests/boxed_uint.rs +++ b/tests/boxed_uint.rs @@ -32,19 +32,29 @@ fn reduce(x: &BoxedUint, n: &NonZero) -> BoxedUint { } fn uint() -> impl Strategy { - sizeduint(1..8192) + prop_oneof![ + 9 => uint_bits(1..1024), + 1 => uint_bits(1024..8192), + ] } -fn sizeduint(bits_range: Range) -> impl Strategy { +fn uint_bits(bits_range: Range) -> impl Strategy { let min_limbs = bits_range.start.max(1).div_ceil(Limb::BITS) as usize; let max_limbs = bits_range.end.div_ceil(Limb::BITS) as usize; - let random_words = || propvec(any::(), min_limbs..max_limbs); + uint_limbs(min_limbs..max_limbs) +} + +#[allow(clippy::cast_possible_truncation)] +fn uint_limbs(limbs_range: Range) -> impl Strategy { + let random_words = || propvec(any::(), limbs_range.clone()); let random = random_words().prop_map(BoxedUint::from_words); - let zero = bits_range.clone().prop_map(BoxedUint::zero_with_precision); - let single_bit = (bits_range.clone(), any::()).prop_map(|(bits, bit)| { - let mut uint = BoxedUint::zero_with_precision(bits); - uint.set_bit_vartime(bit % bits, true); + let zero = limbs_range + .clone() + .prop_map(|l| BoxedUint::zero_with_precision(l as u32 * Limb::BITS)); + let single_bit = (limbs_range.clone(), any::()).prop_map(|(l, bit)| { + let mut uint = BoxedUint::zero_with_precision(l as u32 * Limb::BITS); + uint.set_bit_vartime(bit % uint.bits_precision(), true); uint }); let low_bits = (random_words(), any::()).prop_map(|(words, bit)| { @@ -249,7 +259,7 @@ proptest! { } #[test] - fn wrapping_pow(a in uint(), b in sizeduint(1..1024)) { + fn wrapping_pow(a in uint(), b in uint_bits(1..1024)) { let a_bi = to_biguint(&a); let b_bi = to_biguint(&b); let p_bi = to_biguint(&BoxedUint::max(a.bits_precision())) + 1u32; @@ -262,7 +272,7 @@ proptest! { } #[test] - fn pow_mod(a in uint(), b in sizeduint(1..1024), n in modulus()) { + fn pow_mod(a in uint(), b in uint_bits(1..1024), n in modulus()) { let a = reduce(&a, n.as_nz_ref()); let a_bi = to_biguint(&a); From 65f40c8231cf407feaa66546f3423ffde4a9ee25 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 25 Jun 2026 14:07:23 -0600 Subject: [PATCH 4/4] additional test cleanups Signed-off-by: Andrew Whitehead --- tests/boxed_uint.rs | 77 +++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/tests/boxed_uint.rs b/tests/boxed_uint.rs index 803b3e7c..6f0998fc 100644 --- a/tests/boxed_uint.rs +++ b/tests/boxed_uint.rs @@ -8,8 +8,8 @@ mod common; use common::to_biguint; use core::ops::Range; use crypto_bigint::{ - BitOps, BoxedUint, CheckedAdd, Choice, ConcatenatingMul, ConcatenatingSquare, Gcd, Integer, - Limb, NonZero, Odd, Resize, Word, + BitOps, BoxedUint, CheckedAdd, ConcatenatingMul, ConcatenatingSquare, Gcd, Integer, Limb, + NonZero, Odd, Resize, Word, }; use num_bigint::BigUint; use num_integer::Integer as _; @@ -78,20 +78,26 @@ fn uint_limbs(limbs_range: Range) -> impl Strategy { } prop_compose! { - /// Generate a pair of random `BoxedUint`s with the same precision. - fn uint_pair()(a in uint(), b in uint()) -> (BoxedUint, BoxedUint) { - let bits_precision = core::cmp::max(a.bits_precision(), b.bits_precision()); - (a.resize(bits_precision), b.resize(bits_precision)) + fn nonzero_uint()(mut val in uint()) -> NonZero { + if val.is_zero().to_bool_vartime() { + val.set_one(); + } + val.into_nz().unwrap() } } prop_compose! { - /// Generate a random odd modulus. - fn modulus()(mut n in uint()) -> Odd { - if n.is_even().into() { - n.wrapping_add_assign(Limb::ONE); - } - n.to_odd().expect("odd by construction") + fn odd_uint()(mut val in uint()) -> Odd { + val.set_bit_vartime(0, true); + val.into_odd().unwrap() + } +} + +prop_compose! { + /// Generate a pair of random `BoxedUint`s with the same precision. + fn uint_pair()(a in uint(), b in uint()) -> (BoxedUint, BoxedUint) { + let bits_precision = core::cmp::max(a.bits_precision(), b.bits_precision()); + (a.resize(bits_precision), b.resize(bits_precision)) } } @@ -150,40 +156,30 @@ proptest! { } #[test] - fn div_rem(a in uint(), mut b in uint()) { - if b.is_zero().into() { - b = b.wrapping_add(Limb::ONE); - } - + fn div_rem(a in uint(), b in nonzero_uint()) { let a_bi = to_biguint(&a); - let b_bi = to_biguint(&b); + let b_bi = to_biguint(b.as_ref()); let (expected_quotient, expected_remainder) = a_bi.div_rem(&b_bi); - let div = NonZero::new(b).unwrap(); - let (actual_quotient, actual_remainder) = a.div_rem(&div); + let (actual_quotient, actual_remainder) = a.div_rem(&b); prop_assert_eq!(expected_quotient, to_biguint(&actual_quotient)); prop_assert_eq!(expected_remainder, to_biguint(&actual_remainder)); - let (quotient_vartime, remainder_vartime) = a.div_rem_vartime(&div); + let (quotient_vartime, remainder_vartime) = a.div_rem_vartime(&b); prop_assert_eq!(actual_quotient, quotient_vartime); prop_assert_eq!(actual_remainder, remainder_vartime); } #[test] - fn div_exact(a in uint(), mut b in uint()) { - if b.is_zero().into() { - b = b.wrapping_add(Limb::ONE); - } - + fn div_exact(a in uint(), b in nonzero_uint()) { let a_bi = to_biguint(&a); - let b_bi = to_biguint(&b); + let b_bi = to_biguint(b.as_ref()); let (expected_quotient, expected_remainder) = a_bi.div_rem(&b_bi); let expected = if expected_remainder.is_zero() { Some(expected_quotient) } else { None }; - let div = NonZero::new(b).unwrap(); - let actual = a.div_exact(&div).into_option(); + let actual = a.div_exact(&b).into_option(); prop_assert_eq!(&expected, &actual.as_ref().map(to_biguint)); - let actual_vartime = a.div_exact_vartime(&div).into_option(); + let actual_vartime = a.div_exact_vartime(&b).into_option(); prop_assert_eq!(expected, actual_vartime.as_ref().map(to_biguint)); } @@ -199,8 +195,7 @@ proptest! { } #[test] - fn invert_mod2k(mut a in uint(), k in any::()) { - a.set_bit(0, Choice::TRUE); // make odd + fn invert_mod2k(a in odd_uint(), k in any::()) { let k = k % (a.bits() + 1); let a_bi = to_biguint(&a); let m_bi = BigUint::one() << k as usize; @@ -245,7 +240,7 @@ proptest! { } #[test] - fn mul_mod(a in uint(), b in uint(), n in modulus()) { + fn mul_mod(a in uint(), b in uint(), n in odd_uint()) { let a = reduce(&a, n.as_nz_ref()); let b = reduce(&b, n.as_nz_ref()); @@ -272,7 +267,7 @@ proptest! { } #[test] - fn pow_mod(a in uint(), b in uint_bits(1..1024), n in modulus()) { + fn pow_mod(a in uint(), b in uint_bits(1..1024), n in odd_uint()) { let a = reduce(&a, n.as_nz_ref()); let a_bi = to_biguint(&a); @@ -329,27 +324,25 @@ proptest! { } #[test] - fn rem(a in uint(), b in uint()) { - prop_assume!(b.is_nonzero().to_bool_vartime()); - + fn rem(a in uint(), b in nonzero_uint()) { let a_bi = to_biguint(&a); - let b_bi = to_biguint(&b); + let b_bi = to_biguint(b.as_ref()); let expected = a_bi % b_bi; - let actual = a.rem(&NonZero::new(b).unwrap()); + let actual = a.rem(&b); prop_assert_eq!(expected, to_biguint(&actual)); } #[test] - fn rem_vartime(a in uint(), b in uint()) { + fn rem_vartime(a in uint(), b in nonzero_uint()) { prop_assume!(b.is_nonzero().to_bool_vartime()); let a_bi = to_biguint(&a); - let b_bi = to_biguint(&b); + let b_bi = to_biguint(b.as_ref()); let expected = a_bi % b_bi; - let actual = a.rem_vartime(&NonZero::new(b).unwrap()); + let actual = a.rem_vartime(&b); prop_assert_eq!(expected, to_biguint(&actual)); }