Impl Zero, One of BigInt, BigUint

This commit is contained in:
gifnksm 2012-12-22 11:13:28 +09:00
parent 0e83d70cc1
commit 54b548795f

View File

@ -7,6 +7,7 @@ A BigInt is a combination of BigUint and Sign.
*/
use core::cmp::{Eq, Ord};
use core::num::{Num, Zero, One};
/**
A BigDigit is a BigUint's composing element.
@ -99,6 +100,14 @@ impl BigUint : Shr<uint, BigUint> {
}
}
impl BigUint : Zero {
static pure fn zero() -> BigUint { BigUint::from_at_vec(@[]) }
}
impl BigUint : One {
static pub pure fn one() -> BigUint { BigUint::from_at_vec(@[1]) }
}
impl BigUint : Num {
pure fn add(&self, other: &BigUint) -> BigUint {
let new_len = uint::max(self.data.len(), other.data.len());
@ -141,7 +150,7 @@ impl BigUint : Num {
}
pure fn mul(&self, other: &BigUint) -> BigUint {
if self.is_zero() || other.is_zero() { return BigUint::zero(); }
if self.is_zero() || other.is_zero() { return Zero::zero(); }
let s_len = self.data.len(), o_len = other.data.len();
if s_len == 1 { return mul_digit(other, self.data[0]); }
@ -167,7 +176,7 @@ impl BigUint : Num {
return ll + mm.shl_unit(half_len) + hh.shl_unit(half_len * 2);
pure fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint {
if n == 0 { return BigUint::zero(); }
if n == 0 { return Zero::zero(); }
if n == 1 { return *a; }
let mut carry = 0;
@ -192,7 +201,7 @@ impl BigUint : Num {
match a.cmp(&b) {
s if s < 0 => (s, b - a),
s if s > 0 => (s, a - b),
_ => (0, BigUint::zero())
_ => (0, Zero::zero())
}
}
}
@ -211,7 +220,7 @@ impl BigUint : Num {
}
static pure fn from_int(n: int) -> BigUint {
if (n < 0) { BigUint::zero() } else { BigUint::from_uint(n as uint) }
if (n < 0) { Zero::zero() } else { BigUint::from_uint(n as uint) }
}
}
@ -219,7 +228,7 @@ pub impl BigUint {
/// Creates and initializes an BigUint.
static pub pure fn from_uint(n: uint) -> BigUint {
match BigDigit::from_uint(n) {
(0, 0) => BigUint::zero(),
(0, 0) => Zero::zero(),
(0, n0) => BigUint::from_at_vec(@[n0]),
(n1, n0) => BigUint::from_at_vec(@[n0, n1])
}
@ -257,8 +266,8 @@ pub impl BigUint {
let base_num: BigUint = BigUint::from_uint(base);
let mut end = buf.len();
let mut n: BigUint = BigUint::zero();
let mut power: BigUint = BigUint::one();
let mut n: BigUint = Zero::zero();
let mut power: BigUint = One::one();
loop {
let start = uint::max(end, unit_len) - unit_len;
match uint::parse_bytes(vec::view(buf, start, end), radix) {
@ -273,8 +282,6 @@ pub impl BigUint {
}
}
static pub pure fn zero() -> BigUint { BigUint::from_at_vec(@[]) }
static pub pure fn one() -> BigUint { BigUint::from_at_vec(@[1]) }
pure fn abs(&self) -> BigUint { *self }
/// Compare two BigUint value.
@ -295,12 +302,12 @@ pub impl BigUint {
pure fn divmod(&self, other: &BigUint) -> (BigUint, BigUint) {
if other.is_zero() { fail }
if self.is_zero() { return (BigUint::zero(), BigUint::zero()); }
if *other == BigUint::one() { return (*self, BigUint::zero()); }
if self.is_zero() { return (Zero::zero(), Zero::zero()); }
if *other == One::one() { return (*self, Zero::zero()); }
match self.cmp(other) {
s if s < 0 => return (BigUint::zero(), *self),
0 => return (BigUint::one(), BigUint::zero()),
s if s < 0 => return (Zero::zero(), *self),
0 => return (One::one(), Zero::zero()),
_ => {} // Do nothing
}
@ -317,7 +324,7 @@ pub impl BigUint {
pure fn divmod_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
let mut r = a;
let mut d = BigUint::zero();
let mut d = Zero::zero::<BigUint>();
let mut n = 1;
while r >= b {
let mut (d0, d_unit, b_unit) = div_estimate(r, b, n);
@ -340,7 +347,7 @@ pub impl BigUint {
pure fn div_estimate(a: BigUint, b: BigUint, n: uint)
-> (BigUint, BigUint, BigUint) {
if a.data.len() < n {
return (BigUint::zero(), BigUint::zero(), a);
return (Zero::zero(), Zero::zero(), a);
}
let an = vec::view(a.data, a.data.len() - n, a.data.len());
@ -357,7 +364,7 @@ pub impl BigUint {
let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
return (BigUint::from_slice(d).shl_unit(shift),
BigUint::one().shl_unit(shift),
One::one::<BigUint>().shl_unit(shift),
b.shl_unit(shift));
}
}
@ -442,7 +449,7 @@ pub impl BigUint {
priv pure fn shr_unit(&self, n_unit: uint) -> BigUint {
if n_unit == 0 { return *self; }
if self.data.len() < n_unit { return BigUint::zero(); }
if self.data.len() < n_unit { return Zero::zero(); }
return BigUint::from_slice(
vec::view(self.data, n_unit, self.data.len())
);
@ -560,6 +567,18 @@ impl BigInt : Shr<uint, BigInt> {
}
}
impl BigInt : Zero {
static pub pure fn zero() -> BigInt {
BigInt::from_biguint(Zero, Zero::zero())
}
}
impl BigInt : One {
static pub pure fn one() -> BigInt {
BigInt::from_biguint(Plus, One::one())
}
}
impl BigInt : Num {
pure fn add(&self, other: &BigInt) -> BigInt {
match (self.sign, other.sign) {
@ -582,7 +601,7 @@ impl BigInt : Num {
s if s > 0 =>
BigInt::from_biguint(Plus, self.data - other.data),
_ =>
BigInt::zero()
Zero::zero()
},
(Plus, Minus) => self + (-*other),
(Minus, Plus) => -((-self) + *other),
@ -591,7 +610,7 @@ impl BigInt : Num {
}
pure fn mul(&self, other: &BigInt) -> BigInt {
match (self.sign, other.sign) {
(Zero, _) | (_, Zero) => BigInt::zero(),
(Zero, _) | (_, Zero) => Zero::zero(),
(Plus, Plus) | (Minus, Minus) => {
BigInt::from_biguint(Plus, self.data * other.data)
},
@ -628,7 +647,7 @@ impl BigInt : Num {
Minus, BigUint::from_uint(uint::max_value - (n as uint) + 1)
);
}
return BigInt::zero();
return Zero::zero();
}
}
@ -636,14 +655,14 @@ pub impl BigInt {
/// Creates and initializes an BigInt.
static pub pure fn from_biguint(sign: Sign, data: BigUint) -> BigInt {
if sign == Zero || data.is_zero() {
return BigInt { sign: Zero, data: BigUint::zero() };
return BigInt { sign: Zero, data: Zero::zero() };
}
return BigInt { sign: sign, data: data };
}
/// Creates and initializes an BigInt.
static pub pure fn from_uint(n: uint) -> BigInt {
if n == 0 { return BigInt::zero(); }
if n == 0 { return Zero::zero(); }
return BigInt::from_biguint(Plus, BigUint::from_uint(n));
}
@ -678,13 +697,6 @@ pub impl BigInt {
.map(|bu| BigInt::from_biguint(sign, *bu));
}
static pub pure fn zero() -> BigInt {
BigInt::from_biguint(Zero, BigUint::zero())
}
static pub pure fn one() -> BigInt {
BigInt::from_biguint(Plus, BigUint::one())
}
pure fn abs(&self) -> BigInt { BigInt::from_biguint(Plus, self.data) }
pure fn cmp(&self, other: &BigInt) -> int {
@ -709,14 +721,14 @@ pub impl BigInt {
(_, Zero) => fail,
(Plus, Plus) | (Zero, Plus) => (d, m),
(Plus, Minus) | (Zero, Minus) => if m.is_zero() {
(-d, BigInt::zero())
(-d, Zero::zero())
} else {
(-d - BigInt::one(), m + *other)
(-d - One::one(), m + *other)
},
(Minus, Plus) => if m.is_zero() {
(-d, BigInt::zero())
(-d, Zero::zero())
} else {
(-d - BigInt::one(), other - m)
(-d - One::one(), other - m)
},
(Minus, Minus) => (d, -m)
}
@ -876,11 +888,11 @@ mod biguint_tests {
#[test]
fn test_convert_int() {
fn check_conv(b: BigUint, i: int) {
assert b == num::Num::from_int(i);
assert b == Num::from_int(i);
assert b.to_int() == i;
}
check_conv(BigUint::zero(), 0);
check_conv(Zero::zero(), 0);
check_conv(BigUint::from_at_vec(@[1]), 1);
check_conv(BigUint::from_at_vec(@[-1]),
@ -902,7 +914,7 @@ mod biguint_tests {
assert b.to_uint() == u;
}
check_conv(BigUint::zero(), 0);
check_conv(Zero::zero(), 0);
check_conv(BigUint::from_at_vec(@[ 1]), 1);
check_conv(BigUint::from_at_vec(@[-1]),
uint::max_value >> BigDigit::bits);
@ -1022,10 +1034,10 @@ mod biguint_tests {
let c = BigUint::from_slice(cVec);
if a.is_not_zero() {
assert c.divmod(&a) == (b, BigUint::zero());
assert c.divmod(&a) == (b, Zero::zero());
}
if b.is_not_zero() {
assert c.divmod(&b) == (a, BigUint::zero());
assert c.divmod(&b) == (a, Zero::zero());
}
}
@ -1041,7 +1053,7 @@ mod biguint_tests {
}
fn to_str_pairs() -> ~[ (BigUint, ~[(uint, ~str)]) ] {
~[( BigUint::zero(), ~[
~[( Zero::zero(), ~[
(2, ~"0"), (3, ~"0")
]), ( BigUint::from_slice([ 0xff ]), ~[
(2, ~"11111111"),
@ -1108,7 +1120,7 @@ mod biguint_tests {
#[test]
fn test_factor() {
fn factor(n: uint) -> BigUint {
let mut f= BigUint::one();
let mut f= One::one::<BigUint>();
for uint::range(2, n + 1) |i| {
f *= BigUint::from_uint(i);
}
@ -1130,12 +1142,12 @@ mod bigint_tests {
fn test_from_biguint() {
assert BigInt::from_biguint(Plus, BigUint::from_uint(1)) ==
BigInt { sign: Plus, data: BigUint::from_uint(1) };
assert BigInt::from_biguint(Plus, BigUint::zero()) ==
BigInt { sign: Zero, data: BigUint::zero() };
assert BigInt::from_biguint(Plus, Zero::zero()) ==
BigInt { sign: Zero, data: Zero::zero() };
assert BigInt::from_biguint(Minus, BigUint::from_uint(1)) ==
BigInt { sign: Minus, data: BigUint::from_uint(1) };
assert BigInt::from_biguint(Zero, BigUint::from_uint(1)) ==
BigInt { sign: Zero, data: BigUint::zero() };
BigInt { sign: Zero, data: Zero::zero() };
}
#[test]
@ -1144,7 +1156,7 @@ mod bigint_tests {
.map(|data| BigUint::from_slice(*data));
let nums: ~[BigInt]
= vec::reversed(uints).map(|bu| BigInt::from_biguint(Minus, *bu))
+ [ BigInt::zero() ]
+ [ Zero::zero() ]
+ uints.map(|bu| BigInt::from_biguint(Plus, *bu));
for nums.eachi |i, ni| {
@ -1183,12 +1195,12 @@ mod bigint_tests {
#[test]
fn test_convert_int() {
fn check_conv(b: BigInt, i: int) {
assert b == num::Num::from_int(i);
assert b == Num::from_int(i);
assert b.to_int() == i;
}
check_conv(BigInt::zero(), 0);
check_conv(BigInt::one(), 1);
check_conv(Zero::zero(), 0);
check_conv(One::one(), 1);
check_conv(
BigInt::from_biguint(
Plus, BigUint::from_uint(int::max_value as uint)),
@ -1220,8 +1232,8 @@ mod bigint_tests {
assert b.to_uint() == u;
}
check_conv(BigInt::zero(), 0);
check_conv(BigInt::one(), 1);
check_conv(Zero::zero(), 0);
check_conv(One::one(), 1);
check_conv(
BigInt::from_biguint(Plus, BigUint::from_uint(uint::max_value)),
@ -1265,7 +1277,7 @@ mod bigint_tests {
assert a + (-c) == (-b);
assert b + (-c) == (-a);
assert (-a) + (-b) == (-c);
assert a + (-a) == BigInt::zero();
assert a + (-a) == Zero::zero();
}
}
@ -1284,7 +1296,7 @@ mod bigint_tests {
assert b - (-a) == c;
assert a - (-b) == c;
assert (-c) - (-a) == (-b);
assert a - a == BigInt::zero();
assert a - a == Zero::zero();
}
}
@ -1366,17 +1378,17 @@ mod bigint_tests {
check_divmod_sub(-a, -b);
if d.is_zero() {
assert a.divmod(&b) == (c, BigInt::zero());
assert (-a).divmod(&b) == (-c, BigInt::zero());
assert (a).divmod(&-b) == (-c, BigInt::zero());
assert (-a).divmod(&-b) == (c, BigInt::zero());
assert a.divmod(&b) == (c, Zero::zero());
assert (-a).divmod(&b) == (-c, Zero::zero());
assert (a).divmod(&-b) == (-c, Zero::zero());
assert (-a).divmod(&-b) == (c, Zero::zero());
} else {
// a == bc + d
assert a.divmod(&b) == (c, d);
// a == (-b)(-c - 1) + (d - b)
assert a.divmod(&-b) == (-c - BigInt::one(), d - b);
assert a.divmod(&-b) == (-c - One::one(), d - b);
// (-a) == b (-c - 1) + (b - d)
assert (-a).divmod(&b) == (-c - BigInt::one(), b - d);
assert (-a).divmod(&b) == (-c - One::one(), b - d);
// (-a) == (-b)(c) - d
assert (-a).divmod(&-b) == (c, -d);
}
@ -1387,8 +1399,8 @@ mod bigint_tests {
let b = BigInt::from_slice(Plus, bVec);
let c = BigInt::from_slice(Plus, cVec);
if a.is_not_zero() { check_divmod(c, a, b, BigInt::zero()); }
if b.is_not_zero() { check_divmod(c, b, a, BigInt::zero()); }
if a.is_not_zero() { check_divmod(c, a, b, Zero::zero()); }
if b.is_not_zero() { check_divmod(c, b, a, Zero::zero()); }
}
for divmod_quadruples.each |elm| {
@ -1422,10 +1434,10 @@ mod bigint_tests {
check_quotrem_sub(-a, -b);
if d.is_zero() {
assert a.quotrem(&b) == (c, BigInt::zero());
assert (-a).quotrem(&b) == (-c, BigInt::zero());
assert (a).quotrem(&-b) == (-c, BigInt::zero());
assert (-a).quotrem(&-b) == (c, BigInt::zero());
assert a.quotrem(&b) == (c, Zero::zero());
assert (-a).quotrem(&b) == (-c, Zero::zero());
assert (a).quotrem(&-b) == (-c, Zero::zero());
assert (-a).quotrem(&-b) == (c, Zero::zero());
} else {
// a == bc + d
assert a.quotrem(&b) == (c, d);
@ -1443,8 +1455,8 @@ mod bigint_tests {
let b = BigInt::from_slice(Plus, bVec);
let c = BigInt::from_slice(Plus, cVec);
if a.is_not_zero() { check_quotrem(c, a, b, BigInt::zero()); }
if b.is_not_zero() { check_quotrem(c, b, a, BigInt::zero()); }
if a.is_not_zero() { check_quotrem(c, a, b, Zero::zero()); }
if b.is_not_zero() { check_quotrem(c, b, a, Zero::zero()); }
}
for divmod_quadruples.each |elm| {
@ -1464,9 +1476,9 @@ mod bigint_tests {
fn test_to_str_radix() {
assert BigInt::from_biguint(Plus, BigUint::from_uint(10))
.to_str_radix(10) == ~"10";
assert BigInt::one().to_str_radix(10) == ~"1";
assert BigInt::zero().to_str_radix(10) == ~"0";
assert (-BigInt::one()).to_str_radix(10) == ~"-1";
assert One::one::<BigInt>().to_str_radix(10) == ~"1";
assert Zero::zero::<BigInt>().to_str_radix(10) == ~"0";
assert (-One::one::<BigInt>()).to_str_radix(10) == ~"-1";
assert BigInt::from_biguint(Minus, BigUint::from_uint(10))
.to_str_radix(10) == ~"-10";
}
@ -1476,16 +1488,16 @@ mod bigint_tests {
fn test_from_str_radix() {
assert BigInt::from_biguint(Plus, BigUint::from_uint(10)) ==
BigInt::from_str_radix(~"10", 10).get();
assert BigInt::one()== BigInt::from_str_radix(~"1", 10).get();
assert BigInt::zero() == BigInt::from_str_radix(~"0", 10).get();
assert (-BigInt::one()) == BigInt::from_str_radix(~"-1", 10).get();
assert One::one::<BigInt>() == BigInt::from_str_radix(~"1", 10).get();
assert Zero::zero::<BigInt>() == BigInt::from_str_radix(~"0", 10).get();
assert (-One::one::<BigInt>()) == BigInt::from_str_radix(~"-1", 10).get();
assert BigInt::from_biguint(Minus, BigUint::from_uint(10)) ==
BigInt::from_str_radix(~"-10", 10).get();
assert BigInt::from_str_radix(~"Z", 10) == None;
assert BigInt::from_str_radix(~"_", 2) == None;
assert BigInt::from_str_radix(~"-1", 10) ==
Some(BigInt::from_biguint(Minus, BigUint::one()));
Some(BigInt::from_biguint(Minus, One::one()));
}
#[test]
@ -1494,7 +1506,7 @@ mod bigint_tests {
BigInt::from_at_vec(Minus, @[1, 1, 1]);
assert -BigInt::from_at_vec(Minus, @[1, 1, 1]) ==
BigInt::from_at_vec(Plus, @[1, 1, 1]);
assert -BigInt::zero() == BigInt::zero();
assert -Zero::zero::<BigInt>() == Zero::zero::<BigInt>();
}
}