Implement RemAssign for BigUint

This commit is contained in:
Alice Ryhl 2017-09-02 23:29:34 +02:00
parent e85ab24567
commit 23085800e0
2 changed files with 63 additions and 13 deletions

View File

@ -1,7 +1,7 @@
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, AddAssign, SubAssign, MulAssign, DivAssign}; use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
use std::str::{self, FromStr}; use std::str::{self, FromStr};
use std::fmt; use std::fmt;
use std::cmp; use std::cmp;
@ -713,6 +713,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;
@ -723,8 +724,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);
@ -737,19 +745,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:tt) => {
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;
@ -760,18 +798,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),
}
} }
} }

View File

@ -115,6 +115,16 @@ macro_rules! forward_val_assign {
} }
} }
} }
macro_rules! forward_val_assign_scalar {
(impl $imp:ident for $res:ty, $scalar:ty, $method:ident) => {
impl<'a> $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) => {