Chop the tests up

The test modules were getting huge, and some of its functions were
actually a huge amount of code due to macros, causing tests to take a
long time just to compile.  They are now separated into a few different
tests, and the scalar macros especially are now expanded more sparingly
in just a few `check()` functions.

Test compile times for me went from about 25 seconds to 1.5s in debug
mode, and from 300 seconds (!) to about 8s in release mode.
This commit is contained in:
Josh Stone 2018-02-26 22:13:25 -08:00
parent 01cf35ae3c
commit 8964eb9887
12 changed files with 657 additions and 610 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
Cargo.lock Cargo.lock
target target
*.bk
*.orig

View File

@ -32,10 +32,6 @@ use biguint::BigUint;
use UsizePromotion; use UsizePromotion;
use IsizePromotion; use IsizePromotion;
#[cfg(test)]
#[path = "tests/bigint.rs"]
mod bigint_tests;
/// A Sign is a `BigInt`'s composing element. /// A Sign is a `BigInt`'s composing element.
#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)] #[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)]
pub enum Sign { pub enum Sign {
@ -1812,3 +1808,53 @@ fn twos_complement<'a, I>(digits: I)
} }
} }
} }
#[test]
fn test_from_biguint() {
fn check(inp_s: Sign, inp_n: usize, ans_s: Sign, ans_n: usize) {
let inp = BigInt::from_biguint(inp_s, FromPrimitive::from_usize(inp_n).unwrap());
let ans = BigInt {
sign: ans_s,
data: FromPrimitive::from_usize(ans_n).unwrap(),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}
#[test]
fn test_from_slice() {
fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) {
let inp = BigInt::from_slice(inp_s, &[inp_n]);
let ans = BigInt {
sign: ans_s,
data: FromPrimitive::from_u32(ans_n).unwrap(),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}
#[test]
fn test_assign_from_slice() {
fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) {
let mut inp = BigInt::from_slice(Minus, &[2627_u32, 0_u32, 9182_u32, 42_u32]);
inp.assign_from_slice(inp_s, &[inp_n]);
let ans = BigInt {
sign: ans_s,
data: FromPrimitive::from_u32(ans_n).unwrap(),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}

View File

@ -38,10 +38,6 @@ use UsizePromotion;
use ParseBigIntError; use ParseBigIntError;
#[cfg(test)]
#[path = "tests/biguint.rs"]
mod biguint_tests;
/// A big unsigned integer type. /// A big unsigned integer type.
/// ///
/// A `BigUint`-typed value `BigUint { data: vec!(a, b, c) }` represents a number /// A `BigUint`-typed value `BigUint { data: vec!(a, b, c) }` represents a number
@ -2277,3 +2273,32 @@ fn get_radix_base(radix: u32) -> (BigDigit, usize) {
_ => panic!("Invalid bigdigit size") _ => panic!("Invalid bigdigit size")
} }
} }
#[test]
fn test_from_slice() {
fn check(slice: &[BigDigit], data: &[BigDigit]) {
assert!(BigUint::from_slice(slice).data == data);
}
check(&[1], &[1]);
check(&[0, 0, 0], &[]);
check(&[1, 2, 0, 0], &[1, 2]);
check(&[0, 0, 1, 2], &[0, 0, 1, 2]);
check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
}
#[test]
fn test_assign_from_slice() {
fn check(slice: &[BigDigit], data: &[BigDigit]) {
let mut p = BigUint::from_slice(&[2627_u32, 0_u32, 9182_u32, 42_u32]);
p.assign_from_slice(slice);
assert!(p.data == data);
}
check(&[1], &[1]);
check(&[0, 0, 0], &[]);
check(&[1, 2, 0, 0], &[1, 2]);
check(&[0, 0, 1, 2], &[0, 0, 1, 2]);
check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
}

View File

@ -127,18 +127,6 @@ impl From<ParseIntError> for ParseBigIntError {
} }
} }
#[cfg(test)]
use std::hash;
#[cfg(test)]
fn hash<T: hash::Hash>(x: &T) -> u64 {
use std::hash::{BuildHasher, Hasher};
use std::collections::hash_map::RandomState;
let mut hasher = <RandomState as BuildHasher>::Hasher::new();
x.hash(&mut hasher);
hasher.finish()
}
#[macro_use] #[macro_use]
mod macros; mod macros;

View File

@ -1,6 +1,11 @@
use {BigDigit, BigUint, big_digit}; extern crate num_bigint;
use {Sign, BigInt, RandBigInt, ToBigInt}; extern crate num_integer;
use Sign::{Minus, NoSign, Plus}; extern crate num_traits;
extern crate rand;
use num_bigint::{BigDigit, BigUint, big_digit};
use num_bigint::{BigInt, ToBigInt};
use num_bigint::Sign::{Minus, NoSign, Plus};
use std::cmp::Ordering::{Less, Equal, Greater}; use std::cmp::Ordering::{Less, Equal, Greater};
use std::{f32, f64}; use std::{f32, f64};
@ -8,89 +13,17 @@ use std::{i8, i16, i32, i64, isize};
use std::iter::repeat; use std::iter::repeat;
use std::{u8, u16, u32, u64, usize}; use std::{u8, u16, u32, u64, usize};
use std::ops::Neg; use std::ops::Neg;
use std::hash::{BuildHasher, Hasher, Hash};
use std::collections::hash_map::RandomState;
use rand::thread_rng; use num_integer::Integer;
use num_traits::{Zero, One, Signed, ToPrimitive, FromPrimitive, Num, Float};
use integer::Integer; mod consts;
use traits::{Zero, One, Signed, ToPrimitive, FromPrimitive, Num, Float}; use consts::*;
/// Assert that an op works for all val/ref combinations #[macro_use]
macro_rules! assert_op { mod macros;
($left:ident $op:tt $right:ident == $expected:expr) => {
assert_eq!((&$left) $op (&$right), $expected);
assert_eq!((&$left) $op $right.clone(), $expected);
assert_eq!($left.clone() $op (&$right), $expected);
assert_eq!($left.clone() $op $right.clone(), $expected);
};
}
/// Assert that an op works for scalar left or right
macro_rules! assert_scalar_op {
(($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => {
$(
if let Some(left) = $left.$to() {
assert_op!(left $op $right == $expected);
}
if let Some(right) = $right.$to() {
assert_op!($left $op right == $expected);
}
)*
};
($left:ident $op:tt $right:ident == $expected:expr) => {
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize,
to_i8, to_i16, to_i32, to_i64, to_isize)
$left $op $right == $expected);
};
}
#[test]
fn test_from_biguint() {
fn check(inp_s: Sign, inp_n: usize, ans_s: Sign, ans_n: usize) {
let inp = BigInt::from_biguint(inp_s, FromPrimitive::from_usize(inp_n).unwrap());
let ans = BigInt {
sign: ans_s,
data: FromPrimitive::from_usize(ans_n).unwrap(),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}
#[test]
fn test_from_slice() {
fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) {
let inp = BigInt::from_slice(inp_s, &[inp_n]);
let ans = BigInt {
sign: ans_s,
data: FromPrimitive::from_u32(ans_n).unwrap(),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}
#[test]
fn test_assign_from_slice() {
fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) {
let mut inp = BigInt::from_slice(Minus, &[2627_u32, 0_u32, 9182_u32, 42_u32]);
inp.assign_from_slice(inp_s, &[inp_n]);
let ans = BigInt {
sign: ans_s,
data: FromPrimitive::from_u32(ans_n).unwrap(),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}
#[test] #[test]
fn test_from_bytes_be() { fn test_from_bytes_be() {
@ -271,11 +204,14 @@ fn test_cmp() {
} }
} }
fn hash<T: Hash>(x: &T) -> u64 {
let mut hasher = <RandomState as BuildHasher>::Hasher::new();
x.hash(&mut hasher);
hasher.finish()
}
#[test] #[test]
fn test_hash() { fn test_hash() {
use hash;
let a = BigInt::new(NoSign, vec![]); let a = BigInt::new(NoSign, vec![]);
let b = BigInt::new(NoSign, vec![0]); let b = BigInt::new(NoSign, vec![0]);
let c = BigInt::new(Plus, vec![1]); let c = BigInt::new(Plus, vec![1]);
@ -569,21 +505,6 @@ fn test_convert_from_biguint() {
BigInt::from_slice(Plus, &[1, 2, 3])); BigInt::from_slice(Plus, &[1, 2, 3]));
} }
const N1: BigDigit = -1i32 as BigDigit;
const N2: BigDigit = -2i32 as BigDigit;
const SUM_TRIPLES: &'static [(&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])] = &[(&[], &[], &[]),
(&[], &[1], &[1]),
(&[1], &[1], &[2]),
(&[1], &[1, 1], &[2, 1]),
(&[1], &[N1], &[0, 1]),
(&[1], &[N1, N1], &[0, 0, 1]),
(&[N1, N1], &[N1, N1], &[N2, N1, 1]),
(&[1, 1, 1], &[N1, N1], &[0, 1, 2]),
(&[2, 2, 1], &[N1, N2], &[1, 1, 2])];
#[test] #[test]
fn test_add() { fn test_add() {
for elm in SUM_TRIPLES.iter() { for elm in SUM_TRIPLES.iter() {
@ -604,26 +525,6 @@ fn test_add() {
} }
} }
#[test]
fn test_scalar_add() {
for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let b = BigInt::from_slice(Plus, b_vec);
let c = BigInt::from_slice(Plus, c_vec);
let (na, nb, nc) = (-&a, -&b, -&c);
assert_scalar_op!(a + b == c);
assert_scalar_op!(b + a == c);
assert_scalar_op!(c + na == b);
assert_scalar_op!(c + nb == a);
assert_scalar_op!(a + nc == nb);
assert_scalar_op!(b + nc == na);
assert_scalar_op!(na + nb == nc);
assert_scalar_op!(a + na == Zero::zero());
}
}
#[test] #[test]
fn test_sub() { fn test_sub() {
for elm in SUM_TRIPLES.iter() { for elm in SUM_TRIPLES.iter() {
@ -644,63 +545,6 @@ fn test_sub() {
} }
} }
#[test]
fn test_scalar_sub() {
for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let b = BigInt::from_slice(Plus, b_vec);
let c = BigInt::from_slice(Plus, c_vec);
let (na, nb, nc) = (-&a, -&b, -&c);
assert_scalar_op!(c - a == b);
assert_scalar_op!(c - b == a);
assert_scalar_op!(nb - a == nc);
assert_scalar_op!(na - b == nc);
assert_scalar_op!(b - na == c);
assert_scalar_op!(a - nb == c);
assert_scalar_op!(nc - na == nb);
assert_scalar_op!(a - a == Zero::zero());
}
}
const M: u32 = ::std::u32::MAX;
static MUL_TRIPLES: &'static [(&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])] = &[(&[], &[], &[]),
(&[], &[1], &[]),
(&[2], &[], &[]),
(&[1], &[1], &[1]),
(&[2], &[3], &[6]),
(&[1], &[1, 1, 1], &[1, 1, 1]),
(&[1, 2, 3], &[3], &[3, 6, 9]),
(&[1, 1, 1], &[N1], &[N1, N1, N1]),
(&[1, 2, 3], &[N1], &[N1, N2, N2, 2]),
(&[1, 2, 3, 4], &[N1], &[N1, N2, N2, N2, 3]),
(&[N1], &[N1], &[1, N2]),
(&[N1, N1], &[N1], &[1, N1, N2]),
(&[N1, N1, N1], &[N1], &[1, N1, N1, N2]),
(&[N1, N1, N1, N1], &[N1], &[1, N1, N1, N1, N2]),
(&[M / 2 + 1], &[2], &[0, 1]),
(&[0, M / 2 + 1], &[2], &[0, 0, 1]),
(&[1, 2], &[1, 2, 3], &[1, 4, 7, 6]),
(&[N1, N1], &[N1, N1, N1], &[1, 0, N1, N2, N1]),
(&[N1, N1, N1],
&[N1, N1, N1, N1],
&[1, 0, 0, N1, N2, N1, N1]),
(&[0, 0, 1], &[1, 2, 3], &[0, 0, 1, 2, 3]),
(&[0, 0, 1], &[0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])];
static DIV_REM_QUADRUPLES: &'static [(&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])] = &[(&[1], &[2], &[], &[1]),
(&[3], &[2], &[1], &[1]),
(&[1, 1], &[2], &[M / 2 + 1], &[1]),
(&[1, 1, 1], &[2], &[M / 2 + 1, M / 2 + 1], &[1]),
(&[0, 1], &[N1], &[1], &[1]),
(&[N1, N1], &[N2], &[2, 1], &[3])];
#[test] #[test]
fn test_mul() { fn test_mul() {
for elm in MUL_TRIPLES.iter() { for elm in MUL_TRIPLES.iter() {
@ -730,30 +574,12 @@ fn test_mul() {
} }
} }
#[test]
fn test_scalar_mul() {
for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let b = BigInt::from_slice(Plus, b_vec);
let c = BigInt::from_slice(Plus, c_vec);
let (na, nb, nc) = (-&a, -&b, -&c);
assert_scalar_op!(a * b == c);
assert_scalar_op!(b * a == c);
assert_scalar_op!(na * nb == c);
assert_scalar_op!(na * b == nc);
assert_scalar_op!(nb * a == nc);
}
}
#[test] #[test]
fn test_div_mod_floor() { fn test_div_mod_floor() {
fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) { fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
let (d, m) = a.div_mod_floor(b); let (d, m) = a.div_mod_floor(b);
if !m.is_zero() { if !m.is_zero() {
assert_eq!(m.sign, b.sign); assert_eq!(m.sign(), b.sign());
} }
assert!(m.abs() <= b.abs()); assert!(m.abs() <= b.abs());
assert!(*a == b * &d + &m); assert!(*a == b * &d + &m);
@ -809,7 +635,7 @@ fn test_div_rem() {
fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) { fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) {
let (q, r) = a.div_rem(b); let (q, r) = a.div_rem(b);
if !r.is_zero() { if !r.is_zero() {
assert_eq!(r.sign, a.sign); assert_eq!(r.sign(), a.sign());
} }
assert!(r.abs() <= b.abs()); assert!(r.abs() <= b.abs());
assert!(*a == b * &q + &r); assert!(*a == b * &q + &r);
@ -854,65 +680,6 @@ fn test_div_rem() {
} }
} }
#[test]
fn test_scalar_div_rem() {
fn check_sub(a: &BigInt, b: BigDigit, ans_q: &BigInt, ans_r: &BigInt) {
let (q, r) = (a / b, a % b);
if !r.is_zero() {
assert_eq!(r.sign, a.sign);
}
assert!(r.abs() <= From::from(b));
assert!(*a == b * &q + &r);
assert!(q == *ans_q);
assert!(r == *ans_r);
let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone());
assert_op!(a / b == ans_q);
assert_op!(a % b == ans_r);
if b <= i32::max_value() as u32 {
let nb = -(b as i32);
assert_op!(a / nb == -ans_q.clone());
assert_op!(a % nb == ans_r);
}
}
fn check(a: &BigInt, b: BigDigit, q: &BigInt, r: &BigInt) {
check_sub(a, b, q, r);
check_sub(&a.neg(), b, &q.neg(), &r.neg());
}
for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let b = BigInt::from_slice(Plus, b_vec);
let c = BigInt::from_slice(Plus, c_vec);
if a_vec.len() == 1 && a_vec[0] != 0 {
let a = a_vec[0];
check(&c, a, &b, &Zero::zero());
}
if b_vec.len() == 1 && b_vec[0] != 0 {
let b = b_vec[0];
check(&c, b, &a, &Zero::zero());
}
}
for elm in DIV_REM_QUADRUPLES.iter() {
let (a_vec, b_vec, c_vec, d_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let c = BigInt::from_slice(Plus, c_vec);
let d = BigInt::from_slice(Plus, d_vec);
if b_vec.len() == 1 && b_vec[0] != 0 {
let b = b_vec[0];
check(&a, b, &c, &d);
}
}
}
#[test] #[test]
fn test_checked_add() { fn test_checked_add() {
for elm in SUM_TRIPLES.iter() { for elm in SUM_TRIPLES.iter() {
@ -1144,55 +911,6 @@ fn test_neg() {
assert_eq!(-&zero, zero); assert_eq!(-&zero, zero);
} }
#[test]
fn test_rand() {
let mut rng = thread_rng();
let _n: BigInt = rng.gen_bigint(137);
assert!(rng.gen_bigint(0).is_zero());
}
#[test]
fn test_rand_range() {
let mut rng = thread_rng();
for _ in 0..10 {
assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_usize(236).unwrap(),
&FromPrimitive::from_usize(237).unwrap()),
FromPrimitive::from_usize(236).unwrap());
}
fn check(l: BigInt, u: BigInt) {
let mut rng = thread_rng();
for _ in 0..1000 {
let n: BigInt = rng.gen_bigint_range(&l, &u);
assert!(n >= l);
assert!(n < u);
}
}
let l: BigInt = FromPrimitive::from_usize(403469000 + 2352).unwrap();
let u: BigInt = FromPrimitive::from_usize(403469000 + 3513).unwrap();
check(l.clone(), u.clone());
check(-l.clone(), u.clone());
check(-u.clone(), -l.clone());
}
#[test]
#[should_panic]
fn test_zero_rand_range() {
thread_rng().gen_bigint_range(&FromPrimitive::from_isize(54).unwrap(),
&FromPrimitive::from_isize(54).unwrap());
}
#[test]
#[should_panic]
fn test_negative_rand_range() {
let mut rng = thread_rng();
let l = FromPrimitive::from_usize(2352).unwrap();
let u = FromPrimitive::from_usize(3513).unwrap();
// Switching u and l should fail:
let _n: BigInt = rng.gen_bigint_range(&u, &l);
}
#[test] #[test]
fn test_negative_shr() { fn test_negative_shr() {
assert_eq!(BigInt::from(-1) >> 1, BigInt::from(-1)); assert_eq!(BigInt::from(-1) >> 1, BigInt::from(-1));
@ -1204,7 +922,7 @@ fn test_negative_shr() {
#[test] #[test]
fn test_random_shr() { fn test_random_shr() {
use rand::Rng; use rand::Rng;
let mut rng = thread_rng(); let mut rng = rand::thread_rng();
for p in rng.gen_iter::<i64>().take(1000) { for p in rng.gen_iter::<i64>().take(1000) {
let big = BigInt::from(p); let big = BigInt::from(p);
@ -1217,6 +935,7 @@ fn test_random_shr() {
} }
} }
} }
#[test] #[test]
fn test_iter_sum() { fn test_iter_sum() {
let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap(); let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap();

146
tests/bigint_scalar.rs Normal file
View File

@ -0,0 +1,146 @@
extern crate num_bigint;
extern crate num_traits;
use num_bigint::{BigDigit, BigInt};
use num_bigint::Sign::Plus;
use num_traits::{Zero, Signed, ToPrimitive};
use std::ops::Neg;
mod consts;
use consts::*;
#[macro_use]
mod macros;
#[test]
fn test_scalar_add() {
fn check(x: &BigInt, y: &BigInt, z: &BigInt) {
let (x, y, z) = (x.clone(), y.clone(), z.clone());
assert_signed_scalar_op!(x + y == z);
}
for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let b = BigInt::from_slice(Plus, b_vec);
let c = BigInt::from_slice(Plus, c_vec);
let (na, nb, nc) = (-&a, -&b, -&c);
check(&a, &b, &c);
check(&b, &a, &c);
check(&c, &na, &b);
check(&c, &nb, &a);
check(&a, &nc, &nb);
check(&b, &nc, &na);
check(&na, &nb, &nc);
check(&a, &na, &Zero::zero());
}
}
#[test]
fn test_scalar_sub() {
fn check(x: &BigInt, y: &BigInt, z: &BigInt) {
let (x, y, z) = (x.clone(), y.clone(), z.clone());
assert_signed_scalar_op!(x - y == z);
}
for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let b = BigInt::from_slice(Plus, b_vec);
let c = BigInt::from_slice(Plus, c_vec);
let (na, nb, nc) = (-&a, -&b, -&c);
check(&c, &a, &b);
check(&c, &b, &a);
check(&nb, &a, &nc);
check(&na, &b, &nc);
check(&b, &na, &c);
check(&a, &nb, &c);
check(&nc, &na, &nb);
check(&a, &a, &Zero::zero());
}
}
#[test]
fn test_scalar_mul() {
fn check(x: &BigInt, y: &BigInt, z: &BigInt) {
let (x, y, z) = (x.clone(), y.clone(), z.clone());
assert_signed_scalar_op!(x * y == z);
}
for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let b = BigInt::from_slice(Plus, b_vec);
let c = BigInt::from_slice(Plus, c_vec);
let (na, nb, nc) = (-&a, -&b, -&c);
check(&a, &b, &c);
check(&b, &a, &c);
check(&na, &nb, &c);
check(&na, &b, &nc);
check(&nb, &a, &nc);
}
}
#[test]
fn test_scalar_div_rem() {
fn check_sub(a: &BigInt, b: BigDigit, ans_q: &BigInt, ans_r: &BigInt) {
let (q, r) = (a / b, a % b);
if !r.is_zero() {
assert_eq!(r.sign(), a.sign());
}
assert!(r.abs() <= From::from(b));
assert!(*a == b * &q + &r);
assert!(q == *ans_q);
assert!(r == *ans_r);
let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone());
assert_op!(a / b == ans_q);
assert_op!(a % b == ans_r);
if b <= i32::max_value() as u32 {
let nb = -(b as i32);
assert_op!(a / nb == -ans_q.clone());
assert_op!(a % nb == ans_r);
}
}
fn check(a: &BigInt, b: BigDigit, q: &BigInt, r: &BigInt) {
check_sub(a, b, q, r);
check_sub(&a.neg(), b, &q.neg(), &r.neg());
}
for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let b = BigInt::from_slice(Plus, b_vec);
let c = BigInt::from_slice(Plus, c_vec);
if a_vec.len() == 1 && a_vec[0] != 0 {
let a = a_vec[0];
check(&c, a, &b, &Zero::zero());
}
if b_vec.len() == 1 && b_vec[0] != 0 {
let b = b_vec[0];
check(&c, b, &a, &Zero::zero());
}
}
for elm in DIV_REM_QUADRUPLES.iter() {
let (a_vec, b_vec, c_vec, d_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let c = BigInt::from_slice(Plus, c_vec);
let d = BigInt::from_slice(Plus, d_vec);
if b_vec.len() == 1 && b_vec[0] != 0 {
let b = b_vec[0];
check(&a, b, &c, &d);
}
}
}

View File

@ -1,7 +1,12 @@
use integer::Integer; extern crate num_bigint;
use {BigDigit, BigUint, ToBigUint, big_digit}; extern crate num_integer;
use {BigInt, RandBigInt, ToBigInt}; extern crate num_traits;
use Sign::Plus; extern crate rand;
use num_integer::Integer;
use num_bigint::{BigDigit, BigUint, ToBigUint, big_digit};
use num_bigint::{BigInt, ToBigInt};
use num_bigint::Sign::Plus;
use std::cmp::Ordering::{Less, Equal, Greater}; use std::cmp::Ordering::{Less, Equal, Greater};
use std::{f32, f64}; use std::{f32, f64};
@ -9,79 +14,17 @@ use std::i64;
use std::iter::repeat; use std::iter::repeat;
use std::str::FromStr; use std::str::FromStr;
use std::{u8, u16, u32, u64, usize}; use std::{u8, u16, u32, u64, usize};
use std::hash::{BuildHasher, Hasher, Hash};
use std::collections::hash_map::RandomState;
use rand::thread_rng; use num_traits::{Num, Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, ToPrimitive,
use traits::{Num, Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, ToPrimitive,
FromPrimitive, Float}; FromPrimitive, Float};
mod consts;
use consts::*;
/// Assert that an op works for all val/ref combinations #[macro_use]
macro_rules! assert_op { mod macros;
($left:ident $op:tt $right:ident == $expected:expr) => {
assert_eq!((&$left) $op (&$right), $expected);
assert_eq!((&$left) $op $right.clone(), $expected);
assert_eq!($left.clone() $op (&$right), $expected);
assert_eq!($left.clone() $op $right.clone(), $expected);
};
}
/// Assert that an assign-op works for all val/ref combinations
macro_rules! assert_assign_op {
($left:ident $op:tt $right:ident == $expected:expr) => {
{
let mut tmp12384 = $left.clone();
assert_eq!({ tmp12384 $op &$right; tmp12384}, $expected);
let mut tmp12384 = $left.clone();
assert_eq!({ tmp12384 $op $right.clone(); tmp12384}, $expected);
}
};
}
/// Assert that an op works for scalar left or right
macro_rules! assert_scalar_op {
(($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => {
$(
if let Some(left) = $left.$to() {
assert_op!(left $op $right == $expected);
}
if let Some(right) = $right.$to() {
assert_op!($left $op right == $expected);
}
)*
};
($left:ident $op:tt $right:ident == $expected:expr) => {
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize)
$left $op $right == $expected);
};
}
#[test]
fn test_from_slice() {
fn check(slice: &[BigDigit], data: &[BigDigit]) {
assert!(BigUint::from_slice(slice).data == data);
}
check(&[1], &[1]);
check(&[0, 0, 0], &[]);
check(&[1, 2, 0, 0], &[1, 2]);
check(&[0, 0, 1, 2], &[0, 0, 1, 2]);
check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
}
#[test]
fn test_assign_from_slice() {
fn check(slice: &[BigDigit], data: &[BigDigit]) {
let mut p = BigUint::from_slice(&[2627_u32, 0_u32, 9182_u32, 42_u32]);
p.assign_from_slice(slice);
assert!(p.data == data);
}
check(&[1], &[1]);
check(&[0, 0, 0], &[]);
check(&[1, 2, 0, 0], &[1, 2]);
check(&[0, 0, 1, 2], &[0, 0, 1, 2]);
check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
}
#[test] #[test]
fn test_from_bytes_be() { fn test_from_bytes_be() {
@ -182,6 +125,12 @@ fn test_cmp() {
} }
} }
fn hash<T: Hash>(x: &T) -> u64 {
let mut hasher = <RandomState as BuildHasher>::Hasher::new();
x.hash(&mut hasher);
hasher.finish()
}
#[test] #[test]
fn test_hash() { fn test_hash() {
use hash; use hash;
@ -510,9 +459,6 @@ fn test_shr() {
"88887777666655554444333322221111"); "88887777666655554444333322221111");
} }
const N1: BigDigit = -1i32 as BigDigit;
const N2: BigDigit = -2i32 as BigDigit;
// `DoubleBigDigit` size dependent // `DoubleBigDigit` size dependent
#[test] #[test]
fn test_convert_i64() { fn test_convert_i64() {
@ -527,9 +473,9 @@ fn test_convert_i64() {
check(i64::MAX.to_biguint().unwrap(), i64::MAX); check(i64::MAX.to_biguint().unwrap(), i64::MAX);
check(BigUint::new(vec![]), 0); check(BigUint::new(vec![]), 0);
check(BigUint::new(vec![1]), (1 << (0 * big_digit::BITS))); check(BigUint::new(vec![1]), 1 << (0 * big_digit::BITS));
check(BigUint::new(vec![N1]), (1 << (1 * big_digit::BITS)) - 1); check(BigUint::new(vec![N1]), (1 << (1 * big_digit::BITS)) - 1);
check(BigUint::new(vec![0, 1]), (1 << (1 * big_digit::BITS))); check(BigUint::new(vec![0, 1]), 1 << (1 * big_digit::BITS));
check(BigUint::new(vec![N1, N1 >> 1]), i64::MAX); check(BigUint::new(vec![N1, N1 >> 1]), i64::MAX);
assert_eq!(i64::MIN.to_biguint(), None); assert_eq!(i64::MIN.to_biguint(), None);
@ -553,9 +499,9 @@ fn test_convert_u64() {
check(u64::MAX.to_biguint().unwrap(), u64::MAX); check(u64::MAX.to_biguint().unwrap(), u64::MAX);
check(BigUint::new(vec![]), 0); check(BigUint::new(vec![]), 0);
check(BigUint::new(vec![1]), (1 << (0 * big_digit::BITS))); check(BigUint::new(vec![1]), 1 << (0 * big_digit::BITS));
check(BigUint::new(vec![N1]), (1 << (1 * big_digit::BITS)) - 1); check(BigUint::new(vec![N1]), (1 << (1 * big_digit::BITS)) - 1);
check(BigUint::new(vec![0, 1]), (1 << (1 * big_digit::BITS))); check(BigUint::new(vec![0, 1]), 1 << (1 * big_digit::BITS));
check(BigUint::new(vec![N1, N1]), u64::MAX); check(BigUint::new(vec![N1, N1]), u64::MAX);
assert_eq!(BigUint::new(vec![0, 0, 1]).to_u64(), None); assert_eq!(BigUint::new(vec![0, 0, 1]).to_u64(), None);
@ -728,18 +674,6 @@ fn test_convert_from_uint() {
check!(usize, BigUint::from(usize::MAX as u64)); check!(usize, BigUint::from(usize::MAX as u64));
} }
const SUM_TRIPLES: &'static [(&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])] = &[(&[], &[], &[]),
(&[], &[1], &[1]),
(&[1], &[1], &[2]),
(&[1], &[1, 1], &[2, 1]),
(&[1], &[N1], &[0, 1]),
(&[1], &[N1, N1], &[0, 0, 1]),
(&[N1, N1], &[N1, N1], &[N2, N1, 1]),
(&[1, 1, 1], &[N1, N1], &[0, 1, 2]),
(&[2, 2, 1], &[N1, N2], &[1, 1, 2])];
#[test] #[test]
fn test_add() { fn test_add() {
for elm in SUM_TRIPLES.iter() { for elm in SUM_TRIPLES.iter() {
@ -755,19 +689,6 @@ fn test_add() {
} }
} }
#[test]
fn test_scalar_add() {
for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
assert_scalar_op!(a + b == c);
assert_scalar_op!(b + a == c);
}
}
#[test] #[test]
fn test_sub() { fn test_sub() {
for elm in SUM_TRIPLES.iter() { for elm in SUM_TRIPLES.iter() {
@ -783,19 +704,6 @@ fn test_sub() {
} }
} }
#[test]
fn test_scalar_sub() {
for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
assert_scalar_op!(c - a == b);
assert_scalar_op!(c - b == a);
}
}
#[test] #[test]
#[should_panic] #[should_panic]
fn test_sub_fail_on_underflow() { fn test_sub_fail_on_underflow() {
@ -803,43 +711,6 @@ fn test_sub_fail_on_underflow() {
a - b; a - b;
} }
const M: u32 = ::std::u32::MAX;
const MUL_TRIPLES: &'static [(&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])] = &[(&[], &[], &[]),
(&[], &[1], &[]),
(&[2], &[], &[]),
(&[1], &[1], &[1]),
(&[2], &[3], &[6]),
(&[1], &[1, 1, 1], &[1, 1, 1]),
(&[1, 2, 3], &[3], &[3, 6, 9]),
(&[1, 1, 1], &[N1], &[N1, N1, N1]),
(&[1, 2, 3], &[N1], &[N1, N2, N2, 2]),
(&[1, 2, 3, 4], &[N1], &[N1, N2, N2, N2, 3]),
(&[N1], &[N1], &[1, N2]),
(&[N1, N1], &[N1], &[1, N1, N2]),
(&[N1, N1, N1], &[N1], &[1, N1, N1, N2]),
(&[N1, N1, N1, N1], &[N1], &[1, N1, N1, N1, N2]),
(&[M / 2 + 1], &[2], &[0, 1]),
(&[0, M / 2 + 1], &[2], &[0, 0, 1]),
(&[1, 2], &[1, 2, 3], &[1, 4, 7, 6]),
(&[N1, N1], &[N1, N1, N1], &[1, 0, N1, N2, N1]),
(&[N1, N1, N1],
&[N1, N1, N1, N1],
&[1, 0, 0, N1, N2, N1, N1]),
(&[0, 0, 1], &[1, 2, 3], &[0, 0, 1, 2, 3]),
(&[0, 0, 1], &[0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])];
const DIV_REM_QUADRUPLES: &'static [(&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])] = &[(&[1], &[2], &[], &[1]),
(&[3], &[2], &[1], &[1]),
(&[1, 1], &[2], &[M / 2 + 1], &[1]),
(&[1, 1, 1], &[2], &[M / 2 + 1, M / 2 + 1], &[1]),
(&[0, 1], &[N1], &[1], &[1]),
(&[N1, N1], &[N2], &[2, 1], &[3])];
#[test] #[test]
fn test_mul() { fn test_mul() {
for elm in MUL_TRIPLES.iter() { for elm in MUL_TRIPLES.iter() {
@ -866,19 +737,6 @@ fn test_mul() {
} }
} }
#[test]
fn test_scalar_mul() {
for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
assert_scalar_op!(a * b == c);
assert_scalar_op!(b * a == c);
}
}
#[test] #[test]
fn test_div_rem() { fn test_div_rem() {
for elm in MUL_TRIPLES.iter() { for elm in MUL_TRIPLES.iter() {
@ -920,39 +778,6 @@ fn test_div_rem() {
} }
} }
#[test]
fn test_scalar_div_rem() {
for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
if !a.is_zero() {
assert_scalar_op!(c / a == b);
assert_scalar_op!(c % a == Zero::zero());
}
if !b.is_zero() {
assert_scalar_op!(c / b == a);
assert_scalar_op!(c % b == Zero::zero());
}
}
for elm in DIV_REM_QUADRUPLES.iter() {
let (a_vec, b_vec, c_vec, d_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
let d = BigUint::from_slice(d_vec);
if !b.is_zero() {
assert_scalar_op!(a / b == c);
assert_scalar_op!(a % b == d);
}
}
}
#[test] #[test]
fn test_checked_add() { fn test_checked_add() {
for elm in SUM_TRIPLES.iter() { for elm in SUM_TRIPLES.iter() {
@ -1595,88 +1420,6 @@ fn test_bits() {
assert_eq!((one << 426).bits(), 427); assert_eq!((one << 426).bits(), 427);
} }
#[test]
fn test_rand() {
let mut rng = thread_rng();
let _n: BigUint = rng.gen_biguint(137);
assert!(rng.gen_biguint(0).is_zero());
}
#[test]
fn test_rand_range() {
let mut rng = thread_rng();
for _ in 0..10 {
assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_usize(236).unwrap(),
&FromPrimitive::from_usize(237).unwrap()),
FromPrimitive::from_usize(236).unwrap());
}
let l = FromPrimitive::from_usize(403469000 + 2352).unwrap();
let u = FromPrimitive::from_usize(403469000 + 3513).unwrap();
for _ in 0..1000 {
let n: BigUint = rng.gen_biguint_below(&u);
assert!(n < u);
let n: BigUint = rng.gen_biguint_range(&l, &u);
assert!(n >= l);
assert!(n < u);
}
}
#[test]
#[should_panic]
fn test_zero_rand_range() {
thread_rng().gen_biguint_range(&FromPrimitive::from_usize(54).unwrap(),
&FromPrimitive::from_usize(54).unwrap());
}
#[test]
#[should_panic]
fn test_negative_rand_range() {
let mut rng = thread_rng();
let l = FromPrimitive::from_usize(2352).unwrap();
let u = FromPrimitive::from_usize(3513).unwrap();
// Switching u and l should fail:
let _n: BigUint = rng.gen_biguint_range(&u, &l);
}
fn test_mul_divide_torture_count(count: usize) {
use rand::{SeedableRng, StdRng, Rng};
let bits_max = 1 << 12;
let seed: &[_] = &[1, 2, 3, 4];
let mut rng: StdRng = SeedableRng::from_seed(seed);
for _ in 0..count {
// Test with numbers of random sizes:
let xbits = rng.gen_range(0, bits_max);
let ybits = rng.gen_range(0, bits_max);
let x = rng.gen_biguint(xbits);
let y = rng.gen_biguint(ybits);
if x.is_zero() || y.is_zero() {
continue;
}
let prod = &x * &y;
assert_eq!(&prod / &x, y);
assert_eq!(&prod / &y, x);
}
}
#[test]
fn test_mul_divide_torture() {
test_mul_divide_torture_count(1000);
}
#[test]
#[ignore]
fn test_mul_divide_torture_long() {
test_mul_divide_torture_count(1000000);
}
#[test] #[test]
fn test_iter_sum() { fn test_iter_sum() {
let result: BigUint = FromPrimitive::from_isize(1234567).unwrap(); let result: BigUint = FromPrimitive::from_isize(1234567).unwrap();

103
tests/biguint_scalar.rs Normal file
View File

@ -0,0 +1,103 @@
extern crate num_bigint;
extern crate num_traits;
use num_bigint::BigUint;
use num_traits::{Zero, ToPrimitive};
mod consts;
use consts::*;
#[macro_use]
mod macros;
#[test]
fn test_scalar_add() {
fn check(x: &BigUint, y: &BigUint, z: &BigUint) {
let (x, y, z) = (x.clone(), y.clone(), z.clone());
assert_unsigned_scalar_op!(x + y == z);
}
for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
check(&a, &b, &c);
check(&b, &a, &c);
}
}
#[test]
fn test_scalar_sub() {
fn check(x: &BigUint, y: &BigUint, z: &BigUint) {
let (x, y, z) = (x.clone(), y.clone(), z.clone());
assert_unsigned_scalar_op!(x - y == z);
}
for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
check(&c, &a, &b);
check(&c, &b, &a);
}
}
#[test]
fn test_scalar_mul() {
fn check(x: &BigUint, y: &BigUint, z: &BigUint) {
let (x, y, z) = (x.clone(), y.clone(), z.clone());
assert_unsigned_scalar_op!(x * y == z);
}
for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
check(&a, &b, &c);
check(&b, &a, &c);
}
}
#[test]
fn test_scalar_div_rem() {
fn check(x: &BigUint, y: &BigUint, z: &BigUint, r: &BigUint) {
let (x, y, z, r) = (x.clone(), y.clone(), z.clone(), r.clone());
assert_unsigned_scalar_op!(x / y == z);
assert_unsigned_scalar_op!(x % y == r);
}
for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
if !a.is_zero() {
check(&c, &a, &b, &Zero::zero());
}
if !b.is_zero() {
check(&c, &b, &a, &Zero::zero());
}
}
for elm in DIV_REM_QUADRUPLES.iter() {
let (a_vec, b_vec, c_vec, d_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
let d = BigUint::from_slice(d_vec);
if !b.is_zero() {
check(&a, &b, &c, &d);
assert_unsigned_scalar_op!(a / b == c);
assert_unsigned_scalar_op!(a % b == d);
}
}
}

65
tests/consts/mod.rs Normal file
View File

@ -0,0 +1,65 @@
#![allow(unused)]
use num_bigint::BigDigit;
pub const N1: BigDigit = -1i32 as BigDigit;
pub const N2: BigDigit = -2i32 as BigDigit;
pub const SUM_TRIPLES: &'static [(
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit],
)] = &[
(&[], &[], &[]),
(&[], &[1], &[1]),
(&[1], &[1], &[2]),
(&[1], &[1, 1], &[2, 1]),
(&[1], &[N1], &[0, 1]),
(&[1], &[N1, N1], &[0, 0, 1]),
(&[N1, N1], &[N1, N1], &[N2, N1, 1]),
(&[1, 1, 1], &[N1, N1], &[0, 1, 2]),
(&[2, 2, 1], &[N1, N2], &[1, 1, 2]),
];
pub const M: u32 = ::std::u32::MAX;
pub const MUL_TRIPLES: &'static [(
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit],
)] = &[
(&[], &[], &[]),
(&[], &[1], &[]),
(&[2], &[], &[]),
(&[1], &[1], &[1]),
(&[2], &[3], &[6]),
(&[1], &[1, 1, 1], &[1, 1, 1]),
(&[1, 2, 3], &[3], &[3, 6, 9]),
(&[1, 1, 1], &[N1], &[N1, N1, N1]),
(&[1, 2, 3], &[N1], &[N1, N2, N2, 2]),
(&[1, 2, 3, 4], &[N1], &[N1, N2, N2, N2, 3]),
(&[N1], &[N1], &[1, N2]),
(&[N1, N1], &[N1], &[1, N1, N2]),
(&[N1, N1, N1], &[N1], &[1, N1, N1, N2]),
(&[N1, N1, N1, N1], &[N1], &[1, N1, N1, N1, N2]),
(&[M / 2 + 1], &[2], &[0, 1]),
(&[0, M / 2 + 1], &[2], &[0, 0, 1]),
(&[1, 2], &[1, 2, 3], &[1, 4, 7, 6]),
(&[N1, N1], &[N1, N1, N1], &[1, 0, N1, N2, N1]),
(&[N1, N1, N1], &[N1, N1, N1, N1], &[1, 0, 0, N1, N2, N1, N1]),
(&[0, 0, 1], &[1, 2, 3], &[0, 0, 1, 2, 3]),
(&[0, 0, 1], &[0, 0, 0, 1], &[0, 0, 0, 0, 0, 1]),
];
pub const DIV_REM_QUADRUPLES: &'static [(
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit],
)] = &[
(&[1], &[2], &[], &[1]),
(&[3], &[2], &[1], &[1]),
(&[1, 1], &[2], &[M / 2 + 1], &[1]),
(&[1, 1, 1], &[2], &[M / 2 + 1, M / 2 + 1], &[1]),
(&[0, 1], &[N1], &[1], &[1]),
(&[N1, N1], &[N2], &[2, 1], &[3]),
];

53
tests/macros/mod.rs Normal file
View File

@ -0,0 +1,53 @@
#![allow(unused)]
/// Assert that an op works for all val/ref combinations
macro_rules! assert_op {
($left:ident $op:tt $right:ident == $expected:expr) => {
assert_eq!((&$left) $op (&$right), $expected);
assert_eq!((&$left) $op $right.clone(), $expected);
assert_eq!($left.clone() $op (&$right), $expected);
assert_eq!($left.clone() $op $right.clone(), $expected);
};
}
/// Assert that an assign-op works for all val/ref combinations
macro_rules! assert_assign_op {
($left:ident $op:tt $right:ident == $expected:expr) => {
{
let mut left = $left.clone();
assert_eq!({ left $op &$right; left}, $expected);
let mut left = $left.clone();
assert_eq!({ left $op $right.clone(); left}, $expected);
}
};
}
/// Assert that an op works for scalar left or right
macro_rules! assert_scalar_op {
(($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => {
$(
if let Some(left) = $left.$to() {
assert_op!(left $op $right == $expected);
}
if let Some(right) = $right.$to() {
assert_op!($left $op right == $expected);
}
)*
};
}
macro_rules! assert_unsigned_scalar_op {
($left:ident $op:tt $right:ident == $expected:expr) => {
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize)
$left $op $right == $expected);
};
}
macro_rules! assert_signed_scalar_op {
($left:ident $op:tt $right:ident == $expected:expr) => {
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize,
to_i8, to_i16, to_i32, to_i64, to_isize)
$left $op $right == $expected);
};
}

112
tests/rand.rs Normal file
View File

@ -0,0 +1,112 @@
#![cfg(feature = "rand")]
extern crate num_bigint;
extern crate num_traits;
extern crate rand;
mod biguint {
use rand::thread_rng;
use num_bigint::{BigUint, RandBigInt};
use num_traits::{FromPrimitive, Zero};
#[test]
fn test_rand() {
let mut rng = thread_rng();
let _n: BigUint = rng.gen_biguint(137);
assert!(rng.gen_biguint(0).is_zero());
}
#[test]
fn test_rand_range() {
let mut rng = thread_rng();
for _ in 0..10 {
assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_usize(236).unwrap(),
&FromPrimitive::from_usize(237).unwrap()),
FromPrimitive::from_usize(236).unwrap());
}
let l = FromPrimitive::from_usize(403469000 + 2352).unwrap();
let u = FromPrimitive::from_usize(403469000 + 3513).unwrap();
for _ in 0..1000 {
let n: BigUint = rng.gen_biguint_below(&u);
assert!(n < u);
let n: BigUint = rng.gen_biguint_range(&l, &u);
assert!(n >= l);
assert!(n < u);
}
}
#[test]
#[should_panic]
fn test_zero_rand_range() {
thread_rng().gen_biguint_range(&FromPrimitive::from_usize(54).unwrap(),
&FromPrimitive::from_usize(54).unwrap());
}
#[test]
#[should_panic]
fn test_negative_rand_range() {
let mut rng = thread_rng();
let l = FromPrimitive::from_usize(2352).unwrap();
let u = FromPrimitive::from_usize(3513).unwrap();
// Switching u and l should fail:
let _n: BigUint = rng.gen_biguint_range(&u, &l);
}
}
mod bigint {
use rand::thread_rng;
use num_bigint::{BigInt, RandBigInt};
use num_traits::{FromPrimitive, Zero};
#[test]
fn test_rand() {
let mut rng = thread_rng();
let _n: BigInt = rng.gen_bigint(137);
assert!(rng.gen_bigint(0).is_zero());
}
#[test]
fn test_rand_range() {
let mut rng = thread_rng();
for _ in 0..10 {
assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_usize(236).unwrap(),
&FromPrimitive::from_usize(237).unwrap()),
FromPrimitive::from_usize(236).unwrap());
}
fn check(l: BigInt, u: BigInt) {
let mut rng = thread_rng();
for _ in 0..1000 {
let n: BigInt = rng.gen_bigint_range(&l, &u);
assert!(n >= l);
assert!(n < u);
}
}
let l: BigInt = FromPrimitive::from_usize(403469000 + 2352).unwrap();
let u: BigInt = FromPrimitive::from_usize(403469000 + 3513).unwrap();
check(l.clone(), u.clone());
check(-l.clone(), u.clone());
check(-u.clone(), -l.clone());
}
#[test]
#[should_panic]
fn test_zero_rand_range() {
thread_rng().gen_bigint_range(&FromPrimitive::from_isize(54).unwrap(),
&FromPrimitive::from_isize(54).unwrap());
}
#[test]
#[should_panic]
fn test_negative_rand_range() {
let mut rng = thread_rng();
let l = FromPrimitive::from_usize(2352).unwrap();
let u = FromPrimitive::from_usize(3513).unwrap();
// Switching u and l should fail:
let _n: BigInt = rng.gen_bigint_range(&u, &l);
}
}

45
tests/torture.rs Normal file
View File

@ -0,0 +1,45 @@
#![cfg(feature = "rand")]
extern crate num_bigint;
extern crate num_traits;
extern crate rand;
use num_bigint::RandBigInt;
use num_traits::Zero;
use rand::{SeedableRng, StdRng, Rng};
fn test_mul_divide_torture_count(count: usize) {
let bits_max = 1 << 12;
let seed: &[_] = &[1, 2, 3, 4];
let mut rng: StdRng = SeedableRng::from_seed(seed);
for _ in 0..count {
// Test with numbers of random sizes:
let xbits = rng.gen_range(0, bits_max);
let ybits = rng.gen_range(0, bits_max);
let x = rng.gen_biguint(xbits);
let y = rng.gen_biguint(ybits);
if x.is_zero() || y.is_zero() {
continue;
}
let prod = &x * &y;
assert_eq!(&prod / &x, y);
assert_eq!(&prod / &y, x);
}
}
#[test]
fn test_mul_divide_torture() {
test_mul_divide_torture_count(1000);
}
#[test]
#[ignore]
fn test_mul_divide_torture_long() {
test_mul_divide_torture_count(1000000);
}