use num_bigint::BigUint; use num_bigint::Sign::{Minus, NoSign, Plus}; use num_bigint::{BigInt, ToBigInt};
use std::cmp::Ordering::{Equal, Greater, Less}; use std::collections::hash_map::RandomState; use std::hash::{BuildHasher, Hash, Hasher}; use std::iter::repeat; use std::ops::Neg; use std::{f32, f64};
use num_integer::Integer; use num_traits::{
pow, Euclid, FromBytes, FromPrimitive, Num, One, Pow, Signed, ToBytes, ToPrimitive, Zero,
};
// Test with leading/trailing zero bytes and a full BigDigit of value 0 let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap();
assert_eq!(b.to_bytes_be(), (Plus, vec![1, 0, 0, 0, 0, 0, 0, 2, 0]));
}
// Test with leading/trailing zero bytes and a full BigDigit of value 0 let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap();
assert_eq!(b.to_bytes_le(), (Plus, vec![0, 2, 0, 0, 0, 0, 0, 0, 1]));
}
#[test] fn test_to_signed_bytes_le() { fn check(s: &str, result: Vec<u8>) { let b = BigInt::parse_bytes(s.as_bytes(), 10).unwrap();
assert_eq!(b.to_signed_bytes_le(), result);
assert_eq!(<BigInt as ToBytes>::to_le_bytes(&b), result);
}
#[test] fn test_signed_bytes_be_round_trip() { for i in -0x1FFFF..0x20000 { let n = BigInt::from(i);
assert_eq!(n, BigInt::from_signed_bytes_be(&n.to_signed_bytes_be()));
}
}
#[test] fn test_signed_bytes_le_round_trip() { for i in -0x1FFFF..0x20000 { let n = BigInt::from(i);
assert_eq!(n, BigInt::from_signed_bytes_le(&n.to_signed_bytes_le()));
}
}
#[test] fn test_cmp() { let vs: [&[u32]; 4] = [&[2_u32], &[1, 1], &[style='color: green'>2, 1], &[1, 1, 1]]; letmut nums = Vec::new(); for s in vs.iter().rev() {
nums.push(BigInt::from_slice(Minus, *s));
}
nums.push(Zero::zero());
nums.extend(vs.iter().map(|s| BigInt::from_slice(Plus, *s)));
for (i, ni) in nums.iter().enumerate() { for (j0, nj) in nums[i..].iter().enumerate() { let j = i + j0; if i == j {
assert_eq!(ni.cmp(nj), Equal);
assert_eq!(nj.cmp(ni), Equal);
assert_eq!(ni, nj);
assert!(!(ni != nj));
assert!(ni <= nj);
assert!(ni >= nj);
assert!(!(ni < nj));
assert!(!(ni > nj));
} else {
assert_eq!(ni.cmp(nj), Less);
assert_eq!(nj.cmp(ni), Greater);
#[test] fn test_hash() { let a = BigInt::new(NoSign, vec![]); let b = BigInt::new(NoSign, vec![0]); let c = BigInt::new(Plus, vec![1]); let d = BigInt::new(Plus, vec![1, 0, 0, 0, 0, 0]); let e = BigInt::new(Plus, vec![0, 0, 0, 0, 0, 1]); let f = BigInt::new(Minus, vec![1]);
assert!(hash(&a) == hash(&b));
assert!(hash(&b) != hash(&c));
assert!(hash(&c) == hash(&d));
assert!(hash(&d) != hash(&e));
assert!(hash(&c) != hash(&f));
}
// keeping all 24 digits with the bits at different offsets to the BigDigits let x: u32 = 0b00000000101111011111011011011101; letmut f = x as f32; letmut b = BigInt::from(x); for _ in0..64 {
check(&b, f);
f *= 2.0;
b <<= 1;
}
// this number when rounded to f64 then f32 isn't the same as when rounded straight to f32 letmut n: i64 = 0b0000000000111111111111111111111111011111111111111111111111111111;
assert!((n as f64) as f32 != n as f32);
assert_eq!(BigInt::from(n).to_f32(), Some(n as f32));
n = -n;
assert!((n as f64) as f32 != n as f32);
assert_eq!(BigInt::from(n).to_f32(), Some(n as f32));
// test rounding up with the bits at different offsets to the BigDigits letmut f = ((1u64 << 25) - 1) as f32; letmut b = BigInt::from(1u64 << 25); for _ in0..64 {
assert_eq!(b.to_f32(), Some(f));
f *= 2.0;
b <<= 1;
}
// test correct ties-to-even rounding let weird: i128 = (1i128 << 100) + (1i128 << (100 - f32::MANTISSA_DIGITS));
assert_ne!(weird as f32, (weird + 1) as f32);
assert_eq!(BigInt::from(weird).to_f32(), Some(weird as f32));
assert_eq!(BigInt::from(weird + 1).to_f32(), Some((weird + 1) as f32));
// keeping all 53 digits with the bits at different offsets to the BigDigits let x: u64 = 0b0000000000011110111110110111111101110111101111011111011011011101; letmut f = x as f64; letmut b = BigInt::from(x); for _ in0..128 {
check(&b, f);
f *= 2.0;
b <<= 1;
}
// test rounding up with the bits at different offsets to the BigDigits letmut f = ((1u64 << 54) - 1) as f64; letmut b = BigInt::from(1u64 << 54); for _ in0..128 {
assert_eq!(b.to_f64(), Some(f));
f *= 2.0;
b <<= 1;
}
// test correct ties-to-even rounding let weird: i128 = (1i128 << 100) + (1i128 << (100 - f64::MANTISSA_DIGITS));
assert_ne!(weird as f64, (weird + 1) as f64);
assert_eq!(BigInt::from(weird).to_f64(), Some(weird as f64));
assert_eq!(BigInt::from(weird + 1).to_f64(), Some((weird + 1) as f64));
#[test] fn test_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_op!(a + b == c);
assert_op!(b + a == c);
assert_op!(c + na == b);
assert_op!(c + nb == a);
assert_op!(a + nc == nb);
assert_op!(b + nc == na);
assert_op!(na + nb == nc);
assert_op!(a + na == BigInt::zero());
assert_assign_op!(a += b == c);
assert_assign_op!(b += a == c);
assert_assign_op!(c += na == b);
assert_assign_op!(c += nb == a);
assert_assign_op!(a += nc == nb);
assert_assign_op!(b += nc == na);
assert_assign_op!(na += nb == nc);
assert_assign_op!(a += na == BigInt::zero());
}
}
#[test] fn test_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_op!(c - a == b);
assert_op!(c - b == a);
assert_op!(nb - a == nc);
assert_op!(na - b == nc);
assert_op!(b - na == c);
assert_op!(a - nb == c);
assert_op!(nc - na == nb);
assert_op!(a - a == BigInt::zero());
assert_assign_op!(c -= a == b);
assert_assign_op!(c -= b == a);
assert_assign_op!(nb -= a == nc);
assert_assign_op!(na -= b == nc);
assert_assign_op!(b -= na == c);
assert_assign_op!(a -= nb == c);
assert_assign_op!(nc -= na == nb);
assert_assign_op!(a -= a == BigInt::zero());
}
}
#[test] fn test_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_op!(a * b == c);
assert_op!(b * a == c);
assert_op!(na * nb == c);
assert_op!(na * b == nc);
assert_op!(nb * a == nc);
assert_assign_op!(a *= b == c);
assert_assign_op!(b *= a == c);
assert_assign_op!(na *= nb == c);
assert_assign_op!(na *= b == nc);
assert_assign_op!(nb *= a == nc);
}
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 b = BigInt::from_slice(Plus, b_vec); let c = BigInt::from_slice(Plus, c_vec); let d = BigInt::from_slice(Plus, d_vec);
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.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 = BigInt::from_slice(Plus, a_vec); let b = BigInt::from_slice(Plus, b_vec); let c = BigInt::from_slice(Plus, c_vec); let d = BigInt::from_slice(Plus, d_vec);
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);
assert_assign_op!(a /= b == ans_q);
assert_assign_op!(a %= b == ans_r);
}
fn check(a: &BigInt, b: &BigInt, q: &BigInt, r: &BigInt) {
check_sub(a, b, q, r);
check_sub(a, &b.neg(), &q.neg(), r);
check_sub(&a.neg(), b, &q.neg(), &r.neg());
check_sub(&a.neg(), &b.neg(), q, &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.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 = BigInt::from_slice(Plus, a_vec); let b = BigInt::from_slice(Plus, b_vec); let c = BigInt::from_slice(Plus, c_vec); let d = BigInt::from_slice(Plus, d_vec);
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.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 = BigInt::from_slice(Plus, a_vec); let b = BigInt::from_slice(Plus, b_vec); let c = BigInt::from_slice(Plus, c_vec); let d = BigInt::from_slice(Plus, d_vec);
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.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 = BigInt::from_slice(Plus, a_vec); let b = BigInt::from_slice(Plus, b_vec); let c = BigInt::from_slice(Plus, c_vec); let d = BigInt::from_slice(Plus, d_vec);
if !b.is_zero() {
check(&a, &b, &c, &d);
}
}
}
#[test] fn test_checked_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);
#[test] fn test_checked_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);
#[test] fn test_checked_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);
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 b = BigInt::from_slice(Plus, b_vec); let c = BigInt::from_slice(Plus, c_vec); let d = BigInt::from_slice(Plus, d_vec);
assert!(a == b.checked_mul(&c).unwrap() + &d);
assert!(a == c.checked_mul(&b).unwrap() + &d);
}
} #[test] fn test_checked_div() { 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);
// issue 10522, this hit an edge case that caused it to // attempt to allocate a vector of size (-1u) == huge. let x: BigInt = format!("1{}", repeat("0").take(36).collect::<String>())
.parse()
.unwrap(); let _y = x.to_string();
}
#[test] fn test_lower_hex() { let a = BigInt::parse_bytes(b"A", 16).unwrap(); let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap();
#[test] fn test_upper_hex() { let a = BigInt::parse_bytes(b"A", 16).unwrap(); let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap();
#[test] fn test_octal() { let a = BigInt::parse_bytes(b"A", 16).unwrap(); let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap();
#[test] fn test_display() { let a = BigInt::parse_bytes(b"A", 16).unwrap(); let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.