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
|
Cargo.lock
|
||||||
target
|
target
|
||||||
|
*.bk
|
||||||
|
*.orig
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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]);
|
||||||
|
}
|
||||||
|
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]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
|
@ -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
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;
|
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
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