#![cfg(feature = "quickcheck")] #![cfg(feature = "quickcheck_macros")] extern crate num_bigint; extern crate num_integer; extern crate num_traits; extern crate quickcheck; #[macro_use] extern crate quickcheck_macros; use num_bigint::{BigInt, BigUint}; use num_traits::{Num, One, Pow, Zero}; use quickcheck::{QuickCheck, StdThreadGen, TestResult}; #[quickcheck] fn quickcheck_unsigned_eq_reflexive(a: BigUint) -> bool { a == a } #[quickcheck] fn quickcheck_signed_eq_reflexive(a: BigInt) -> bool { a == a } #[quickcheck] fn quickcheck_unsigned_eq_symmetric(a: BigUint, b: BigUint) -> bool { if a == b { b == a } else { b != a } } #[quickcheck] fn quickcheck_signed_eq_symmetric(a: BigInt, b: BigInt) -> bool { if a == b { b == a } else { b != a } } #[test] fn quickcheck_arith_primitive() { let gen = StdThreadGen::new(usize::max_value()); let mut qc = QuickCheck::with_gen(gen); fn test_unsigned_add_primitive(a: usize, b: usize) -> TestResult { let actual = BigUint::from(a) + BigUint::from(b); match a.checked_add(b) { None => TestResult::discard(), Some(expected) => TestResult::from_bool(BigUint::from(expected) == actual), } } fn test_signed_add_primitive(a: isize, b: isize) -> TestResult { let actual = BigInt::from(a) + BigInt::from(b); match a.checked_add(b) { None => TestResult::discard(), Some(expected) => TestResult::from_bool(BigInt::from(expected) == actual), } } fn test_unsigned_mul_primitive(a: u64, b: u64) -> bool { //maximum value of u64 means no overflow BigUint::from(a as u128 * b as u128) == BigUint::from(a) * BigUint::from(b) } fn test_signed_mul_primitive(a: i64, b: i64) -> bool { //maximum value of i64 means no overflow BigInt::from(a as i128 * b as i128) == BigInt::from(a) * BigInt::from(b) } fn test_unsigned_sub_primitive(a: u128, b: u128) -> bool { if b < a { BigUint::from(a - b) == BigUint::from(a) - BigUint::from(b) } else { BigUint::from(b - a) == BigUint::from(b) - BigUint::from(a) } } fn test_signed_sub_primitive(a: i128, b: i128) -> bool { if b < a { BigInt::from(a - b) == BigInt::from(a) - BigInt::from(b) } else { BigInt::from(b - a) == BigInt::from(b) - BigInt::from(a) } } fn test_unsigned_div_primitive(a: u128, b: u128) -> TestResult { if b == 0 { TestResult::discard() } else { TestResult::from_bool(BigUint::from(a / b) == BigUint::from(a) / BigUint::from(b)) } } fn test_signed_div_primitive(a: i128, b: i128) -> TestResult { if b == 0 { TestResult::discard() } else { TestResult::from_bool(BigInt::from(a / b) == BigInt::from(a) / BigInt::from(b)) } } qc.quickcheck(test_unsigned_add_primitive as fn(usize, usize) -> TestResult); qc.quickcheck(test_signed_add_primitive as fn(isize, isize) -> TestResult); qc.quickcheck(test_unsigned_mul_primitive as fn(u64, u64) -> bool); qc.quickcheck(test_signed_mul_primitive as fn(i64, i64) -> bool); qc.quickcheck(test_unsigned_sub_primitive as fn(u128, u128) -> bool); qc.quickcheck(test_signed_sub_primitive as fn(i128, i128) -> bool); qc.quickcheck(test_unsigned_div_primitive as fn(u128, u128) -> TestResult); qc.quickcheck(test_signed_div_primitive as fn(i128, i128) -> TestResult); } #[quickcheck] fn quickcheck_unsigned_add_commutative(a: BigUint, b: BigUint) -> bool { &a + &b == b + a } #[quickcheck] fn quickcheck_signed_add_commutative(a: BigInt, b: BigInt) -> bool { &a + &b == b + a } #[quickcheck] fn quickcheck_unsigned_add_zero(a: BigUint) -> bool { a == &a + BigUint::zero() } #[quickcheck] fn quickcheck_signed_add_zero(a: BigInt) -> bool { a == &a + BigInt::zero() } #[quickcheck] fn quickcheck_unsigned_add_associative(a: BigUint, b: BigUint, c: BigUint) -> bool { (&a + &b) + &c == a + (b + c) } #[quickcheck] fn quickcheck_signed_add_associative(a: BigInt, b: BigInt, c: BigInt) -> bool { (&a + &b) + &c == a + (b + c) } #[quickcheck] fn quickcheck_unsigned_mul_zero(a: BigUint) -> bool { a * BigUint::zero() == BigUint::zero() } #[quickcheck] fn quickcheck_signed_mul_zero(a: BigInt) -> bool { a * BigInt::zero() == BigInt::zero() } #[quickcheck] fn quickcheck_unsigned_mul_one(a: BigUint) -> bool { &a * BigUint::one() == a } #[quickcheck] fn quickcheck_signed_mul_one(a: BigInt) -> bool { &a * BigInt::one() == a } #[quickcheck] fn quickcheck_unsigned_mul_commutative(a: BigUint, b: BigUint) -> bool { &a * &b == b * a } #[quickcheck] fn quickcheck_signed_mul_commutative(a: BigInt, b: BigInt) -> bool { &a * &b == b * a } #[quickcheck] fn quickcheck_unsigned_mul_associative(a: BigUint, b: BigUint, c: BigUint) -> bool { (&a * &b) * &c == a * (b * c) } #[quickcheck] fn quickcheck_signed_mul_associative(a: BigInt, b: BigInt, c: BigInt) -> bool { (&a * &b) * &c == a * (b * c) } #[quickcheck] fn quickcheck_unsigned_distributive(a: BigUint, b: BigUint, c: BigUint) -> bool { &a * (&b + &c) == &a * b + a * c } #[quickcheck] fn quickcheck_signed_distributive(a: BigInt, b: BigInt, c: BigInt) -> bool { &a * (&b + &c) == &a * b + a * c } #[quickcheck] ///Tests that exactly one of ab a=b is true fn quickcheck_unsigned_ge_le_eq_mut_exclusive(a: BigUint, b: BigUint) -> bool { let gt_lt_eq = vec![a > b, a < b, a == b]; gt_lt_eq .iter() .fold(0, |acc, e| if *e { acc + 1 } else { acc }) == 1 } #[quickcheck] ///Tests that exactly one of ab a=b is true fn quickcheck_signed_ge_le_eq_mut_exclusive(a: BigInt, b: BigInt) -> bool { let gt_lt_eq = vec![a > b, a < b, a == b]; gt_lt_eq .iter() .fold(0, |acc, e| if *e { acc + 1 } else { acc }) == 1 } #[quickcheck] /// Tests correctness of subtraction assuming addition is correct fn quickcheck_unsigned_sub(a: BigUint, b: BigUint) -> bool { if b < a { &a - &b + b == a } else { &b - &a + a == b } } #[quickcheck] /// Tests correctness of subtraction assuming addition is correct fn quickcheck_signed_sub(a: BigInt, b: BigInt) -> bool { if b < a { &a - &b + b == a } else { &b - &a + a == b } } #[quickcheck] fn quickcheck_unsigned_pow_zero(a: BigUint) -> bool { a.pow(0_u32) == BigUint::one() } #[quickcheck] fn quickcheck_unsigned_pow_one(a: BigUint) -> bool { a.pow(1_u32) == a } #[quickcheck] fn quickcheck_unsigned_sqrt(a: BigUint) -> bool { (&a * &a).sqrt() == a } #[quickcheck] fn quickcheck_unsigned_cbrt(a: BigUint) -> bool { (&a * &a * &a).cbrt() == a } #[quickcheck] fn quickcheck_signed_cbrt(a: BigInt) -> bool { (&a * &a * &a).cbrt() == a } #[quickcheck] fn quickcheck_unsigned_conversion(a: BigUint, radix: u8) -> TestResult { let radix = radix as u32; if radix > 36 || radix < 2 { return TestResult::discard(); } let string = a.to_str_radix(radix); TestResult::from_bool(a == BigUint::from_str_radix(&string, radix).unwrap()) } #[quickcheck] fn quickcheck_signed_conversion(a: BigInt, radix: u8) -> TestResult { let radix = radix as u32; if radix > 36 || radix < 2 { return TestResult::discard(); } let string = a.to_str_radix(radix); TestResult::from_bool(a == BigInt::from_str_radix(&string, radix).unwrap()) } #[test] fn quicktest_shift() { let gen = StdThreadGen::new(usize::max_value()); let mut qc = QuickCheck::with_gen(gen); fn test_shr_unsigned(a: u64, shift: u8) -> TestResult { let shift = (shift % 64) as usize; //shift at most 64 bits let big_a = BigUint::from(a); TestResult::from_bool(BigUint::from(a >> shift) == big_a >> shift) } fn test_shr_signed(a: i64, shift: u8) -> TestResult { let shift = (shift % 64) as usize; //shift at most 64 bits let big_a = BigInt::from(a); TestResult::from_bool(BigInt::from(a >> shift) == big_a >> shift) } fn test_shl_unsigned(a: u32, shift: u8) -> TestResult { let shift = (shift % 32) as usize; //shift at most 32 bits let a = a as u64; //leave room for the shifted bits let big_a = BigUint::from(a); TestResult::from_bool(BigUint::from(a >> shift) == big_a >> shift) } fn test_shl_signed(a: i32, shift: u8) -> TestResult { let shift = (shift % 32) as usize; let a = a as u64; //leave room for the shifted bits let big_a = BigInt::from(a); TestResult::from_bool(BigInt::from(a >> shift) == big_a >> shift) } qc.quickcheck(test_shr_unsigned as fn(u64, u8) -> TestResult); qc.quickcheck(test_shr_signed as fn(i64, u8) -> TestResult); qc.quickcheck(test_shl_unsigned as fn(u32, u8) -> TestResult); qc.quickcheck(test_shl_signed as fn(i32, u8) -> TestResult); }