From 54b548795f603bb790853ff6dd0190dc3f32b7b9 Mon Sep 17 00:00:00 2001 From: gifnksm Date: Sat, 22 Dec 2012 11:13:28 +0900 Subject: [PATCH] Impl Zero, One of BigInt, BigUint --- src/libstd/bigint.rs | 158 +++++++++++++++++++++++-------------------- 1 file changed, 85 insertions(+), 73 deletions(-) diff --git a/src/libstd/bigint.rs b/src/libstd/bigint.rs index 4d4bfb6bd7ba..1e772c0a585a 100644 --- a/src/libstd/bigint.rs +++ b/src/libstd/bigint.rs @@ -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 { } } +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::(); 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::().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 { } } +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::(); 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::().to_str_radix(10) == ~"1"; + assert Zero::zero::().to_str_radix(10) == ~"0"; + assert (-One::one::()).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::from_str_radix(~"1", 10).get(); + assert Zero::zero::() == BigInt::from_str_radix(~"0", 10).get(); + assert (-One::one::()) == 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::() == Zero::zero::(); } }