1
Fork 0

auto merge of #12672 : korenchkin/rust/checked-bigint, r=alexcrichton

This commit is contained in:
bors 2014-03-03 22:01:40 -08:00
commit 062e950ae8

View file

@ -21,6 +21,7 @@ use Integer;
use std::cmp; use std::cmp;
use std::fmt; use std::fmt;
use std::from_str::FromStr; use std::from_str::FromStr;
use std::num::CheckedDiv;
use std::num::{Bitwise, ToPrimitive, FromPrimitive}; use std::num::{Bitwise, ToPrimitive, FromPrimitive};
use std::num::{Zero, One, ToStrRadix, FromStrRadix}; use std::num::{Zero, One, ToStrRadix, FromStrRadix};
use std::rand::Rng; use std::rand::Rng;
@ -338,6 +339,40 @@ impl Neg<BigUint> for BigUint {
fn neg(&self) -> BigUint { fail!() } fn neg(&self) -> BigUint { fail!() }
} }
impl CheckedAdd for BigUint {
#[inline]
fn checked_add(&self, v: &BigUint) -> Option<BigUint> {
return Some(self.add(v));
}
}
impl CheckedSub for BigUint {
#[inline]
fn checked_sub(&self, v: &BigUint) -> Option<BigUint> {
if *self < *v {
return None;
}
return Some(self.sub(v));
}
}
impl CheckedMul for BigUint {
#[inline]
fn checked_mul(&self, v: &BigUint) -> Option<BigUint> {
return Some(self.mul(v));
}
}
impl CheckedDiv for BigUint {
#[inline]
fn checked_div(&self, v: &BigUint) -> Option<BigUint> {
if v.is_zero() {
return None;
}
return Some(self.div(v));
}
}
impl Integer for BigUint { impl Integer for BigUint {
#[inline] #[inline]
fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) { fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
@ -1053,6 +1088,38 @@ impl Neg<BigInt> for BigInt {
} }
} }
impl CheckedAdd for BigInt {
#[inline]
fn checked_add(&self, v: &BigInt) -> Option<BigInt> {
return Some(self.add(v));
}
}
impl CheckedSub for BigInt {
#[inline]
fn checked_sub(&self, v: &BigInt) -> Option<BigInt> {
return Some(self.sub(v));
}
}
impl CheckedMul for BigInt {
#[inline]
fn checked_mul(&self, v: &BigInt) -> Option<BigInt> {
return Some(self.mul(v));
}
}
impl CheckedDiv for BigInt {
#[inline]
fn checked_div(&self, v: &BigInt) -> Option<BigInt> {
if v.is_zero() {
return None;
}
return Some(self.div(v));
}
}
impl Integer for BigInt { impl Integer for BigInt {
#[inline] #[inline]
fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) { fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
@ -1402,6 +1469,7 @@ mod biguint_tests {
use std::i64; use std::i64;
use std::num::{Zero, One, FromStrRadix, ToStrRadix}; use std::num::{Zero, One, FromStrRadix, ToStrRadix};
use std::num::{ToPrimitive, FromPrimitive}; use std::num::{ToPrimitive, FromPrimitive};
use std::num::CheckedDiv;
use std::rand::{task_rng}; use std::rand::{task_rng};
use std::str; use std::str;
use std::u64; use std::u64;
@ -1822,6 +1890,82 @@ mod biguint_tests {
} }
} }
#[test]
fn test_checked_add() {
for elm in sum_triples.iter() {
let (aVec, bVec, cVec) = *elm;
let a = BigUint::from_slice(aVec);
let b = BigUint::from_slice(bVec);
let c = BigUint::from_slice(cVec);
assert!(a.checked_add(&b).unwrap() == c);
assert!(b.checked_add(&a).unwrap() == c);
}
}
#[test]
fn test_checked_sub() {
for elm in sum_triples.iter() {
let (aVec, bVec, cVec) = *elm;
let a = BigUint::from_slice(aVec);
let b = BigUint::from_slice(bVec);
let c = BigUint::from_slice(cVec);
assert!(c.checked_sub(&a).unwrap() == b);
assert!(c.checked_sub(&b).unwrap() == a);
if a > c {
assert!(a.checked_sub(&c).is_none());
}
if b > c {
assert!(b.checked_sub(&c).is_none());
}
}
}
#[test]
fn test_checked_mul() {
for elm in mul_triples.iter() {
let (aVec, bVec, cVec) = *elm;
let a = BigUint::from_slice(aVec);
let b = BigUint::from_slice(bVec);
let c = BigUint::from_slice(cVec);
assert!(a.checked_mul(&b).unwrap() == c);
assert!(b.checked_mul(&a).unwrap() == c);
}
for elm in div_rem_quadruples.iter() {
let (aVec, bVec, cVec, dVec) = *elm;
let a = BigUint::from_slice(aVec);
let b = BigUint::from_slice(bVec);
let c = BigUint::from_slice(cVec);
let d = BigUint::from_slice(dVec);
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 (aVec, bVec, cVec) = *elm;
let a = BigUint::from_slice(aVec);
let b = BigUint::from_slice(bVec);
let c = BigUint::from_slice(cVec);
if !a.is_zero() {
assert!(c.checked_div(&a).unwrap() == b);
}
if !b.is_zero() {
assert!(c.checked_div(&b).unwrap() == a);
}
assert!(c.checked_div(&Zero::zero()).is_none());
}
}
#[test] #[test]
fn test_gcd() { fn test_gcd() {
fn check(a: uint, b: uint, c: uint) { fn check(a: uint, b: uint, c: uint) {
@ -2058,6 +2202,7 @@ mod bigint_tests {
use std::cmp::{Less, Equal, Greater}; use std::cmp::{Less, Equal, Greater};
use std::i64; use std::i64;
use std::num::CheckedDiv;
use std::num::{Zero, One, FromStrRadix, ToStrRadix}; use std::num::{Zero, One, FromStrRadix, ToStrRadix};
use std::num::{ToPrimitive, FromPrimitive}; use std::num::{ToPrimitive, FromPrimitive};
use std::rand::{task_rng}; use std::rand::{task_rng};
@ -2399,6 +2544,94 @@ mod bigint_tests {
} }
} }
#[test]
fn test_checked_add() {
for elm in sum_triples.iter() {
let (aVec, bVec, cVec) = *elm;
let a = BigInt::from_slice(Plus, aVec);
let b = BigInt::from_slice(Plus, bVec);
let c = BigInt::from_slice(Plus, cVec);
assert!(a.checked_add(&b).unwrap() == c);
assert!(b.checked_add(&a).unwrap() == c);
assert!(c.checked_add(&(-a)).unwrap() == b);
assert!(c.checked_add(&(-b)).unwrap() == a);
assert!(a.checked_add(&(-c)).unwrap() == (-b));
assert!(b.checked_add(&(-c)).unwrap() == (-a));
assert!((-a).checked_add(&(-b)).unwrap() == (-c))
assert!(a.checked_add(&(-a)).unwrap() == Zero::zero());
}
}
#[test]
fn test_checked_sub() {
for elm in sum_triples.iter() {
let (aVec, bVec, cVec) = *elm;
let a = BigInt::from_slice(Plus, aVec);
let b = BigInt::from_slice(Plus, bVec);
let c = BigInt::from_slice(Plus, cVec);
assert!(c.checked_sub(&a).unwrap() == b);
assert!(c.checked_sub(&b).unwrap() == a);
assert!((-b).checked_sub(&a).unwrap() == (-c))
assert!((-a).checked_sub(&b).unwrap() == (-c))
assert!(b.checked_sub(&(-a)).unwrap() == c);
assert!(a.checked_sub(&(-b)).unwrap() == c);
assert!((-c).checked_sub(&(-a)).unwrap() == (-b));
assert!(a.checked_sub(&a).unwrap() == Zero::zero());
}
}
#[test]
fn test_checked_mul() {
for elm in mul_triples.iter() {
let (aVec, bVec, cVec) = *elm;
let a = BigInt::from_slice(Plus, aVec);
let b = BigInt::from_slice(Plus, bVec);
let c = BigInt::from_slice(Plus, cVec);
assert!(a.checked_mul(&b).unwrap() == c);
assert!(b.checked_mul(&a).unwrap() == c);
assert!((-a).checked_mul(&b).unwrap() == -c);
assert!((-b).checked_mul(&a).unwrap() == -c);
}
for elm in div_rem_quadruples.iter() {
let (aVec, bVec, cVec, dVec) = *elm;
let a = BigInt::from_slice(Plus, aVec);
let b = BigInt::from_slice(Plus, bVec);
let c = BigInt::from_slice(Plus, cVec);
let d = BigInt::from_slice(Plus, dVec);
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 (aVec, bVec, cVec) = *elm;
let a = BigInt::from_slice(Plus, aVec);
let b = BigInt::from_slice(Plus, bVec);
let c = BigInt::from_slice(Plus, cVec);
if !a.is_zero() {
assert!(c.checked_div(&a).unwrap() == b);
assert!((-c).checked_div(&(-a)).unwrap() == b);
assert!((-c).checked_div(&a).unwrap() == -b);
}
if !b.is_zero() {
assert!(c.checked_div(&b).unwrap() == a);
assert!((-c).checked_div(&(-b)).unwrap() == a);
assert!((-c).checked_div(&b).unwrap() == -a);
}
assert!(c.checked_div(&Zero::zero()).is_none());
assert!((-c).checked_div(&Zero::zero()).is_none());
}
}
#[test] #[test]
fn test_gcd() { fn test_gcd() {
fn check(a: int, b: int, c: int) { fn check(a: int, b: int, c: int) {