diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index 430c5a9..d65e06f 100644 --- a/bigint/src/biguint.rs +++ b/bigint/src/biguint.rs @@ -1,7 +1,7 @@ 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, 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::fmt; use std::cmp; @@ -713,6 +713,7 @@ impl Div 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; @@ -723,8 +724,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 for BigUint, rem); forward_all_scalar_binop_to_val_val!(impl Rem for BigUint, rem); @@ -737,19 +745,49 @@ impl Rem for BigUint { From::from(r) } } +impl RemAssign for BigUint { + #[inline] + fn rem_assign(&mut self, other: BigDigit) { + *self = &*self % other; + } +} impl Rem 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: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 for BigUint { type Output = BigUint; @@ -760,18 +798,20 @@ impl Rem for BigUint { r } } +impl RemAssign for BigUint { + #[inline] + fn rem_assign(&mut self, other: DoubleBigDigit) { + *self = &*self % other; + } +} impl Rem 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) } } diff --git a/bigint/src/macros.rs b/bigint/src/macros.rs index 20d34b9..3324eba 100644 --- a/bigint/src/macros.rs +++ b/bigint/src/macros.rs @@ -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 { (impl $imp:ident<$scalar:ty> for $res:ty, $method: ident) => {