From cfe8ffb0cb9250ba3c64fde05369f73d9c9bfc4c Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Wed, 4 Jul 2018 13:26:53 +0200 Subject: [PATCH 1/9] Support BigUint.pow() for primitives --- src/biguint.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/biguint.rs | 35 +++++++++++++++++++++++++++++++-- 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/biguint.rs b/src/biguint.rs index e7a3ce19..f33aab11 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -434,6 +434,57 @@ impl One for BigUint { impl Unsigned for BigUint {} +macro_rules! pow_impl { + ($unsigned:ty, $signed:ty) => { + impl pow::Pow<$unsigned> for BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: $unsigned) -> Self::Output { + // square and multiply from num_traits::pow + pow::pow(self, exp as usize) + } + } + + impl<'a> pow::Pow<$unsigned> for &'a BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: $unsigned) -> Self::Output { + // square and multiply from num_traits::pow + pow::pow(self.clone(), exp as usize) + } + } + + impl<'a> pow::Pow<$signed> for BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: $signed) -> Self::Output { + assert!(exp >= 0, "Negative exponentiation is not supported"); + pow::pow(self, exp as usize) + } + } + + impl<'a> pow::Pow<$signed> for &'a BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: $signed) -> Self::Output { + assert!(exp >= 0, "Negative exponentiation is not supported"); + pow::pow(self.clone(), exp as usize) + } + } + } +} + +pow_impl!(u8, i8); +pow_impl!(u16, i16); +pow_impl!(u32, i32); +pow_impl!(u64, i64); +pow_impl!(usize, isize); +// FIXME support i128 + forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add); forward_val_assign!(impl AddAssign for BigUint, add_assign); diff --git a/tests/biguint.rs b/tests/biguint.rs index 92c8ce9e..009b16a0 100644 --- a/tests/biguint.rs +++ b/tests/biguint.rs @@ -19,7 +19,7 @@ use std::hash::{BuildHasher, Hasher, Hash}; use std::collections::hash_map::RandomState; use num_traits::{Num, Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, ToPrimitive, - FromPrimitive, Float}; + FromPrimitive, Float, Pow}; mod consts; use consts::*; @@ -766,7 +766,7 @@ fn test_sub() { #[should_panic] fn test_sub_fail_on_underflow() { let (a, b): (BigUint, BigUint) = (Zero::zero(), One::one()); - a - b; + let _ = a - b; } #[test] @@ -1530,3 +1530,34 @@ fn test_iter_product_generic() { assert_eq!(result, data.iter().product()); assert_eq!(result, data.into_iter().product()); } + + +#[test] +fn test_pow() { + let one = 1u32.to_biguint().unwrap(); + let two = 2u32.to_biguint().unwrap(); + let four = 4u32.to_biguint().unwrap(); + let eight = 8u32.to_biguint().unwrap(); + macro_rules! check { + ($t:ty) => { + assert_eq!((&two).pow(0 as $t), one); + assert_eq!(two.clone().pow(0 as $t), one); + assert_eq!((&two).pow(1 as $t), two); + assert_eq!(two.clone().pow(1 as $t), two); + assert_eq!((&two).clone().pow(2 as $t), four); + assert_eq!(two.clone().pow(2 as $t), four); + assert_eq!((&two).pow(3 as $t), eight); + assert_eq!(two.clone().pow(3 as $t), eight); + } + } + check!(u8); + check!(i8); + check!(u16); + check!(i16); + check!(u32); + check!(i32); + check!(u64); + check!(i64); + check!(usize); + check!(isize); +} From 136d7d9aab597df093ea08ace7c82df273a94d03 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Wed, 4 Jul 2018 14:58:42 +0200 Subject: [PATCH 2/9] Implement pow for BigInt --- src/bigint.rs | 42 +++++++++++++++++++++++++++++++++++++++++- tests/bigint.rs | 37 ++++++++++++++++++++++++++++++++++++- tests/biguint.rs | 1 - 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 93bb6b26..aae32a70 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -18,7 +18,7 @@ use serde; use integer::{Integer, Roots}; use traits::{ToPrimitive, FromPrimitive, Num, CheckedAdd, CheckedSub, - CheckedMul, CheckedDiv, Signed, Zero, One}; + CheckedMul, CheckedDiv, PrimInt, Signed, Zero, One, Pow}; use self::Sign::{Minus, NoSign, Plus}; @@ -66,6 +66,24 @@ impl Mul for Sign { } } +impl> Pow for Sign { + type Output = Sign; + + #[inline] + fn pow(self, other: T) -> Sign { + if self != Minus { + self + } else if other == T::zero() { + Plus + } else if other & T::one() == T::one() { + self + } else { + -self + } + } +} + + #[cfg(feature = "serde")] impl serde::Serialize for Sign { fn serialize(&self, serializer: S) -> Result @@ -811,6 +829,28 @@ impl Signed for BigInt { } } +impl Pow for BigInt + where BigUint: Pow +{ + type Output = BigInt; + + #[inline] + fn pow(self, rhs: T) -> BigInt { + BigInt::from_biguint(self.sign.pow(rhs), self.data.pow(rhs)) + } +} + +impl<'a, T: PrimInt> Pow for &'a BigInt + where BigUint: Pow +{ + type Output = BigInt; + + #[inline] + fn pow(self, rhs: T) -> BigInt { + BigInt::from_biguint(self.sign.pow(rhs), self.clone().data.pow(rhs)) + } +} + // A convenience method for getting the absolute value of an i32 in a u32. #[inline] fn i32_abs_as_u32(a: i32) -> u32 { diff --git a/tests/bigint.rs b/tests/bigint.rs index be9c871d..e4ee7968 100644 --- a/tests/bigint.rs +++ b/tests/bigint.rs @@ -20,7 +20,7 @@ use std::hash::{BuildHasher, Hasher, Hash}; use std::collections::hash_map::RandomState; use num_integer::Integer; -use num_traits::{Zero, One, Signed, ToPrimitive, FromPrimitive, Num, Float}; +use num_traits::{Zero, One, Signed, ToPrimitive, FromPrimitive, Num, Float, Pow}; mod consts; use consts::*; @@ -1092,3 +1092,38 @@ fn test_iter_product_generic() { assert_eq!(result, data.iter().product()); assert_eq!(result, data.into_iter().product()); } + +#[test] +fn test_pow() { + let one = 1u32.to_bigint().unwrap(); + let two = 2u32.to_bigint().unwrap(); + let minus_two = -2i32.to_bigint().unwrap(); + let four = 4u32.to_bigint().unwrap(); + let eight = 8u32.to_bigint().unwrap(); + macro_rules! check { + ($t:ty) => { + assert_eq!((&two).pow(0 as $t), one); + assert_eq!(two.clone().pow(0 as $t), one); + assert_eq!((&two).pow(1 as $t), two); + assert_eq!(two.clone().pow(1 as $t), two); + assert_eq!((&two).clone().pow(2 as $t), four); + assert_eq!(two.clone().pow(2 as $t), four); + assert_eq!((&two).pow(3 as $t), eight); + assert_eq!(two.clone().pow(3 as $t), eight); + assert_eq!((&minus_two).pow(0 as $t), one, "-2^0"); + assert_eq!((&minus_two).pow(1 as $t), minus_two, "-2^1"); + assert_eq!((&minus_two).pow(2 as $t), four, "-2^2"); + assert_eq!((&minus_two).pow(3 as $t), -&eight, "-2^3"); + } + } + check!(u8); + check!(i8); + check!(u16); + check!(i16); + check!(u32); + check!(i32); + check!(u64); + check!(i64); + check!(usize); + check!(isize); +} diff --git a/tests/biguint.rs b/tests/biguint.rs index 009b16a0..3ee47d2d 100644 --- a/tests/biguint.rs +++ b/tests/biguint.rs @@ -1531,7 +1531,6 @@ fn test_iter_product_generic() { assert_eq!(result, data.into_iter().product()); } - #[test] fn test_pow() { let one = 1u32.to_biguint().unwrap(); From 3f7934961491cdf33f58f034ec79cfa25d180f03 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Mon, 9 Jul 2018 17:07:51 +0200 Subject: [PATCH 3/9] Implement Pow directly on references --- src/bigint.rs | 47 ++++++++++++++++++----------------- src/biguint.rs | 64 ++++++++++++++++++++---------------------------- tests/bigint.rs | 25 ++++++------------- tests/biguint.rs | 19 +++++--------- 4 files changed, 65 insertions(+), 90 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index aae32a70..0a335d44 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -18,7 +18,7 @@ use serde; use integer::{Integer, Roots}; use traits::{ToPrimitive, FromPrimitive, Num, CheckedAdd, CheckedSub, - CheckedMul, CheckedDiv, PrimInt, Signed, Zero, One, Pow}; + CheckedMul, CheckedDiv, Signed, Zero, One, Pow}; use self::Sign::{Minus, NoSign, Plus}; @@ -66,16 +66,16 @@ impl Mul for Sign { } } -impl> Pow for Sign { +impl<'a, T: Integer> Pow<&'a T> for Sign { type Output = Sign; #[inline] - fn pow(self, other: T) -> Sign { - if self != Minus { - self - } else if other == T::zero() { + fn pow(self, other: &T) -> Sign { + if other.is_zero() { Plus - } else if other & T::one() == T::one() { + } else if self != Minus { + self + } else if other.is_odd() { self } else { -self @@ -829,27 +829,28 @@ impl Signed for BigInt { } } -impl Pow for BigInt - where BigUint: Pow -{ - type Output = BigInt; - #[inline] - fn pow(self, rhs: T) -> BigInt { - BigInt::from_biguint(self.sign.pow(rhs), self.data.pow(rhs)) +macro_rules! pow_impl { + ($type:ty) => { + impl<'a> Pow<$type> for &'a BigInt { + type Output = BigInt; + + #[inline] + fn pow(self, rhs: $type) -> BigInt { + BigInt::from_biguint(self.sign.pow(&rhs), self.data.pow(rhs)) + } + } } } -impl<'a, T: PrimInt> Pow for &'a BigInt - where BigUint: Pow -{ - type Output = BigInt; +pow_impl!(u8); +pow_impl!(u16); +pow_impl!(u32); +pow_impl!(u64); +pow_impl!(usize); +#[cfg(has_i128)] +pow_impl!(u128); - #[inline] - fn pow(self, rhs: T) -> BigInt { - BigInt::from_biguint(self.sign.pow(rhs), self.clone().data.pow(rhs)) - } -} // A convenience method for getting the absolute value of an i32 in a u32. #[inline] diff --git a/src/biguint.rs b/src/biguint.rs index f33aab11..f8add16c 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -435,55 +435,45 @@ impl One for BigUint { impl Unsigned for BigUint {} macro_rules! pow_impl { - ($unsigned:ty, $signed:ty) => { - impl pow::Pow<$unsigned> for BigUint { + ($unsigned:ty) => { + impl<'a> pow::Pow<$unsigned> for &'a BigUint { type Output = BigUint; #[inline] - fn pow(self, exp: $unsigned) -> Self::Output { - // square and multiply from num_traits::pow - pow::pow(self, exp as usize) - } - } + fn pow(self, mut exp: $unsigned) -> Self::Output { + // square and multiply from num_traits::pow in the next branch + let mut base = self.clone(); - impl<'a> pow::Pow<$unsigned> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn pow(self, exp: $unsigned) -> Self::Output { - // square and multiply from num_traits::pow - pow::pow(self.clone(), exp as usize) - } - } - - impl<'a> pow::Pow<$signed> for BigUint { - type Output = BigUint; + if exp == 0 { return BigUint::one(); } - #[inline] - fn pow(self, exp: $signed) -> Self::Output { - assert!(exp >= 0, "Negative exponentiation is not supported"); - pow::pow(self, exp as usize) - } - } + while exp & 1 == 0 { + base = &base * &base; + exp >>= 1; + } - impl<'a> pow::Pow<$signed> for &'a BigUint { - type Output = BigUint; + if exp == 1 { return base; } - #[inline] - fn pow(self, exp: $signed) -> Self::Output { - assert!(exp >= 0, "Negative exponentiation is not supported"); - pow::pow(self.clone(), exp as usize) + let mut acc = self.clone(); + while exp > 1 { + exp >>= 1; + base = &base * &base; + if exp & 1 == 1 { + acc = &acc * &base; + } + } + acc } } } } -pow_impl!(u8, i8); -pow_impl!(u16, i16); -pow_impl!(u32, i32); -pow_impl!(u64, i64); -pow_impl!(usize, isize); -// FIXME support i128 +pow_impl!(u8); +pow_impl!(u16); +pow_impl!(u32); +pow_impl!(u64); +pow_impl!(usize); +#[cfg(has_i128)] +pow_impl!(u128); forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add); forward_val_assign!(impl AddAssign for BigUint, add_assign); diff --git a/tests/bigint.rs b/tests/bigint.rs index e4ee7968..e2c582da 100644 --- a/tests/bigint.rs +++ b/tests/bigint.rs @@ -1102,28 +1102,19 @@ fn test_pow() { let eight = 8u32.to_bigint().unwrap(); macro_rules! check { ($t:ty) => { - assert_eq!((&two).pow(0 as $t), one); - assert_eq!(two.clone().pow(0 as $t), one); - assert_eq!((&two).pow(1 as $t), two); - assert_eq!(two.clone().pow(1 as $t), two); - assert_eq!((&two).clone().pow(2 as $t), four); - assert_eq!(two.clone().pow(2 as $t), four); - assert_eq!((&two).pow(3 as $t), eight); - assert_eq!(two.clone().pow(3 as $t), eight); - assert_eq!((&minus_two).pow(0 as $t), one, "-2^0"); - assert_eq!((&minus_two).pow(1 as $t), minus_two, "-2^1"); - assert_eq!((&minus_two).pow(2 as $t), four, "-2^2"); - assert_eq!((&minus_two).pow(3 as $t), -&eight, "-2^3"); + assert_eq!(two.pow(0 as $t), one); + assert_eq!(two.pow(1 as $t), two); + assert_eq!(two.pow(2 as $t), four); + assert_eq!(two.pow(3 as $t), eight); + assert_eq!(minus_two.pow(0 as $t), one, "-2^0"); + assert_eq!(minus_two.pow(1 as $t), minus_two, "-2^1"); + assert_eq!(minus_two.pow(2 as $t), four, "-2^2"); + assert_eq!(minus_two.pow(3 as $t), -&eight, "-2^3"); } } check!(u8); - check!(i8); check!(u16); - check!(i16); check!(u32); - check!(i32); check!(u64); - check!(i64); check!(usize); - check!(isize); } diff --git a/tests/biguint.rs b/tests/biguint.rs index 3ee47d2d..565fcce4 100644 --- a/tests/biguint.rs +++ b/tests/biguint.rs @@ -1539,24 +1539,17 @@ fn test_pow() { let eight = 8u32.to_biguint().unwrap(); macro_rules! check { ($t:ty) => { - assert_eq!((&two).pow(0 as $t), one); - assert_eq!(two.clone().pow(0 as $t), one); - assert_eq!((&two).pow(1 as $t), two); - assert_eq!(two.clone().pow(1 as $t), two); - assert_eq!((&two).clone().pow(2 as $t), four); - assert_eq!(two.clone().pow(2 as $t), four); - assert_eq!((&two).pow(3 as $t), eight); - assert_eq!(two.clone().pow(3 as $t), eight); + assert_eq!(two.pow(0 as $t), one); + assert_eq!(two.pow(1 as $t), two); + assert_eq!(two.pow(2 as $t), four); + assert_eq!(two.pow(3 as $t), eight); } } check!(u8); - check!(i8); check!(u16); - check!(i16); check!(u32); - check!(i32); check!(u64); - check!(i64); check!(usize); - check!(isize); + #[cfg(has_i128)] + check!(u128); } From 9009cf80d7e342f7a31e120236a9f4d2ffb6e1d9 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Thu, 19 Jul 2018 16:57:24 +0200 Subject: [PATCH 4/9] Address feedback --- src/bigint.rs | 36 +++++++++++++++++------------------- src/biguint.rs | 16 ++++++++++++---- tests/biguint.rs | 13 +++++++++---- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 0a335d44..2cd9abe0 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -66,24 +66,6 @@ impl Mul for Sign { } } -impl<'a, T: Integer> Pow<&'a T> for Sign { - type Output = Sign; - - #[inline] - fn pow(self, other: &T) -> Sign { - if other.is_zero() { - Plus - } else if self != Minus { - self - } else if other.is_odd() { - self - } else { - -self - } - } -} - - #[cfg(feature = "serde")] impl serde::Serialize for Sign { fn serialize(&self, serializer: S) -> Result @@ -830,6 +812,22 @@ impl Signed for BigInt { } +/// Help function for pow +/// +/// Computes the effect of the exponent on the sign. +#[inline] +fn powsign(sign: Sign, other: &T) -> Sign { + if other.is_zero() { + Plus + } else if sign != Minus { + sign + } else if other.is_odd() { + sign + } else { + -sign + } +} + macro_rules! pow_impl { ($type:ty) => { impl<'a> Pow<$type> for &'a BigInt { @@ -837,7 +835,7 @@ macro_rules! pow_impl { #[inline] fn pow(self, rhs: $type) -> BigInt { - BigInt::from_biguint(self.sign.pow(&rhs), self.data.pow(rhs)) + BigInt::from_biguint(powsign(self.sign, &rhs), (&self.data).pow(rhs)) } } } diff --git a/src/biguint.rs b/src/biguint.rs index f8add16c..eaf04256 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -436,15 +436,14 @@ impl Unsigned for BigUint {} macro_rules! pow_impl { ($unsigned:ty) => { - impl<'a> pow::Pow<$unsigned> for &'a BigUint { + impl<'a> pow::Pow<$unsigned> for &'a BigUint { type Output = BigUint; #[inline] fn pow(self, mut exp: $unsigned) -> Self::Output { - // square and multiply from num_traits::pow in the next branch + if exp == 0 { return BigUint::one(); } let mut base = self.clone(); - if exp == 0 { return BigUint::one(); } while exp & 1 == 0 { base = &base * &base; @@ -453,7 +452,7 @@ macro_rules! pow_impl { if exp == 1 { return base; } - let mut acc = self.clone(); + let mut acc = base.clone(); while exp > 1 { exp >>= 1; base = &base * &base; @@ -464,6 +463,15 @@ macro_rules! pow_impl { acc } } + + impl<'a, 'b> pow::Pow<&'b $unsigned> for &'a BigUint { + type Output = BigUint; + + #[inline] + fn pow(self, exp: &$unsigned) -> Self::Output { + self.pow(*exp) + } + } } } diff --git a/tests/biguint.rs b/tests/biguint.rs index 565fcce4..35c54c70 100644 --- a/tests/biguint.rs +++ b/tests/biguint.rs @@ -1533,16 +1533,21 @@ fn test_iter_product_generic() { #[test] fn test_pow() { - let one = 1u32.to_biguint().unwrap(); - let two = 2u32.to_biguint().unwrap(); - let four = 4u32.to_biguint().unwrap(); - let eight = 8u32.to_biguint().unwrap(); + let one = BigUint::from(1u32); + let two = BigUint::from(2u32); + let four = BigUint::from(4u32); + let eight = BigUint::from(8u32); + let tentwentyfour = BigUint::from(1024u32); + let twentyfourtyeight = BigUint::from(2048u32); macro_rules! check { ($t:ty) => { assert_eq!(two.pow(0 as $t), one); assert_eq!(two.pow(1 as $t), two); assert_eq!(two.pow(2 as $t), four); assert_eq!(two.pow(3 as $t), eight); + assert_eq!(two.pow(10 as $t), tentwentyfour); + assert_eq!(two.pow(11 as $t), twentyfourtyeight); + assert_eq!(two.pow(&(11 as $t)), twentyfourtyeight); } } check!(u8); From ab3594f87801f3de45b96d4cf70aaf2d53fbb8f1 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Thu, 19 Jul 2018 16:59:18 +0200 Subject: [PATCH 5/9] Also allow `BigInt.pow(&$type)` --- src/bigint.rs | 9 +++++++++ tests/bigint.rs | 1 + 2 files changed, 10 insertions(+) diff --git a/src/bigint.rs b/src/bigint.rs index 2cd9abe0..27afed12 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -838,6 +838,15 @@ macro_rules! pow_impl { BigInt::from_biguint(powsign(self.sign, &rhs), (&self.data).pow(rhs)) } } + + impl<'a, 'b> Pow<&'b $type> for &'a BigInt { + type Output = BigInt; + + #[inline] + fn pow(self, rhs: &$type) -> BigInt { + BigInt::from_biguint(powsign(self.sign, rhs), (&self.data).pow(rhs)) + } + } } } diff --git a/tests/bigint.rs b/tests/bigint.rs index e2c582da..2b65ff01 100644 --- a/tests/bigint.rs +++ b/tests/bigint.rs @@ -1106,6 +1106,7 @@ fn test_pow() { assert_eq!(two.pow(1 as $t), two); assert_eq!(two.pow(2 as $t), four); assert_eq!(two.pow(3 as $t), eight); + assert_eq!(two.pow(&(3 as $t)), eight); assert_eq!(minus_two.pow(0 as $t), one, "-2^0"); assert_eq!(minus_two.pow(1 as $t), minus_two, "-2^1"); assert_eq!(minus_two.pow(2 as $t), four, "-2^2"); From d3ef15195edc4a0418e45a2d9ab73f80aa470a9e Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Thu, 19 Jul 2018 17:01:56 +0200 Subject: [PATCH 6/9] also use BigInt::from --- tests/bigint.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/bigint.rs b/tests/bigint.rs index 2b65ff01..67c14921 100644 --- a/tests/bigint.rs +++ b/tests/bigint.rs @@ -1095,11 +1095,11 @@ fn test_iter_product_generic() { #[test] fn test_pow() { - let one = 1u32.to_bigint().unwrap(); - let two = 2u32.to_bigint().unwrap(); - let minus_two = -2i32.to_bigint().unwrap(); - let four = 4u32.to_bigint().unwrap(); - let eight = 8u32.to_bigint().unwrap(); + let one = BigInt::from(1i32); + let two = BigInt::from(2i32); + let four = BigInt::from(4i32); + let eight = BigInt::from(8i32); + let minus_two = BigInt::from(-2i32); macro_rules! check { ($t:ty) => { assert_eq!(two.pow(0 as $t), one); From 5fe8a5fbdf26164d74d60b335dc72a87b778ab37 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Thu, 19 Jul 2018 17:07:57 +0200 Subject: [PATCH 7/9] Get rid of num_traits::pow usage See also #56 --- benches/bigint.rs | 2 +- src/biguint.rs | 8 ++++---- tests/roots.rs | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/benches/bigint.rs b/benches/bigint.rs index 6893f137..f50a74a9 100644 --- a/benches/bigint.rs +++ b/benches/bigint.rs @@ -301,7 +301,7 @@ fn pow_bench(b: &mut Bencher) { for i in 2..upper + 1 { for j in 2..upper + 1 { let i_big = BigUint::from_usize(i).unwrap(); - num_traits::pow(i_big, j); + i_big.pow(j); } } }); diff --git a/src/biguint.rs b/src/biguint.rs index eaf04256..826c95b6 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -19,7 +19,7 @@ use serde; use integer::{Integer, Roots}; use traits::{ToPrimitive, FromPrimitive, Float, Num, Unsigned, CheckedAdd, CheckedSub, CheckedMul, - CheckedDiv, Zero, One, pow}; + CheckedDiv, Zero, One, Pow}; use big_digit::{self, BigDigit, DoubleBigDigit}; @@ -436,7 +436,7 @@ impl Unsigned for BigUint {} macro_rules! pow_impl { ($unsigned:ty) => { - impl<'a> pow::Pow<$unsigned> for &'a BigUint { + impl<'a> Pow<$unsigned> for &'a BigUint { type Output = BigUint; #[inline] @@ -464,7 +464,7 @@ macro_rules! pow_impl { } } - impl<'a, 'b> pow::Pow<&'b $unsigned> for &'a BigUint { + impl<'a, 'b> Pow<&'b $unsigned> for &'a BigUint { type Output = BigUint; #[inline] @@ -1105,7 +1105,7 @@ impl Roots for BigUint { loop { s = u; - let q = self / pow(s.clone(), n_min_1); + let q = self / s.pow(n_min_1); let t: BigUint = n_min_1 * &s + q; u = t / n; diff --git a/tests/roots.rs b/tests/roots.rs index 58838b76..442f40a9 100644 --- a/tests/roots.rs +++ b/tests/roots.rs @@ -4,7 +4,7 @@ extern crate num_traits; mod biguint { use num_bigint::BigUint; - use num_traits::pow; + use num_traits::Pow; use std::str::FromStr; fn check(x: u64, n: u32) { @@ -17,8 +17,8 @@ mod biguint { assert_eq!(&res, &big_x.cbrt()) } - assert!(pow(res.clone(), n as usize) <= big_x); - assert!(pow(res.clone() + 1u32, n as usize) > big_x); + assert!(res.pow(n) <= big_x); + assert!((res + 1u32).pow(n) > big_x); } #[test] @@ -58,7 +58,7 @@ mod biguint { mod bigint { use num_bigint::BigInt; - use num_traits::{Signed, pow}; + use num_traits::{Signed, Pow}; fn check(x: i64, n: u32) { let big_x = BigInt::from(x); @@ -71,11 +71,11 @@ mod bigint { } if big_x.is_negative() { - assert!(pow(res.clone() - 1u32, n as usize) < big_x); - assert!(pow(res.clone(), n as usize) >= big_x); + assert!(res.pow(n) >= big_x); + assert!((res - 1u32).pow(n) < big_x); } else { - assert!(pow(res.clone(), n as usize) <= big_x); - assert!(pow(res.clone() + 1u32, n as usize) > big_x); + assert!(res.pow(n) <= big_x); + assert!((res + 1u32).pow(n) > big_x); } } From de5b78c26afd615a035342e7711c4fa08b4acfdd Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Thu, 19 Jul 2018 17:15:06 +0200 Subject: [PATCH 8/9] Avoid 'unsigned' and 'type' as macro variable It seems to break R1.15 --- src/bigint.rs | 10 +++++----- src/biguint.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 27afed12..520e37dc 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -829,21 +829,21 @@ fn powsign(sign: Sign, other: &T) -> Sign { } macro_rules! pow_impl { - ($type:ty) => { - impl<'a> Pow<$type> for &'a BigInt { + ($T:ty) => { + impl<'a> Pow<$T> for &'a BigInt { type Output = BigInt; #[inline] - fn pow(self, rhs: $type) -> BigInt { + fn pow(self, rhs: $T) -> BigInt { BigInt::from_biguint(powsign(self.sign, &rhs), (&self.data).pow(rhs)) } } - impl<'a, 'b> Pow<&'b $type> for &'a BigInt { + impl<'a, 'b> Pow<&'b $T> for &'a BigInt { type Output = BigInt; #[inline] - fn pow(self, rhs: &$type) -> BigInt { + fn pow(self, rhs: &$T) -> BigInt { BigInt::from_biguint(powsign(self.sign, rhs), (&self.data).pow(rhs)) } } diff --git a/src/biguint.rs b/src/biguint.rs index 826c95b6..795ae323 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -435,12 +435,12 @@ impl One for BigUint { impl Unsigned for BigUint {} macro_rules! pow_impl { - ($unsigned:ty) => { - impl<'a> Pow<$unsigned> for &'a BigUint { + ($T:ty) => { + impl<'a> Pow<$T> for &'a BigUint { type Output = BigUint; #[inline] - fn pow(self, mut exp: $unsigned) -> Self::Output { + fn pow(self, mut exp: $T) -> Self::Output { if exp == 0 { return BigUint::one(); } let mut base = self.clone(); @@ -464,11 +464,11 @@ macro_rules! pow_impl { } } - impl<'a, 'b> Pow<&'b $unsigned> for &'a BigUint { + impl<'a, 'b> Pow<&'b $T> for &'a BigUint { type Output = BigUint; #[inline] - fn pow(self, exp: &$unsigned) -> Self::Output { + fn pow(self, exp: &$T) -> Self::Output { self.pow(*exp) } } From 03e01cb3f04658cfcd4b4e698fb2b4b8db1ffa26 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Fri, 27 Jul 2018 12:22:46 +0200 Subject: [PATCH 9/9] Fix benchmark --- benches/bigint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/bigint.rs b/benches/bigint.rs index f50a74a9..bba683bc 100644 --- a/benches/bigint.rs +++ b/benches/bigint.rs @@ -10,7 +10,7 @@ extern crate rand; use std::mem::replace; use test::Bencher; use num_bigint::{BigInt, BigUint, RandBigInt}; -use num_traits::{Zero, One, FromPrimitive, Num}; +use num_traits::{Zero, One, FromPrimitive, Num, Pow}; use rand::{SeedableRng, StdRng}; fn get_rng() -> StdRng {