From 34a5941ee9b5db59c2b76be5e107cfb8bb4cab0c Mon Sep 17 00:00:00 2001 From: nicoo Date: Mon, 3 Aug 2020 14:00:34 +0200 Subject: [PATCH] factor::numeric: Add more property-based tests (#1577) * factor::numeric::gcd: Rename test against the Euclidean algorithm * factor::numeric::gcd: Add various property-based tests * factor::numeric::modular_inverse: Rename test * factor::numeric::modular_inverse: Add test on random values --- src/uu/factor/src/numeric/gcd.rs | 35 ++++++++++++++++++-- src/uu/factor/src/numeric/modular_inverse.rs | 17 ++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/uu/factor/src/numeric/gcd.rs b/src/uu/factor/src/numeric/gcd.rs index 54067c56e..0cde65472 100644 --- a/src/uu/factor/src/numeric/gcd.rs +++ b/src/uu/factor/src/numeric/gcd.rs @@ -51,7 +51,7 @@ mod tests { use quickcheck::quickcheck; quickcheck! { - fn gcd(a: u64, b: u64) -> bool { + fn euclidean(a: u64, b: u64) -> bool { // Test against the Euclidean algorithm let g = { let (mut a, mut b) = (a, b); @@ -61,7 +61,38 @@ mod tests { } a }; - super::gcd(a, b) == g + gcd(a, b) == g + } + + fn one(a: u64) -> bool { + gcd(1, a) == 1 + } + + fn divisor(a: u64, b: u64) -> bool { + // Test that gcd(a, b) divides a and b + let g = gcd(a, b); + a % g == 0 && b % g == 0 + } + + fn commutative(a: u64, b: u64) -> bool { + gcd(a, b) == gcd(b, a) + } + + fn associative(a: u64, b: u64, c: u64) -> bool { + gcd(a, gcd(b, c)) == gcd(gcd(a, b), c) + } + + fn scalar_mult(a: u64, b: u64, k: u64) -> bool { + gcd(k * a, k * b) == k * gcd(a, b) + } + + fn multiplicative(a: u64, b: u64, c: u64) -> bool { + // gcd(ab, c) = gcd(a, c) gcd(b, c) when a and b coprime + gcd(a, b) != 1 || gcd(a * b, c) == gcd(a, c) * gcd(b, c) + } + + fn linearity(a: u64, b: u64, k: u64) -> bool { + gcd(a + k * b, b) == gcd(a, b) } } } diff --git a/src/uu/factor/src/numeric/modular_inverse.rs b/src/uu/factor/src/numeric/modular_inverse.rs index 5310a1886..763ee90a0 100644 --- a/src/uu/factor/src/numeric/modular_inverse.rs +++ b/src/uu/factor/src/numeric/modular_inverse.rs @@ -47,8 +47,9 @@ pub(crate) fn modular_inverse(a: T) -> T { mod tests { use super::{super::traits::Int, *}; use crate::parametrized_check; + use quickcheck::quickcheck; - fn test_inverter() { + fn small_values() { // All odd integers from 1 to 20 000 let one = T::from(1).unwrap(); let two = T::from(2).unwrap(); @@ -58,5 +59,17 @@ mod tests { assert!(test_values.all(|x| x.wrapping_mul(&modular_inverse(x)) == one)); } - parametrized_check!(test_inverter); + parametrized_check!(small_values); + + quickcheck! { + fn random_values_u32(n: u32) -> bool { + let n = 2 * n + 1; + modular_inverse(n).wrapping_mul(n) == 1 + } + + fn random_values_u64(n: u64) -> bool { + let n = 2 * n + 1; + modular_inverse(n).wrapping_mul(n) == 1 + } + } }