Merge #330
330: Implement *Assign for BigUint r=cuviper a=Darksonn Not only does this change increase convenience of use, it also allows adding a `&BigUint` to a `&mut BigUint` without allocating (if not necessary) or tricks such as: fn add(a: &mut BigUint, b: &BigUint) { let aa = mem::replace(a, BigUint::from_slice(&[])); // BigUint::from_slice(&[]) does not allocate *a = aa + b; } With this change: fn add(a: &mut BigUint, b: &BigUint) { *a += b; } It would make sense to add the same functionality to `BigInt`, but it uses some macros to handle the signs, and I'm not sure how to change the macros in order to perform this change.
This commit is contained in:
commit
8646be5a95
|
@ -1,7 +1,9 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub};
|
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub,
|
||||||
|
AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign,
|
||||||
|
MulAssign, RemAssign, ShlAssign, ShrAssign, SubAssign};
|
||||||
use std::str::{self, FromStr};
|
use std::str::{self, FromStr};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -268,54 +270,74 @@ impl Num for BigUint {
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_all_binop_to_val_ref_commutative!(impl BitAnd for BigUint, bitand);
|
forward_all_binop_to_val_ref_commutative!(impl BitAnd for BigUint, bitand);
|
||||||
|
forward_val_assign!(impl BitAndAssign for BigUint, bitand_assign);
|
||||||
|
|
||||||
impl<'a> BitAnd<&'a BigUint> for BigUint {
|
impl<'a> BitAnd<&'a BigUint> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitand(self, other: &BigUint) -> BigUint {
|
fn bitand(mut self, other: &BigUint) -> BigUint {
|
||||||
let mut data = self.data;
|
self &= other;
|
||||||
for (ai, &bi) in data.iter_mut().zip(other.data.iter()) {
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> BitAndAssign<&'a BigUint> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn bitand_assign(&mut self, other: &BigUint) {
|
||||||
|
for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) {
|
||||||
*ai &= bi;
|
*ai &= bi;
|
||||||
}
|
}
|
||||||
data.truncate(other.data.len());
|
self.data.truncate(other.data.len());
|
||||||
BigUint::new(data)
|
self.normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_all_binop_to_val_ref_commutative!(impl BitOr for BigUint, bitor);
|
forward_all_binop_to_val_ref_commutative!(impl BitOr for BigUint, bitor);
|
||||||
|
forward_val_assign!(impl BitOrAssign for BigUint, bitor_assign);
|
||||||
|
|
||||||
impl<'a> BitOr<&'a BigUint> for BigUint {
|
impl<'a> BitOr<&'a BigUint> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
fn bitor(self, other: &BigUint) -> BigUint {
|
fn bitor(mut self, other: &BigUint) -> BigUint {
|
||||||
let mut data = self.data;
|
self |= other;
|
||||||
for (ai, &bi) in data.iter_mut().zip(other.data.iter()) {
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> BitOrAssign<&'a BigUint> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn bitor_assign(&mut self, other: &BigUint) {
|
||||||
|
for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) {
|
||||||
*ai |= bi;
|
*ai |= bi;
|
||||||
}
|
}
|
||||||
if other.data.len() > data.len() {
|
if other.data.len() > self.data.len() {
|
||||||
let extra = &other.data[data.len()..];
|
let extra = &other.data[self.data.len()..];
|
||||||
data.extend(extra.iter().cloned());
|
self.data.extend(extra.iter().cloned());
|
||||||
}
|
}
|
||||||
BigUint::new(data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_all_binop_to_val_ref_commutative!(impl BitXor for BigUint, bitxor);
|
forward_all_binop_to_val_ref_commutative!(impl BitXor for BigUint, bitxor);
|
||||||
|
forward_val_assign!(impl BitXorAssign for BigUint, bitxor_assign);
|
||||||
|
|
||||||
impl<'a> BitXor<&'a BigUint> for BigUint {
|
impl<'a> BitXor<&'a BigUint> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
fn bitxor(self, other: &BigUint) -> BigUint {
|
fn bitxor(mut self, other: &BigUint) -> BigUint {
|
||||||
let mut data = self.data;
|
self ^= other;
|
||||||
for (ai, &bi) in data.iter_mut().zip(other.data.iter()) {
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> BitXorAssign<&'a BigUint> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn bitxor_assign(&mut self, other: &BigUint) {
|
||||||
|
for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) {
|
||||||
*ai ^= bi;
|
*ai ^= bi;
|
||||||
}
|
}
|
||||||
if other.data.len() > data.len() {
|
if other.data.len() > self.data.len() {
|
||||||
let extra = &other.data[data.len()..];
|
let extra = &other.data[self.data.len()..];
|
||||||
data.extend(extra.iter().cloned());
|
self.data.extend(extra.iter().cloned());
|
||||||
}
|
}
|
||||||
BigUint::new(data)
|
self.normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +349,6 @@ impl Shl<usize> for BigUint {
|
||||||
biguint_shl(Cow::Owned(self), rhs)
|
biguint_shl(Cow::Owned(self), rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Shl<usize> for &'a BigUint {
|
impl<'a> Shl<usize> for &'a BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
|
@ -337,6 +358,13 @@ impl<'a> Shl<usize> for &'a BigUint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ShlAssign<usize> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn shl_assign(&mut self, rhs: usize) {
|
||||||
|
*self = biguint_shl(Cow::Borrowed(&*self), rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Shr<usize> for BigUint {
|
impl Shr<usize> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
|
@ -345,7 +373,6 @@ impl Shr<usize> for BigUint {
|
||||||
biguint_shr(Cow::Owned(self), rhs)
|
biguint_shr(Cow::Owned(self), rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Shr<usize> for &'a BigUint {
|
impl<'a> Shr<usize> for &'a BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
|
@ -355,6 +382,13 @@ impl<'a> Shr<usize> for &'a BigUint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ShrAssign<usize> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn shr_assign(&mut self, rhs: usize) {
|
||||||
|
*self = biguint_shr(Cow::Borrowed(&*self), rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Zero for BigUint {
|
impl Zero for BigUint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero() -> BigUint {
|
fn zero() -> BigUint {
|
||||||
|
@ -377,11 +411,19 @@ impl One for BigUint {
|
||||||
impl Unsigned for BigUint {}
|
impl Unsigned for BigUint {}
|
||||||
|
|
||||||
forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add);
|
forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add);
|
||||||
|
forward_val_assign!(impl AddAssign for BigUint, add_assign);
|
||||||
|
|
||||||
impl<'a> Add<&'a BigUint> for BigUint {
|
impl<'a> Add<&'a BigUint> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
fn add(mut self, other: &BigUint) -> BigUint {
|
fn add(mut self, other: &BigUint) -> BigUint {
|
||||||
|
self += other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> AddAssign<&'a BigUint> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, other: &BigUint) {
|
||||||
if self.data.len() < other.data.len() {
|
if self.data.len() < other.data.len() {
|
||||||
let extra = other.data.len() - self.data.len();
|
let extra = other.data.len() - self.data.len();
|
||||||
self.data.extend(repeat(0).take(extra));
|
self.data.extend(repeat(0).take(extra));
|
||||||
|
@ -391,12 +433,11 @@ impl<'a> Add<&'a BigUint> for BigUint {
|
||||||
if carry != 0 {
|
if carry != 0 {
|
||||||
self.data.push(carry);
|
self.data.push(carry);
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
promote_unsigned_scalars!(impl Add for BigUint, add);
|
promote_unsigned_scalars!(impl Add for BigUint, add);
|
||||||
|
promote_unsigned_scalars_assign!(impl AddAssign for BigUint, add_assign);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Add<BigDigit> for BigUint, add);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Add<BigDigit> for BigUint, add);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Add<DoubleBigDigit> for BigUint, add);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Add<DoubleBigDigit> for BigUint, add);
|
||||||
|
|
||||||
|
@ -405,6 +446,13 @@ impl Add<BigDigit> for BigUint {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(mut self, other: BigDigit) -> BigUint {
|
fn add(mut self, other: BigDigit) -> BigUint {
|
||||||
|
self += other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AddAssign<BigDigit> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, other: BigDigit) {
|
||||||
if other != 0 {
|
if other != 0 {
|
||||||
if self.data.len() == 0 {
|
if self.data.len() == 0 {
|
||||||
self.data.push(0);
|
self.data.push(0);
|
||||||
|
@ -415,7 +463,6 @@ impl Add<BigDigit> for BigUint {
|
||||||
self.data.push(carry);
|
self.data.push(carry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,9 +471,16 @@ impl Add<DoubleBigDigit> for BigUint {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(mut self, other: DoubleBigDigit) -> BigUint {
|
fn add(mut self, other: DoubleBigDigit) -> BigUint {
|
||||||
|
self += other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AddAssign<DoubleBigDigit> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, other: DoubleBigDigit) {
|
||||||
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
||||||
if hi == 0 {
|
if hi == 0 {
|
||||||
self + lo
|
*self += lo;
|
||||||
} else {
|
} else {
|
||||||
while self.data.len() < 2 {
|
while self.data.len() < 2 {
|
||||||
self.data.push(0);
|
self.data.push(0);
|
||||||
|
@ -436,20 +490,26 @@ impl Add<DoubleBigDigit> for BigUint {
|
||||||
if carry != 0 {
|
if carry != 0 {
|
||||||
self.data.push(carry);
|
self.data.push(carry);
|
||||||
}
|
}
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_val_val_binop!(impl Sub for BigUint, sub);
|
forward_val_val_binop!(impl Sub for BigUint, sub);
|
||||||
forward_ref_ref_binop!(impl Sub for BigUint, sub);
|
forward_ref_ref_binop!(impl Sub for BigUint, sub);
|
||||||
|
forward_val_assign!(impl SubAssign for BigUint, sub_assign);
|
||||||
|
|
||||||
impl<'a> Sub<&'a BigUint> for BigUint {
|
impl<'a> Sub<&'a BigUint> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
fn sub(mut self, other: &BigUint) -> BigUint {
|
fn sub(mut self, other: &BigUint) -> BigUint {
|
||||||
|
self -= other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> SubAssign<&'a BigUint> for BigUint {
|
||||||
|
fn sub_assign(&mut self, other: &'a BigUint) {
|
||||||
sub2(&mut self.data[..], &other.data[..]);
|
sub2(&mut self.data[..], &other.data[..]);
|
||||||
self.normalized()
|
self.normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,6 +528,7 @@ impl<'a> Sub<BigUint> for &'a BigUint {
|
||||||
}
|
}
|
||||||
|
|
||||||
promote_unsigned_scalars!(impl Sub for BigUint, sub);
|
promote_unsigned_scalars!(impl Sub for BigUint, sub);
|
||||||
|
promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Sub<BigDigit> for BigUint, sub);
|
forward_all_scalar_binop_to_val_val!(impl Sub<BigDigit> for BigUint, sub);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Sub<DoubleBigDigit> for BigUint, sub);
|
forward_all_scalar_binop_to_val_val!(impl Sub<DoubleBigDigit> for BigUint, sub);
|
||||||
|
|
||||||
|
@ -476,8 +537,14 @@ impl Sub<BigDigit> for BigUint {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(mut self, other: BigDigit) -> BigUint {
|
fn sub(mut self, other: BigDigit) -> BigUint {
|
||||||
|
self -= other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl SubAssign<BigDigit> for BigUint {
|
||||||
|
fn sub_assign(&mut self, other: BigDigit) {
|
||||||
sub2(&mut self.data[..], &[other]);
|
sub2(&mut self.data[..], &[other]);
|
||||||
self.normalized()
|
self.normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,9 +567,15 @@ impl Sub<DoubleBigDigit> for BigUint {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(mut self, other: DoubleBigDigit) -> BigUint {
|
fn sub(mut self, other: DoubleBigDigit) -> BigUint {
|
||||||
|
self -= other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl SubAssign<DoubleBigDigit> for BigUint {
|
||||||
|
fn sub_assign(&mut self, other: DoubleBigDigit) {
|
||||||
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
||||||
sub2(&mut self.data[..], &[lo, hi]);
|
sub2(&mut self.data[..], &[lo, hi]);
|
||||||
self.normalized()
|
self.normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,6 +595,7 @@ impl Sub<BigUint> for DoubleBigDigit {
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul);
|
forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul);
|
||||||
|
forward_val_assign!(impl MulAssign for BigUint, mul_assign);
|
||||||
|
|
||||||
impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint {
|
impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
@ -531,8 +605,15 @@ impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint {
|
||||||
mul3(&self.data[..], &other.data[..])
|
mul3(&self.data[..], &other.data[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'a> MulAssign<&'a BigUint> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, other: &'a BigUint) {
|
||||||
|
*self = &*self * other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
promote_unsigned_scalars!(impl Mul for BigUint, mul);
|
promote_unsigned_scalars!(impl Mul for BigUint, mul);
|
||||||
|
promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<BigDigit> for BigUint, mul);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<BigDigit> for BigUint, mul);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<DoubleBigDigit> for BigUint, mul);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<DoubleBigDigit> for BigUint, mul);
|
||||||
|
|
||||||
|
@ -541,6 +622,13 @@ impl Mul<BigDigit> for BigUint {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(mut self, other: BigDigit) -> BigUint {
|
fn mul(mut self, other: BigDigit) -> BigUint {
|
||||||
|
self *= other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MulAssign<BigDigit> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, other: BigDigit) {
|
||||||
if other == 0 {
|
if other == 0 {
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
} else {
|
} else {
|
||||||
|
@ -549,7 +637,6 @@ impl Mul<BigDigit> for BigUint {
|
||||||
self.data.push(carry);
|
self.data.push(carry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,19 +645,26 @@ impl Mul<DoubleBigDigit> for BigUint {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(mut self, other: DoubleBigDigit) -> BigUint {
|
fn mul(mut self, other: DoubleBigDigit) -> BigUint {
|
||||||
|
self *= other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MulAssign<DoubleBigDigit> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, other: DoubleBigDigit) {
|
||||||
if other == 0 {
|
if other == 0 {
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
self
|
|
||||||
} else if other <= BigDigit::max_value() as DoubleBigDigit {
|
} else if other <= BigDigit::max_value() as DoubleBigDigit {
|
||||||
self * other as BigDigit
|
*self *= other as BigDigit
|
||||||
} else {
|
} else {
|
||||||
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
||||||
mul3(&self.data[..], &[lo, hi])
|
*self = mul3(&self.data[..], &[lo, hi])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_all_binop_to_ref_ref!(impl Div for BigUint, div);
|
forward_all_binop_to_ref_ref!(impl Div for BigUint, div);
|
||||||
|
forward_val_assign!(impl DivAssign for BigUint, div_assign);
|
||||||
|
|
||||||
impl<'a, 'b> Div<&'b BigUint> for &'a BigUint {
|
impl<'a, 'b> Div<&'b BigUint> for &'a BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
@ -581,8 +675,15 @@ impl<'a, 'b> Div<&'b BigUint> for &'a BigUint {
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'a> DivAssign<&'a BigUint> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn div_assign(&mut self, other: &'a BigUint) {
|
||||||
|
*self = &*self / other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
promote_unsigned_scalars!(impl Div for BigUint, div);
|
promote_unsigned_scalars!(impl Div for BigUint, div);
|
||||||
|
promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Div<BigDigit> for BigUint, div);
|
forward_all_scalar_binop_to_val_val!(impl Div<BigDigit> for BigUint, div);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Div<DoubleBigDigit> for BigUint, div);
|
forward_all_scalar_binop_to_val_val!(impl Div<DoubleBigDigit> for BigUint, div);
|
||||||
|
|
||||||
|
@ -595,6 +696,12 @@ impl Div<BigDigit> for BigUint {
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl DivAssign<BigDigit> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn div_assign(&mut self, other: BigDigit) {
|
||||||
|
*self = &*self / other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Div<BigUint> for BigDigit {
|
impl Div<BigUint> for BigDigit {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
@ -618,6 +725,12 @@ impl Div<DoubleBigDigit> for BigUint {
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl DivAssign<DoubleBigDigit> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn div_assign(&mut self, other: DoubleBigDigit) {
|
||||||
|
*self = &*self / other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Div<BigUint> for DoubleBigDigit {
|
impl Div<BigUint> for DoubleBigDigit {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
@ -634,6 +747,7 @@ impl Div<BigUint> for DoubleBigDigit {
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_all_binop_to_ref_ref!(impl Rem for BigUint, rem);
|
forward_all_binop_to_ref_ref!(impl Rem for BigUint, rem);
|
||||||
|
forward_val_assign!(impl RemAssign for BigUint, rem_assign);
|
||||||
|
|
||||||
impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint {
|
impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
@ -644,8 +758,15 @@ impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint {
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'a> RemAssign<&'a BigUint> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn rem_assign(&mut self, other: &BigUint) {
|
||||||
|
*self = &*self % other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
promote_unsigned_scalars!(impl Rem for BigUint, rem);
|
promote_unsigned_scalars!(impl Rem for BigUint, rem);
|
||||||
|
promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Rem<BigDigit> for BigUint, rem);
|
forward_all_scalar_binop_to_val_val!(impl Rem<BigDigit> for BigUint, rem);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Rem<DoubleBigDigit> for BigUint, rem);
|
forward_all_scalar_binop_to_val_val!(impl Rem<DoubleBigDigit> for BigUint, rem);
|
||||||
|
|
||||||
|
@ -658,19 +779,49 @@ impl Rem<BigDigit> for BigUint {
|
||||||
From::from(r)
|
From::from(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl RemAssign<BigDigit> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn rem_assign(&mut self, other: BigDigit) {
|
||||||
|
*self = &*self % other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Rem<BigUint> for BigDigit {
|
impl Rem<BigUint> for BigDigit {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem(self, other: BigUint) -> BigUint {
|
fn rem(mut self, other: BigUint) -> BigUint {
|
||||||
match other.data.len() {
|
self %= other;
|
||||||
0 => panic!(),
|
From::from(self)
|
||||||
1 => From::from(self % other.data[0]),
|
}
|
||||||
_ => From::from(self)
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_rem_assign_scalar {
|
||||||
|
($scalar:ty, $to_scalar:ident) => {
|
||||||
|
forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign);
|
||||||
|
impl<'a> RemAssign<&'a BigUint> for $scalar {
|
||||||
|
#[inline]
|
||||||
|
fn rem_assign(&mut self, other: &BigUint) {
|
||||||
|
*self = match other.$to_scalar() {
|
||||||
|
None => *self,
|
||||||
|
Some(0) => panic!(),
|
||||||
|
Some(v) => *self % v
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// we can scalar %= BigUint for any scalar, including signed types
|
||||||
|
impl_rem_assign_scalar!(usize, to_usize);
|
||||||
|
impl_rem_assign_scalar!(u64, to_u64);
|
||||||
|
impl_rem_assign_scalar!(u32, to_u32);
|
||||||
|
impl_rem_assign_scalar!(u16, to_u16);
|
||||||
|
impl_rem_assign_scalar!(u8, to_u8);
|
||||||
|
impl_rem_assign_scalar!(isize, to_isize);
|
||||||
|
impl_rem_assign_scalar!(i64, to_i64);
|
||||||
|
impl_rem_assign_scalar!(i32, to_i32);
|
||||||
|
impl_rem_assign_scalar!(i16, to_i16);
|
||||||
|
impl_rem_assign_scalar!(i8, to_i8);
|
||||||
|
|
||||||
impl Rem<DoubleBigDigit> for BigUint {
|
impl Rem<DoubleBigDigit> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
@ -681,18 +832,20 @@ impl Rem<DoubleBigDigit> for BigUint {
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl RemAssign<DoubleBigDigit> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn rem_assign(&mut self, other: DoubleBigDigit) {
|
||||||
|
*self = &*self % other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Rem<BigUint> for DoubleBigDigit {
|
impl Rem<BigUint> for DoubleBigDigit {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem(self, other: BigUint) -> BigUint {
|
fn rem(mut self, other: BigUint) -> BigUint {
|
||||||
match other.data.len() {
|
self %= other;
|
||||||
0 => panic!(),
|
From::from(self)
|
||||||
1 => From::from(self % other.data[0] as u64),
|
|
||||||
2 => From::from(self % big_digit::to_doublebigdigit(other.data[0], other.data[1])),
|
|
||||||
_ => From::from(self),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,27 @@ macro_rules! forward_ref_ref_binop_commutative {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! forward_val_assign {
|
||||||
|
(impl $imp:ident for $res:ty, $method:ident) => {
|
||||||
|
impl $imp<$res> for $res {
|
||||||
|
#[inline]
|
||||||
|
fn $method(&mut self, other: $res) {
|
||||||
|
self.$method(&other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
macro_rules! forward_val_assign_scalar {
|
||||||
|
(impl $imp:ident for $res:ty, $scalar:ty, $method:ident) => {
|
||||||
|
impl $imp<$res> for $scalar {
|
||||||
|
#[inline]
|
||||||
|
fn $method(&mut self, other: $res) {
|
||||||
|
self.$method(&other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! forward_scalar_val_val_binop_commutative {
|
macro_rules! forward_scalar_val_val_binop_commutative {
|
||||||
(impl $imp:ident<$scalar:ty> for $res:ty, $method: ident) => {
|
(impl $imp:ident<$scalar:ty> for $res:ty, $method: ident) => {
|
||||||
impl $imp<$res> for $scalar {
|
impl $imp<$res> for $scalar {
|
||||||
|
@ -209,6 +230,18 @@ macro_rules! promote_scalars {
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
macro_rules! promote_scalars_assign {
|
||||||
|
(impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => {
|
||||||
|
$(
|
||||||
|
impl $imp<$scalar> for $res {
|
||||||
|
#[inline]
|
||||||
|
fn $method(&mut self, other: $scalar) {
|
||||||
|
self.$method(other as $promo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! promote_unsigned_scalars {
|
macro_rules! promote_unsigned_scalars {
|
||||||
(impl $imp:ident for $res:ty, $method:ident) => {
|
(impl $imp:ident for $res:ty, $method:ident) => {
|
||||||
|
@ -217,6 +250,13 @@ macro_rules! promote_unsigned_scalars {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! promote_unsigned_scalars_assign {
|
||||||
|
(impl $imp:ident for $res:ty, $method:ident) => {
|
||||||
|
promote_scalars_assign!(impl $imp<u32> for $res, $method, u8, u16);
|
||||||
|
promote_scalars_assign!(impl $imp<UsizePromotion> for $res, $method, usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! promote_signed_scalars {
|
macro_rules! promote_signed_scalars {
|
||||||
(impl $imp:ident for $res:ty, $method:ident) => {
|
(impl $imp:ident for $res:ty, $method:ident) => {
|
||||||
promote_scalars!(impl $imp<i32> for $res, $method, i8, i16);
|
promote_scalars!(impl $imp<i32> for $res, $method, i8, i16);
|
||||||
|
|
|
@ -24,6 +24,18 @@ macro_rules! assert_op {
|
||||||
assert_eq!($left.clone() $op $right.clone(), $expected);
|
assert_eq!($left.clone() $op $right.clone(), $expected);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/// Assert that an assign-op works for all val/ref combinations
|
||||||
|
macro_rules! assert_assign_op {
|
||||||
|
($left:ident $op:tt $right:ident == $expected:expr) => {
|
||||||
|
{
|
||||||
|
let mut tmp12384 = $left.clone();
|
||||||
|
assert_eq!({ tmp12384 $op &$right; tmp12384}, $expected);
|
||||||
|
|
||||||
|
let mut tmp12384 = $left.clone();
|
||||||
|
assert_eq!({ tmp12384 $op $right.clone(); tmp12384}, $expected);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Assert that an op works for scalar left or right
|
/// Assert that an op works for scalar left or right
|
||||||
macro_rules! assert_scalar_op {
|
macro_rules! assert_scalar_op {
|
||||||
|
@ -191,6 +203,8 @@ const BIT_TESTS: &'static [(&'static [BigDigit],
|
||||||
&'static [BigDigit],
|
&'static [BigDigit],
|
||||||
&'static [BigDigit])] = &[// LEFT RIGHT AND OR XOR
|
&'static [BigDigit])] = &[// LEFT RIGHT AND OR XOR
|
||||||
(&[], &[], &[], &[], &[]),
|
(&[], &[], &[], &[], &[]),
|
||||||
|
(&[1, 0, 1], &[1, 1], &[1], &[1, 1, 1], &[0, 1, 1]),
|
||||||
|
(&[1, 0, 1], &[0, 1, 1], &[0, 0, 1], &[1, 1, 1], &[1, 1]),
|
||||||
(&[268, 482, 17],
|
(&[268, 482, 17],
|
||||||
&[964, 54],
|
&[964, 54],
|
||||||
&[260, 34],
|
&[260, 34],
|
||||||
|
@ -207,6 +221,8 @@ fn test_bitand() {
|
||||||
|
|
||||||
assert_op!(a & b == c);
|
assert_op!(a & b == c);
|
||||||
assert_op!(b & a == c);
|
assert_op!(b & a == c);
|
||||||
|
assert_assign_op!(a &= b == c);
|
||||||
|
assert_assign_op!(b &= a == c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,6 +236,8 @@ fn test_bitor() {
|
||||||
|
|
||||||
assert_op!(a | b == c);
|
assert_op!(a | b == c);
|
||||||
assert_op!(b | a == c);
|
assert_op!(b | a == c);
|
||||||
|
assert_assign_op!(a |= b == c);
|
||||||
|
assert_assign_op!(b |= a == c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +255,12 @@ fn test_bitxor() {
|
||||||
assert_op!(c ^ a == b);
|
assert_op!(c ^ a == b);
|
||||||
assert_op!(b ^ c == a);
|
assert_op!(b ^ c == a);
|
||||||
assert_op!(c ^ b == a);
|
assert_op!(c ^ b == a);
|
||||||
|
assert_assign_op!(a ^= b == c);
|
||||||
|
assert_assign_op!(b ^= a == c);
|
||||||
|
assert_assign_op!(a ^= c == b);
|
||||||
|
assert_assign_op!(c ^= a == b);
|
||||||
|
assert_assign_op!(b ^= c == a);
|
||||||
|
assert_assign_op!(c ^= b == a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,8 +268,11 @@ fn test_bitxor() {
|
||||||
fn test_shl() {
|
fn test_shl() {
|
||||||
fn check(s: &str, shift: usize, ans: &str) {
|
fn check(s: &str, shift: usize, ans: &str) {
|
||||||
let opt_biguint = BigUint::from_str_radix(s, 16).ok();
|
let opt_biguint = BigUint::from_str_radix(s, 16).ok();
|
||||||
let bu = (opt_biguint.unwrap() << shift).to_str_radix(16);
|
let mut bu_assign = opt_biguint.unwrap();
|
||||||
|
let bu = (bu_assign.clone() << shift).to_str_radix(16);
|
||||||
assert_eq!(bu, ans);
|
assert_eq!(bu, ans);
|
||||||
|
bu_assign <<= shift;
|
||||||
|
assert_eq!(bu_assign.to_str_radix(16), ans);
|
||||||
}
|
}
|
||||||
|
|
||||||
check("0", 3, "0");
|
check("0", 3, "0");
|
||||||
|
@ -366,8 +393,11 @@ fn test_shl() {
|
||||||
fn test_shr() {
|
fn test_shr() {
|
||||||
fn check(s: &str, shift: usize, ans: &str) {
|
fn check(s: &str, shift: usize, ans: &str) {
|
||||||
let opt_biguint = BigUint::from_str_radix(s, 16).ok();
|
let opt_biguint = BigUint::from_str_radix(s, 16).ok();
|
||||||
let bu = (opt_biguint.unwrap() >> shift).to_str_radix(16);
|
let mut bu_assign = opt_biguint.unwrap();
|
||||||
|
let bu = (bu_assign.clone() >> shift).to_str_radix(16);
|
||||||
assert_eq!(bu, ans);
|
assert_eq!(bu, ans);
|
||||||
|
bu_assign >>= shift;
|
||||||
|
assert_eq!(bu_assign.to_str_radix(16), ans);
|
||||||
}
|
}
|
||||||
|
|
||||||
check("0", 3, "0");
|
check("0", 3, "0");
|
||||||
|
@ -720,6 +750,8 @@ fn test_add() {
|
||||||
|
|
||||||
assert_op!(a + b == c);
|
assert_op!(a + b == c);
|
||||||
assert_op!(b + a == c);
|
assert_op!(b + a == c);
|
||||||
|
assert_assign_op!(a += b == c);
|
||||||
|
assert_assign_op!(b += a == c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,6 +778,8 @@ fn test_sub() {
|
||||||
|
|
||||||
assert_op!(c - a == b);
|
assert_op!(c - a == b);
|
||||||
assert_op!(c - b == a);
|
assert_op!(c - b == a);
|
||||||
|
assert_assign_op!(c -= a == b);
|
||||||
|
assert_assign_op!(c -= b == a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,6 +850,8 @@ fn test_mul() {
|
||||||
|
|
||||||
assert_op!(a * b == c);
|
assert_op!(a * b == c);
|
||||||
assert_op!(b * a == c);
|
assert_op!(b * a == c);
|
||||||
|
assert_assign_op!(a *= b == c);
|
||||||
|
assert_assign_op!(b *= a == c);
|
||||||
}
|
}
|
||||||
|
|
||||||
for elm in DIV_REM_QUADRUPLES.iter() {
|
for elm in DIV_REM_QUADRUPLES.iter() {
|
||||||
|
@ -854,11 +890,15 @@ fn test_div_rem() {
|
||||||
if !a.is_zero() {
|
if !a.is_zero() {
|
||||||
assert_op!(c / a == b);
|
assert_op!(c / a == b);
|
||||||
assert_op!(c % a == Zero::zero());
|
assert_op!(c % a == Zero::zero());
|
||||||
|
assert_assign_op!(c /= a == b);
|
||||||
|
assert_assign_op!(c %= a == Zero::zero());
|
||||||
assert_eq!(c.div_rem(&a), (b.clone(), Zero::zero()));
|
assert_eq!(c.div_rem(&a), (b.clone(), Zero::zero()));
|
||||||
}
|
}
|
||||||
if !b.is_zero() {
|
if !b.is_zero() {
|
||||||
assert_op!(c / b == a);
|
assert_op!(c / b == a);
|
||||||
assert_op!(c % b == Zero::zero());
|
assert_op!(c % b == Zero::zero());
|
||||||
|
assert_assign_op!(c /= b == a);
|
||||||
|
assert_assign_op!(c %= b == Zero::zero());
|
||||||
assert_eq!(c.div_rem(&b), (a.clone(), Zero::zero()));
|
assert_eq!(c.div_rem(&b), (a.clone(), Zero::zero()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -873,6 +913,8 @@ fn test_div_rem() {
|
||||||
if !b.is_zero() {
|
if !b.is_zero() {
|
||||||
assert_op!(a / b == c);
|
assert_op!(a / b == c);
|
||||||
assert_op!(a % b == d);
|
assert_op!(a % b == d);
|
||||||
|
assert_assign_op!(a /= b == c);
|
||||||
|
assert_assign_op!(a %= b == d);
|
||||||
assert!(a.div_rem(&b) == (c, d));
|
assert!(a.div_rem(&b) == (c, d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue