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::default::Default;
|
||||
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::fmt;
|
||||
use std::cmp;
|
||||
|
@ -268,54 +270,74 @@ impl Num for BigUint {
|
|||
}
|
||||
|
||||
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 {
|
||||
type Output = BigUint;
|
||||
|
||||
#[inline]
|
||||
fn bitand(self, other: &BigUint) -> BigUint {
|
||||
let mut data = self.data;
|
||||
for (ai, &bi) in data.iter_mut().zip(other.data.iter()) {
|
||||
fn bitand(mut self, other: &BigUint) -> BigUint {
|
||||
self &= other;
|
||||
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;
|
||||
}
|
||||
data.truncate(other.data.len());
|
||||
BigUint::new(data)
|
||||
self.data.truncate(other.data.len());
|
||||
self.normalize();
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
type Output = BigUint;
|
||||
|
||||
fn bitor(self, other: &BigUint) -> BigUint {
|
||||
let mut data = self.data;
|
||||
for (ai, &bi) in data.iter_mut().zip(other.data.iter()) {
|
||||
fn bitor(mut self, other: &BigUint) -> BigUint {
|
||||
self |= other;
|
||||
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;
|
||||
}
|
||||
if other.data.len() > data.len() {
|
||||
let extra = &other.data[data.len()..];
|
||||
data.extend(extra.iter().cloned());
|
||||
if other.data.len() > self.data.len() {
|
||||
let extra = &other.data[self.data.len()..];
|
||||
self.data.extend(extra.iter().cloned());
|
||||
}
|
||||
BigUint::new(data)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
type Output = BigUint;
|
||||
|
||||
fn bitxor(self, other: &BigUint) -> BigUint {
|
||||
let mut data = self.data;
|
||||
for (ai, &bi) in data.iter_mut().zip(other.data.iter()) {
|
||||
fn bitxor(mut self, other: &BigUint) -> BigUint {
|
||||
self ^= other;
|
||||
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;
|
||||
}
|
||||
if other.data.len() > data.len() {
|
||||
let extra = &other.data[data.len()..];
|
||||
data.extend(extra.iter().cloned());
|
||||
if other.data.len() > self.data.len() {
|
||||
let extra = &other.data[self.data.len()..];
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Shl<usize> for &'a 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 {
|
||||
type Output = BigUint;
|
||||
|
||||
|
@ -345,7 +373,6 @@ impl Shr<usize> for BigUint {
|
|||
biguint_shr(Cow::Owned(self), rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Shr<usize> for &'a 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 {
|
||||
#[inline]
|
||||
fn zero() -> BigUint {
|
||||
|
@ -377,11 +411,19 @@ impl One for BigUint {
|
|||
impl Unsigned for BigUint {}
|
||||
|
||||
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 {
|
||||
type Output = 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() {
|
||||
let extra = other.data.len() - self.data.len();
|
||||
self.data.extend(repeat(0).take(extra));
|
||||
|
@ -391,12 +433,11 @@ impl<'a> Add<&'a BigUint> for BigUint {
|
|||
if carry != 0 {
|
||||
self.data.push(carry);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
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<DoubleBigDigit> for BigUint, add);
|
||||
|
||||
|
@ -405,6 +446,13 @@ impl Add<BigDigit> for BigUint {
|
|||
|
||||
#[inline]
|
||||
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 self.data.len() == 0 {
|
||||
self.data.push(0);
|
||||
|
@ -415,7 +463,6 @@ impl Add<BigDigit> for BigUint {
|
|||
self.data.push(carry);
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,9 +471,16 @@ impl Add<DoubleBigDigit> for BigUint {
|
|||
|
||||
#[inline]
|
||||
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);
|
||||
if hi == 0 {
|
||||
self + lo
|
||||
*self += lo;
|
||||
} else {
|
||||
while self.data.len() < 2 {
|
||||
self.data.push(0);
|
||||
|
@ -436,20 +490,26 @@ impl Add<DoubleBigDigit> for BigUint {
|
|||
if carry != 0 {
|
||||
self.data.push(carry);
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forward_val_val_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 {
|
||||
type Output = 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[..]);
|
||||
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_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<DoubleBigDigit> for BigUint, sub);
|
||||
|
||||
|
@ -476,8 +537,14 @@ impl Sub<BigDigit> for BigUint {
|
|||
|
||||
#[inline]
|
||||
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]);
|
||||
self.normalized()
|
||||
self.normalize();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,9 +567,15 @@ impl Sub<DoubleBigDigit> for BigUint {
|
|||
|
||||
#[inline]
|
||||
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);
|
||||
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_val_assign!(impl MulAssign for BigUint, mul_assign);
|
||||
|
||||
impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint {
|
||||
type Output = BigUint;
|
||||
|
@ -531,8 +605,15 @@ impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint {
|
|||
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_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<DoubleBigDigit> for BigUint, mul);
|
||||
|
||||
|
@ -541,6 +622,13 @@ impl Mul<BigDigit> for BigUint {
|
|||
|
||||
#[inline]
|
||||
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 {
|
||||
self.data.clear();
|
||||
} else {
|
||||
|
@ -549,7 +637,6 @@ impl Mul<BigDigit> for BigUint {
|
|||
self.data.push(carry);
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,19 +645,26 @@ impl Mul<DoubleBigDigit> for BigUint {
|
|||
|
||||
#[inline]
|
||||
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 {
|
||||
self.data.clear();
|
||||
self
|
||||
} else if other <= BigDigit::max_value() as DoubleBigDigit {
|
||||
self * other as BigDigit
|
||||
*self *= other as BigDigit
|
||||
} else {
|
||||
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_val_assign!(impl DivAssign for BigUint, div_assign);
|
||||
|
||||
impl<'a, 'b> Div<&'b BigUint> for &'a BigUint {
|
||||
type Output = BigUint;
|
||||
|
@ -581,8 +675,15 @@ impl<'a, 'b> Div<&'b BigUint> for &'a BigUint {
|
|||
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_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<DoubleBigDigit> for BigUint, div);
|
||||
|
||||
|
@ -595,6 +696,12 @@ impl Div<BigDigit> for BigUint {
|
|||
q
|
||||
}
|
||||
}
|
||||
impl DivAssign<BigDigit> for BigUint {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: BigDigit) {
|
||||
*self = &*self / other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<BigUint> for BigDigit {
|
||||
type Output = BigUint;
|
||||
|
@ -618,6 +725,12 @@ impl Div<DoubleBigDigit> for BigUint {
|
|||
q
|
||||
}
|
||||
}
|
||||
impl DivAssign<DoubleBigDigit> for BigUint {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: DoubleBigDigit) {
|
||||
*self = &*self / other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<BigUint> for DoubleBigDigit {
|
||||
type Output = BigUint;
|
||||
|
@ -634,6 +747,7 @@ impl Div<BigUint> for DoubleBigDigit {
|
|||
}
|
||||
|
||||
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 {
|
||||
type Output = BigUint;
|
||||
|
@ -644,8 +758,15 @@ impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint {
|
|||
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_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<DoubleBigDigit> for BigUint, rem);
|
||||
|
||||
|
@ -658,19 +779,49 @@ impl Rem<BigDigit> for BigUint {
|
|||
From::from(r)
|
||||
}
|
||||
}
|
||||
impl RemAssign<BigDigit> for BigUint {
|
||||
#[inline]
|
||||
fn rem_assign(&mut self, other: BigDigit) {
|
||||
*self = &*self % other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Rem<BigUint> for BigDigit {
|
||||
type Output = BigUint;
|
||||
|
||||
#[inline]
|
||||
fn rem(self, other: BigUint) -> BigUint {
|
||||
match other.data.len() {
|
||||
0 => panic!(),
|
||||
1 => From::from(self % other.data[0]),
|
||||
_ => From::from(self)
|
||||
fn rem(mut self, other: BigUint) -> BigUint {
|
||||
self %= other;
|
||||
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 {
|
||||
type Output = BigUint;
|
||||
|
@ -681,18 +832,20 @@ impl Rem<DoubleBigDigit> for BigUint {
|
|||
r
|
||||
}
|
||||
}
|
||||
impl RemAssign<DoubleBigDigit> for BigUint {
|
||||
#[inline]
|
||||
fn rem_assign(&mut self, other: DoubleBigDigit) {
|
||||
*self = &*self % other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Rem<BigUint> for DoubleBigDigit {
|
||||
type Output = BigUint;
|
||||
|
||||
#[inline]
|
||||
fn rem(self, other: BigUint) -> BigUint {
|
||||
match other.data.len() {
|
||||
0 => panic!(),
|
||||
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),
|
||||
}
|
||||
fn rem(mut self, other: BigUint) -> BigUint {
|
||||
self %= other;
|
||||
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 {
|
||||
(impl $imp:ident<$scalar:ty> for $res:ty, $method: ident) => {
|
||||
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 {
|
||||
(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 {
|
||||
(impl $imp:ident for $res:ty, $method:ident) => {
|
||||
promote_scalars!(impl $imp<i32> for $res, $method, i8, i16);
|
||||
|
@ -271,4 +311,4 @@ macro_rules! promote_all_scalars {
|
|||
promote_unsigned_scalars!(impl $imp for $res, $method);
|
||||
promote_signed_scalars!(impl $imp for $res, $method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,18 @@ macro_rules! assert_op {
|
|||
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
|
||||
macro_rules! assert_scalar_op {
|
||||
|
@ -191,6 +203,8 @@ const BIT_TESTS: &'static [(&'static [BigDigit],
|
|||
&'static [BigDigit],
|
||||
&'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],
|
||||
&[964, 54],
|
||||
&[260, 34],
|
||||
|
@ -207,6 +221,8 @@ fn test_bitand() {
|
|||
|
||||
assert_op!(a & b == 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!(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!(b ^ c == 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 check(s: &str, shift: usize, ans: &str) {
|
||||
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);
|
||||
bu_assign <<= shift;
|
||||
assert_eq!(bu_assign.to_str_radix(16), ans);
|
||||
}
|
||||
|
||||
check("0", 3, "0");
|
||||
|
@ -366,8 +393,11 @@ fn test_shl() {
|
|||
fn test_shr() {
|
||||
fn check(s: &str, shift: usize, ans: &str) {
|
||||
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);
|
||||
bu_assign >>= shift;
|
||||
assert_eq!(bu_assign.to_str_radix(16), ans);
|
||||
}
|
||||
|
||||
check("0", 3, "0");
|
||||
|
@ -720,6 +750,8 @@ fn test_add() {
|
|||
|
||||
assert_op!(a + b == 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 - 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!(b * a == c);
|
||||
assert_assign_op!(a *= b == c);
|
||||
assert_assign_op!(b *= a == c);
|
||||
}
|
||||
|
||||
for elm in DIV_REM_QUADRUPLES.iter() {
|
||||
|
@ -854,11 +890,15 @@ fn test_div_rem() {
|
|||
if !a.is_zero() {
|
||||
assert_op!(c / a == b);
|
||||
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()));
|
||||
}
|
||||
if !b.is_zero() {
|
||||
assert_op!(c / b == a);
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
@ -873,6 +913,8 @@ fn test_div_rem() {
|
|||
if !b.is_zero() {
|
||||
assert_op!(a / b == c);
|
||||
assert_op!(a % b == d);
|
||||
assert_assign_op!(a /= b == c);
|
||||
assert_assign_op!(a %= b == d);
|
||||
assert!(a.div_rem(&b) == (c, d));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue