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:
parent
01cf35ae3c
commit
8964eb9887
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
Cargo.lock
|
||||
target
|
||||
*.bk
|
||||
*.orig
|
||||
|
@ -32,10 +32,6 @@ use biguint::BigUint;
|
||||
use UsizePromotion;
|
||||
use IsizePromotion;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/bigint.rs"]
|
||||
mod bigint_tests;
|
||||
|
||||
/// A Sign is a `BigInt`'s composing element.
|
||||
#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)]
|
||||
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);
|
||||
}
|
||||
|
@ -38,10 +38,6 @@ use UsizePromotion;
|
||||
|
||||
use ParseBigIntError;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/biguint.rs"]
|
||||
mod biguint_tests;
|
||||
|
||||
/// A big unsigned integer type.
|
||||
///
|
||||
/// 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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[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]);
|
||||
}
|
||||
|
12
src/lib.rs
12
src/lib.rs
@ -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]
|
||||
mod macros;
|
||||
|
||||
|
@ -1,6 +1,11 @@
|
||||
use {BigDigit, BigUint, big_digit};
|
||||
use {Sign, BigInt, RandBigInt, ToBigInt};
|
||||
use Sign::{Minus, NoSign, Plus};
|
||||
extern crate num_bigint;
|
||||
extern crate num_integer;
|
||||
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::{f32, f64};
|
||||
@ -8,89 +13,17 @@ use std::{i8, i16, i32, i64, isize};
|
||||
use std::iter::repeat;
|
||||
use std::{u8, u16, u32, u64, usize};
|
||||
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;
|
||||
use traits::{Zero, One, Signed, ToPrimitive, FromPrimitive, Num, Float};
|
||||
mod consts;
|
||||
use consts::*;
|
||||
|
||||
/// 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 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);
|
||||
}
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[test]
|
||||
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]
|
||||
fn test_hash() {
|
||||
use hash;
|
||||
|
||||
let a = BigInt::new(NoSign, vec![]);
|
||||
let b = BigInt::new(NoSign, vec![0]);
|
||||
let c = BigInt::new(Plus, vec![1]);
|
||||
@ -569,21 +505,6 @@ fn test_convert_from_biguint() {
|
||||
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]
|
||||
fn test_add() {
|
||||
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]
|
||||
fn test_sub() {
|
||||
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]
|
||||
fn test_mul() {
|
||||
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]
|
||||
fn test_div_mod_floor() {
|
||||
fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
|
||||
let (d, m) = a.div_mod_floor(b);
|
||||
if !m.is_zero() {
|
||||
assert_eq!(m.sign, b.sign);
|
||||
assert_eq!(m.sign(), b.sign());
|
||||
}
|
||||
assert!(m.abs() <= b.abs());
|
||||
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) {
|
||||
let (q, r) = a.div_rem(b);
|
||||
if !r.is_zero() {
|
||||
assert_eq!(r.sign, a.sign);
|
||||
assert_eq!(r.sign(), a.sign());
|
||||
}
|
||||
assert!(r.abs() <= b.abs());
|
||||
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]
|
||||
fn test_checked_add() {
|
||||
for elm in SUM_TRIPLES.iter() {
|
||||
@ -1144,55 +911,6 @@ fn test_neg() {
|
||||
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]
|
||||
fn test_negative_shr() {
|
||||
assert_eq!(BigInt::from(-1) >> 1, BigInt::from(-1));
|
||||
@ -1204,7 +922,7 @@ fn test_negative_shr() {
|
||||
#[test]
|
||||
fn test_random_shr() {
|
||||
use rand::Rng;
|
||||
let mut rng = thread_rng();
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
for p in rng.gen_iter::<i64>().take(1000) {
|
||||
let big = BigInt::from(p);
|
||||
@ -1217,6 +935,7 @@ fn test_random_shr() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter_sum() {
|
||||
let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap();
|
146
tests/bigint_scalar.rs
Normal file
146
tests/bigint_scalar.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,12 @@
|
||||
use integer::Integer;
|
||||
use {BigDigit, BigUint, ToBigUint, big_digit};
|
||||
use {BigInt, RandBigInt, ToBigInt};
|
||||
use Sign::Plus;
|
||||
extern crate num_bigint;
|
||||
extern crate num_integer;
|
||||
extern crate num_traits;
|
||||
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::{f32, f64};
|
||||
@ -9,79 +14,17 @@ use std::i64;
|
||||
use std::iter::repeat;
|
||||
use std::str::FromStr;
|
||||
use std::{u8, u16, u32, u64, usize};
|
||||
use std::hash::{BuildHasher, Hasher, Hash};
|
||||
use std::collections::hash_map::RandomState;
|
||||
|
||||
use rand::thread_rng;
|
||||
use traits::{Num, Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, ToPrimitive,
|
||||
FromPrimitive, Float};
|
||||
use num_traits::{Num, Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, ToPrimitive,
|
||||
FromPrimitive, Float};
|
||||
|
||||
mod consts;
|
||||
use consts::*;
|
||||
|
||||
/// 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 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]);
|
||||
}
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[test]
|
||||
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]
|
||||
fn test_hash() {
|
||||
use hash;
|
||||
@ -510,9 +459,6 @@ fn test_shr() {
|
||||
"88887777666655554444333322221111");
|
||||
}
|
||||
|
||||
const N1: BigDigit = -1i32 as BigDigit;
|
||||
const N2: BigDigit = -2i32 as BigDigit;
|
||||
|
||||
// `DoubleBigDigit` size dependent
|
||||
#[test]
|
||||
fn test_convert_i64() {
|
||||
@ -527,9 +473,9 @@ fn test_convert_i64() {
|
||||
check(i64::MAX.to_biguint().unwrap(), i64::MAX);
|
||||
|
||||
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![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);
|
||||
|
||||
assert_eq!(i64::MIN.to_biguint(), None);
|
||||
@ -553,9 +499,9 @@ fn test_convert_u64() {
|
||||
check(u64::MAX.to_biguint().unwrap(), u64::MAX);
|
||||
|
||||
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![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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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]
|
||||
fn test_add() {
|
||||
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]
|
||||
fn test_sub() {
|
||||
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]
|
||||
#[should_panic]
|
||||
fn test_sub_fail_on_underflow() {
|
||||
@ -803,43 +711,6 @@ fn test_sub_fail_on_underflow() {
|
||||
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]
|
||||
fn test_mul() {
|
||||
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]
|
||||
fn test_div_rem() {
|
||||
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]
|
||||
fn test_checked_add() {
|
||||
for elm in SUM_TRIPLES.iter() {
|
||||
@ -1595,88 +1420,6 @@ fn test_bits() {
|
||||
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]
|
||||
fn test_iter_sum() {
|
||||
let result: BigUint = FromPrimitive::from_isize(1234567).unwrap();
|
103
tests/biguint_scalar.rs
Normal file
103
tests/biguint_scalar.rs
Normal 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
65
tests/consts/mod.rs
Normal 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
53
tests/macros/mod.rs
Normal 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
112
tests/rand.rs
Normal 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
45
tests/torture.rs
Normal 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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user