Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libstd: correct bigint's quot/rem, div/modulo #6013

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 57 additions & 56 deletions src/libstd/num/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,15 @@ impl Mul<BigUint, BigUint> for BigUint {

impl Quot<BigUint, BigUint> for BigUint {
fn quot(&self, other: &BigUint) -> BigUint {
let (d, _) = self.quot_rem(other);
return d;
let (q, _) = self.quot_rem(other);
return q;
}
}

impl Rem<BigUint, BigUint> for BigUint {
fn rem(&self, other: &BigUint) -> BigUint {
let (_, m) = self.quot_rem(other);
return m;
let (_, r) = self.quot_rem(other);
return r;
}
}

Expand Down Expand Up @@ -302,14 +302,14 @@ impl ToStrRadix for BigUint {
fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] {
let divider = BigUint::from_uint(base);
let mut result = ~[];
let mut r = n;
while r > divider {
let (d, r0) = r.quot_rem(&divider);
result += [r0.to_uint() as BigDigit];
r = d;
let mut m = n;
while m > divider {
let (d, m0) = m.div_mod(&divider);
result += [m0.to_uint() as BigDigit];
m = d;
}
if r.is_not_zero() {
result += [r.to_uint() as BigDigit];
if m.is_not_zero() {
result += [m.to_uint() as BigDigit];
}
return result;
}
Expand Down Expand Up @@ -384,7 +384,16 @@ pub impl BigUint {

fn abs(&self) -> BigUint { copy *self }

fn quot_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
fn div(&self, other: &BigUint) -> BigUint {
let (d, _) = self.div_mod(other);
return d;
}
fn modulo(&self, other: &BigUint) -> BigUint {
let (_, m) = self.div_mod(other);
return m;
}

fn div_mod(&self, other: &BigUint) -> (BigUint, BigUint) {
if other.is_zero() { fail!() }
if self.is_zero() { return (Zero::zero(), Zero::zero()); }
if *other == One::one() { return (copy *self, Zero::zero()); }
Expand All @@ -402,17 +411,17 @@ pub impl BigUint {
shift += 1;
}
assert!(shift < BigDigit::bits);
let (d, m) = quot_rem_inner(self << shift, other << shift);
let (d, m) = div_mod_inner(self << shift, other << shift);
return (d, m >> shift);

fn quot_rem_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
let mut r = a;
fn div_mod_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
let mut m = a;
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);
while m >= b {
let mut (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
let mut prod = b * d0;
while prod > r {
while prod > m {
d0 -= d_unit;
prod -= b_unit;
}
Expand All @@ -422,9 +431,9 @@ pub impl BigUint {
}
n = 1;
d += d0;
r -= prod;
m -= prod;
}
return (d, r);
return (d, m);
}

fn div_estimate(a: &BigUint, b: &BigUint, n: uint)
Expand Down Expand Up @@ -455,16 +464,8 @@ pub impl BigUint {
}
}

fn quot(&self, other: &BigUint) -> BigUint {
let (q, _) = self.quotrem(other);
return q;
}
fn rem(&self, other: &BigUint) -> BigUint {
let (_, r) = self.quotrem(other);
return r;
}
fn quotrem(&self, other: &BigUint) -> (BigUint, BigUint) {
self.quot_rem(other)
fn quot_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
self.div_mod(other)
}

fn is_zero(&self) -> bool { self.data.is_empty() }
Expand Down Expand Up @@ -739,15 +740,15 @@ impl Mul<BigInt, BigInt> for BigInt {

impl Quot<BigInt, BigInt> for BigInt {
fn quot(&self, other: &BigInt) -> BigInt {
let (d, _) = self.quot_rem(other);
return d;
let (q, _) = self.quot_rem(other);
return q;
}
}

impl Rem<BigInt, BigInt> for BigInt {
fn rem(&self, other: &BigInt) -> BigInt {
let (_, m) = self.quot_rem(other);
return m;
let (_, r) = self.quot_rem(other);
return r;
}
}

Expand Down Expand Up @@ -841,7 +842,16 @@ pub impl BigInt {
BigInt::from_biguint(Plus, copy self.data)
}

fn quot_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
fn div(&self, other: &BigInt) -> BigInt {
let (d, _) = self.div_mod(other);
return d;
}
fn modulo(&self, other: &BigInt) -> BigInt {
let (_, m) = self.div_mod(other);
return m;
}

fn div_mod(&self, other: &BigInt) -> (BigInt, BigInt) {
// m.sign == other.sign
let (d_ui, m_ui) = self.data.quot_rem(&other.data);
let d = BigInt::from_biguint(Plus, d_ui),
Expand All @@ -863,18 +873,9 @@ pub impl BigInt {
}
}

fn quot(&self, other: &BigInt) -> BigInt {
let (q, _) = self.quotrem(other);
return q;
}
fn rem(&self, other: &BigInt) -> BigInt {
let (_, r) = self.quotrem(other);
return r;
}

fn quotrem(&self, other: &BigInt) -> (BigInt, BigInt) {
fn quot_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
// r.sign == self.sign
let (q_ui, r_ui) = self.data.quotrem(&other.data);
let (q_ui, r_ui) = self.data.div_mod(&other.data);
let q = BigInt::from_biguint(Plus, q_ui);
let r = BigInt::from_biguint(Plus, r_ui);
match (self.sign, other.sign) {
Expand Down Expand Up @@ -1151,9 +1152,9 @@ mod biguint_tests {
];

static quot_rem_quadruples: &'static [(&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])]
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])]
= &[
(&[ 1], &[ 2], &[], &[1]),
(&[ 1, 1], &[ 2], &[-1/2+1], &[1]),
Expand Down Expand Up @@ -1517,9 +1518,9 @@ mod bigint_tests {
];

static quot_rem_quadruples: &'static [(&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])]
&'static [BigDigit],
&'static [BigDigit],
&'static [BigDigit])]
= &[
(&[ 1], &[ 2], &[], &[1]),
(&[ 1, 1], &[ 2], &[-1/2+1], &[1]),
Expand Down Expand Up @@ -1556,9 +1557,9 @@ mod bigint_tests {
}

#[test]
fn test_quot_rem() {
fn test_div_mod() {
fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
let (d, m) = a.quot_rem(b);
let (d, m) = a.div_mod(b);
if m.is_not_zero() {
assert!(m.sign == b.sign);
}
Expand Down Expand Up @@ -1607,9 +1608,9 @@ mod bigint_tests {


#[test]
fn test_quotrem() {
fn test_quot_rem() {
fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) {
let (q, r) = a.quotrem(b);
let (q, r) = a.quot_rem(b);
if r.is_not_zero() {
assert!(r.sign == a.sign);
}
Expand Down