From 03d717f26f9ad77fa3e33955d8f6db7f45416bc2 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 26 Aug 2017 14:11:08 +0200 Subject: [PATCH 01/14] Implement AddAssign for BigUint --- bigint/src/biguint.rs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index c77328f..a291514 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}; +use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub, AddAssign}; use std::str::{self, FromStr}; use std::fmt; use std::cmp; @@ -382,6 +382,14 @@ 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,8 +399,6 @@ impl<'a> Add<&'a BigUint> for BigUint { if carry != 0 { self.data.push(carry); } - - self } } @@ -405,6 +411,13 @@ impl Add for BigUint { #[inline] fn add(mut self, other: BigDigit) -> BigUint { + self += other; + self + } +} +impl AddAssign for BigUint { + #[inline] + fn add_assign(&mut self, other: BigDigit) { if other != 0 { if self.data.len() == 0 { self.data.push(0); @@ -415,7 +428,6 @@ impl Add for BigUint { self.data.push(carry); } } - self } } @@ -424,9 +436,16 @@ impl Add for BigUint { #[inline] fn add(mut self, other: DoubleBigDigit) -> BigUint { + self += other; + self + } +} +impl AddAssign 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,7 +455,6 @@ impl Add for BigUint { if carry != 0 { self.data.push(carry); } - self } } } From 8c47ca00c76819fea48a58ee70822defc70a7b18 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 26 Aug 2017 14:21:26 +0200 Subject: [PATCH 02/14] Implement MulAssign for BigUint --- bigint/src/biguint.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index a291514..c62cc64 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}; +use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub, AddAssign, MulAssign}; use std::str::{self, FromStr}; use std::fmt; use std::cmp; @@ -549,6 +549,12 @@ 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); forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); @@ -559,6 +565,13 @@ impl Mul for BigUint { #[inline] fn mul(mut self, other: BigDigit) -> BigUint { + self *= other; + self + } +} +impl MulAssign for BigUint { + #[inline] + fn mul_assign(&mut self, other: BigDigit) { if other == 0 { self.data.clear(); } else { @@ -567,7 +580,6 @@ impl Mul for BigUint { self.data.push(carry); } } - self } } @@ -576,14 +588,20 @@ impl Mul for BigUint { #[inline] fn mul(mut self, other: DoubleBigDigit) -> BigUint { + self *= other; + self + } +} +impl MulAssign 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]) } } } From 17030ea412638ceda3cef6bd92e9b00268cd4a72 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 26 Aug 2017 14:30:25 +0200 Subject: [PATCH 03/14] Implement SubAssign for BigUint --- bigint/src/biguint.rs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index c62cc64..a21b5cd 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, MulAssign}; +use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub, AddAssign, SubAssign, MulAssign}; use std::str::{self, FromStr}; use std::fmt; use std::cmp; @@ -466,8 +466,14 @@ 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(); } } @@ -494,8 +500,14 @@ impl Sub for BigUint { #[inline] fn sub(mut self, other: BigDigit) -> BigUint { + self -= other; + self + } +} +impl SubAssign for BigUint { + fn sub_assign(&mut self, other: BigDigit) { sub2(&mut self.data[..], &[other]); - self.normalized() + self.normalize(); } } @@ -518,9 +530,15 @@ impl Sub for BigUint { #[inline] fn sub(mut self, other: DoubleBigDigit) -> BigUint { + self -= other; + self + } +} +impl SubAssign 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(); } } From 04117fafe95e4eeddf01940bcf638260044ec7e2 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 26 Aug 2017 14:35:03 +0200 Subject: [PATCH 04/14] Implement DivAssign for BigUint --- bigint/src/biguint.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index a21b5cd..dd0de5b 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}; +use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub, AddAssign, SubAssign, MulAssign, DivAssign}; use std::str::{self, FromStr}; use std::fmt; use std::cmp; @@ -635,6 +635,12 @@ 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); forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); @@ -649,6 +655,12 @@ impl Div for BigUint { q } } +impl DivAssign for BigUint { + #[inline] + fn div_assign(&mut self, other: BigDigit) { + *self = &*self / other; + } +} impl Div for BigDigit { type Output = BigUint; @@ -672,6 +684,12 @@ impl Div for BigUint { q } } +impl DivAssign for BigUint { + #[inline] + fn div_assign(&mut self, other: DoubleBigDigit) { + *self = &*self / other; + } +} impl Div for DoubleBigDigit { type Output = BigUint; From e85ab24567baa6ee7c0c717809a504af1924aeb5 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 2 Sep 2017 22:38:12 +0200 Subject: [PATCH 05/14] Forward by-value biguint and scalars to {Add,Mul,Sub,Div}Assign --- bigint/src/biguint.rs | 9 ++++++++- bigint/src/macros.rs | 32 +++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index dd0de5b..430c5a9 100644 --- a/bigint/src/biguint.rs +++ b/bigint/src/biguint.rs @@ -377,6 +377,7 @@ 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; @@ -386,7 +387,6 @@ impl<'a> Add<&'a BigUint> for BigUint { self } } - impl<'a> AddAssign<&'a BigUint> for BigUint { #[inline] fn add_assign(&mut self, other: &BigUint) { @@ -403,6 +403,7 @@ impl<'a> AddAssign<&'a BigUint> for BigUint { } 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 for BigUint, add); forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); @@ -461,6 +462,7 @@ impl AddAssign for BigUint { 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; @@ -492,6 +494,7 @@ impl<'a> Sub 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 for BigUint, sub); forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); @@ -558,6 +561,7 @@ impl Sub 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; @@ -575,6 +579,7 @@ impl<'a> MulAssign<&'a BigUint> for BigUint { } 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 for BigUint, mul); forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); @@ -625,6 +630,7 @@ impl MulAssign for BigUint { } 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; @@ -643,6 +649,7 @@ impl<'a> DivAssign<&'a BigUint> for BigUint { } 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 for BigUint, div); forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); diff --git a/bigint/src/macros.rs b/bigint/src/macros.rs index 7705f55..20d34b9 100644 --- a/bigint/src/macros.rs +++ b/bigint/src/macros.rs @@ -105,6 +105,17 @@ macro_rules! forward_ref_ref_binop_commutative { } } +macro_rules! forward_val_assign { + (impl $imp:ident for $res:ty, $method:ident) => { + impl<'a> $imp<$res> for $res { + #[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 +220,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 +240,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 for $res, $method, u8, u16); + promote_scalars_assign!(impl $imp for $res, $method, usize); + } +} + macro_rules! promote_signed_scalars { (impl $imp:ident for $res:ty, $method:ident) => { promote_scalars!(impl $imp for $res, $method, i8, i16); @@ -271,4 +301,4 @@ macro_rules! promote_all_scalars { promote_unsigned_scalars!(impl $imp for $res, $method); promote_signed_scalars!(impl $imp for $res, $method); } -} \ No newline at end of file +} From 23085800e0d36c66c65caf6805d615ff6f40713c Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 2 Sep 2017 23:29:34 +0200 Subject: [PATCH 06/14] Implement RemAssign for BigUint --- bigint/src/biguint.rs | 66 ++++++++++++++++++++++++++++++++++--------- bigint/src/macros.rs | 10 +++++++ 2 files changed, 63 insertions(+), 13 deletions(-) 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) => { From 8c3b2de11c8ea4cefe13ccdd807ce390d75f0ee9 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 2 Sep 2017 23:37:54 +0200 Subject: [PATCH 07/14] Implement BitAndAssign and BitOrAssign for BigUint --- bigint/src/biguint.rs | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index d65e06f..678617d 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, RemAssign}; +use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign, BitAndAssign, BitOrAssign}; use std::str::{self, FromStr}; use std::fmt; use std::cmp; @@ -268,36 +268,48 @@ 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()); } } 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) } } From 2f6c0bf3542bdffd614e9e5f7f9765b2834af6b2 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 2 Sep 2017 23:40:51 +0200 Subject: [PATCH 08/14] Implement BitXorAssign for BigUint --- bigint/src/biguint.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index 678617d..692c5d7 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, RemAssign, BitAndAssign, BitOrAssign}; +use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign, BitAndAssign, BitOrAssign, BitXorAssign}; use std::str::{self, FromStr}; use std::fmt; use std::cmp; @@ -314,20 +314,27 @@ impl<'a> BitOrAssign<&'a BigUint> for BigUint { } 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(); } } From 555dab7d332370822b97a2e13ff02f46e5404376 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sun, 3 Sep 2017 09:56:29 +0200 Subject: [PATCH 09/14] Implement ShrAssign and ShlAssign for BigUint --- bigint/src/biguint.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index 692c5d7..66eff38 100644 --- a/bigint/src/biguint.rs +++ b/bigint/src/biguint.rs @@ -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, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign, BitAndAssign, BitOrAssign, BitXorAssign}; +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; @@ -346,7 +348,6 @@ impl Shl for BigUint { biguint_shl(Cow::Owned(self), rhs) } } - impl<'a> Shl for &'a BigUint { type Output = BigUint; @@ -356,6 +357,13 @@ impl<'a> Shl for &'a BigUint { } } +impl ShlAssign for BigUint { + #[inline] + fn shl_assign(&mut self, rhs: usize) { + *self = biguint_shl(Cow::Borrowed(&*self), rhs); + } +} + impl Shr for BigUint { type Output = BigUint; @@ -364,7 +372,6 @@ impl Shr for BigUint { biguint_shr(Cow::Owned(self), rhs) } } - impl<'a> Shr for &'a BigUint { type Output = BigUint; @@ -374,6 +381,13 @@ impl<'a> Shr for &'a BigUint { } } +impl ShrAssign 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 { From ff8f106186fdf19fba7b9822871a104f3bc89a93 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sun, 3 Sep 2017 10:44:17 +0200 Subject: [PATCH 10/14] Test *Assign for BigUint --- bigint/src/tests/biguint.rs | 45 +++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/bigint/src/tests/biguint.rs b/bigint/src/tests/biguint.rs index c4be751..39c31a0 100644 --- a/bigint/src/tests/biguint.rs +++ b/bigint/src/tests/biguint.rs @@ -24,6 +24,19 @@ 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(); + tmp12384 $op &$right; + assert_eq!(tmp12384, $expected); + tmp12384 = $left.clone(); + tmp12384 $op $right.clone(); + assert_eq!(tmp12384, $expected); + } + }; +} /// Assert that an op works for scalar left or right macro_rules! assert_scalar_op { @@ -207,6 +220,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 +235,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 +254,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 +267,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 +392,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 +749,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 +777,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 +849,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 +889,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 +912,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)); } } From 98a3f17db6a0d96e947c43d5d58c6d2aea19dc97 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 19 Sep 2017 13:47:59 -0700 Subject: [PATCH 11/14] Fix impl_rem_assign_scalar for rust 1.8 --- bigint/src/biguint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index 66eff38..47712d3 100644 --- a/bigint/src/biguint.rs +++ b/bigint/src/biguint.rs @@ -796,7 +796,7 @@ impl Rem for BigDigit { } macro_rules! impl_rem_assign_scalar { - ($scalar:ty, $to_scalar:tt) => { + ($scalar:ty, $to_scalar:ident) => { forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign); impl<'a> RemAssign<&'a BigUint> for $scalar { #[inline] From 953087fe4ee7df801b1a12c690baeb34299323cb Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 19 Sep 2017 14:00:51 -0700 Subject: [PATCH 12/14] Fix biguint assert_assign_op for rust 1.8 The `$op` only seems to be accepted when used indirectly through another macro, in this case `assert_eq`. How nice. --- bigint/src/tests/biguint.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bigint/src/tests/biguint.rs b/bigint/src/tests/biguint.rs index 39c31a0..c656575 100644 --- a/bigint/src/tests/biguint.rs +++ b/bigint/src/tests/biguint.rs @@ -29,11 +29,10 @@ macro_rules! assert_assign_op { ($left:ident $op:tt $right:ident == $expected:expr) => { { let mut tmp12384 = $left.clone(); - tmp12384 $op &$right; - assert_eq!(tmp12384, $expected); - tmp12384 = $left.clone(); - tmp12384 $op $right.clone(); - assert_eq!(tmp12384, $expected); + assert_eq!({ tmp12384 $op &$right; tmp12384}, $expected); + + let mut tmp12384 = $left.clone(); + assert_eq!({ tmp12384 $op $right.clone(); tmp12384}, $expected); } }; } From 952dba4e06bbc5ca9fbfde844b31fce9d2778408 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 19 Sep 2017 17:36:17 -0700 Subject: [PATCH 13/14] remove unused lifetime from forward_val_assign --- bigint/src/macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigint/src/macros.rs b/bigint/src/macros.rs index 3324eba..a1615fb 100644 --- a/bigint/src/macros.rs +++ b/bigint/src/macros.rs @@ -107,7 +107,7 @@ macro_rules! forward_ref_ref_binop_commutative { macro_rules! forward_val_assign { (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a> $imp<$res> for $res { + impl $imp<$res> for $res { #[inline] fn $method(&mut self, other: $res) { self.$method(&other); @@ -117,7 +117,7 @@ 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 { + impl $imp<$res> for $scalar { #[inline] fn $method(&mut self, other: $res) { self.$method(&other); From 3c1c84307c8cc76b96820d6d7ac93db0a413f7bf Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 19 Sep 2017 17:53:13 -0700 Subject: [PATCH 14/14] bigint: make sure bigand is normalized --- bigint/src/biguint.rs | 1 + bigint/src/tests/biguint.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index 47712d3..367e66e 100644 --- a/bigint/src/biguint.rs +++ b/bigint/src/biguint.rs @@ -288,6 +288,7 @@ impl<'a> BitAndAssign<&'a BigUint> for BigUint { *ai &= bi; } self.data.truncate(other.data.len()); + self.normalize(); } } diff --git a/bigint/src/tests/biguint.rs b/bigint/src/tests/biguint.rs index c656575..d010bb5 100644 --- a/bigint/src/tests/biguint.rs +++ b/bigint/src/tests/biguint.rs @@ -203,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],