Skip to content

Commit 14b6f73

Browse files
committed
Move powers to separate modules
1 parent 00f0d2b commit 14b6f73

File tree

5 files changed

+356
-336
lines changed

5 files changed

+356
-336
lines changed

src/bigint.rs

Lines changed: 2 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ mod multiplication;
3434
mod subtraction;
3535

3636
mod bits;
37+
mod power;
3738
mod shift;
3839

3940
/// A Sign is a `BigInt`'s composing element.
@@ -385,68 +386,6 @@ impl Signed for BigInt {
385386
}
386387
}
387388

388-
/// Help function for pow
389-
///
390-
/// Computes the effect of the exponent on the sign.
391-
#[inline]
392-
fn powsign<T: Integer>(sign: Sign, other: &T) -> Sign {
393-
if other.is_zero() {
394-
Plus
395-
} else if sign != Minus || other.is_odd() {
396-
sign
397-
} else {
398-
-sign
399-
}
400-
}
401-
402-
macro_rules! pow_impl {
403-
($T:ty) => {
404-
impl Pow<$T> for BigInt {
405-
type Output = BigInt;
406-
407-
#[inline]
408-
fn pow(self, rhs: $T) -> BigInt {
409-
BigInt::from_biguint(powsign(self.sign, &rhs), self.data.pow(rhs))
410-
}
411-
}
412-
413-
impl<'b> Pow<&'b $T> for BigInt {
414-
type Output = BigInt;
415-
416-
#[inline]
417-
fn pow(self, rhs: &$T) -> BigInt {
418-
BigInt::from_biguint(powsign(self.sign, rhs), self.data.pow(rhs))
419-
}
420-
}
421-
422-
impl<'a> Pow<$T> for &'a BigInt {
423-
type Output = BigInt;
424-
425-
#[inline]
426-
fn pow(self, rhs: $T) -> BigInt {
427-
BigInt::from_biguint(powsign(self.sign, &rhs), Pow::pow(&self.data, rhs))
428-
}
429-
}
430-
431-
impl<'a, 'b> Pow<&'b $T> for &'a BigInt {
432-
type Output = BigInt;
433-
434-
#[inline]
435-
fn pow(self, rhs: &$T) -> BigInt {
436-
BigInt::from_biguint(powsign(self.sign, rhs), Pow::pow(&self.data, rhs))
437-
}
438-
}
439-
};
440-
}
441-
442-
pow_impl!(u8);
443-
pow_impl!(u16);
444-
pow_impl!(u32);
445-
pow_impl!(u64);
446-
pow_impl!(usize);
447-
pow_impl!(u128);
448-
pow_impl!(BigUint);
449-
450389
trait UnsignedAbs {
451390
type Unsigned;
452391

@@ -1582,31 +1521,7 @@ impl BigInt {
15821521
///
15831522
/// Panics if the exponent is negative or the modulus is zero.
15841523
pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self {
1585-
assert!(
1586-
!exponent.is_negative(),
1587-
"negative exponentiation is not supported!"
1588-
);
1589-
assert!(
1590-
!modulus.is_zero(),
1591-
"attempt to calculate with zero modulus!"
1592-
);
1593-
1594-
let result = self.data.modpow(&exponent.data, &modulus.data);
1595-
if result.is_zero() {
1596-
return BigInt::zero();
1597-
}
1598-
1599-
// The sign of the result follows the modulus, like `mod_floor`.
1600-
let (sign, mag) = match (
1601-
self.is_negative() && exponent.is_odd(),
1602-
modulus.is_negative(),
1603-
) {
1604-
(false, false) => (Plus, result),
1605-
(true, false) => (Plus, &modulus.data - result),
1606-
(false, true) => (Minus, &modulus.data - result),
1607-
(true, true) => (Minus, result),
1608-
};
1609-
BigInt::from_biguint(sign, mag)
1524+
power::modpow(self, exponent, modulus)
16101525
}
16111526

16121527
/// Returns the truncated principal square root of `self` --

src/bigint/power.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use super::BigInt;
2+
use super::Sign::{self, Minus, Plus};
3+
4+
use crate::BigUint;
5+
6+
use num_integer::Integer;
7+
use num_traits::{Pow, Signed, Zero};
8+
9+
/// Help function for pow
10+
///
11+
/// Computes the effect of the exponent on the sign.
12+
#[inline]
13+
fn powsign<T: Integer>(sign: Sign, other: &T) -> Sign {
14+
if other.is_zero() {
15+
Plus
16+
} else if sign != Minus || other.is_odd() {
17+
sign
18+
} else {
19+
-sign
20+
}
21+
}
22+
23+
macro_rules! pow_impl {
24+
($T:ty) => {
25+
impl Pow<$T> for BigInt {
26+
type Output = BigInt;
27+
28+
#[inline]
29+
fn pow(self, rhs: $T) -> BigInt {
30+
BigInt::from_biguint(powsign(self.sign, &rhs), self.data.pow(rhs))
31+
}
32+
}
33+
34+
impl<'b> Pow<&'b $T> for BigInt {
35+
type Output = BigInt;
36+
37+
#[inline]
38+
fn pow(self, rhs: &$T) -> BigInt {
39+
BigInt::from_biguint(powsign(self.sign, rhs), self.data.pow(rhs))
40+
}
41+
}
42+
43+
impl<'a> Pow<$T> for &'a BigInt {
44+
type Output = BigInt;
45+
46+
#[inline]
47+
fn pow(self, rhs: $T) -> BigInt {
48+
BigInt::from_biguint(powsign(self.sign, &rhs), Pow::pow(&self.data, rhs))
49+
}
50+
}
51+
52+
impl<'a, 'b> Pow<&'b $T> for &'a BigInt {
53+
type Output = BigInt;
54+
55+
#[inline]
56+
fn pow(self, rhs: &$T) -> BigInt {
57+
BigInt::from_biguint(powsign(self.sign, rhs), Pow::pow(&self.data, rhs))
58+
}
59+
}
60+
};
61+
}
62+
63+
pow_impl!(u8);
64+
pow_impl!(u16);
65+
pow_impl!(u32);
66+
pow_impl!(u64);
67+
pow_impl!(usize);
68+
pow_impl!(u128);
69+
pow_impl!(BigUint);
70+
71+
pub(super) fn modpow(x: &BigInt, exponent: &BigInt, modulus: &BigInt) -> BigInt {
72+
assert!(
73+
!exponent.is_negative(),
74+
"negative exponentiation is not supported!"
75+
);
76+
assert!(
77+
!modulus.is_zero(),
78+
"attempt to calculate with zero modulus!"
79+
);
80+
81+
let result = x.data.modpow(&exponent.data, &modulus.data);
82+
if result.is_zero() {
83+
return BigInt::zero();
84+
}
85+
86+
// The sign of the result follows the modulus, like `mod_floor`.
87+
let (sign, mag) = match (x.is_negative() && exponent.is_odd(), modulus.is_negative()) {
88+
(false, false) => (Plus, result),
89+
(true, false) => (Plus, &modulus.data - result),
90+
(false, true) => (Minus, &modulus.data - result),
91+
(true, true) => (Minus, result),
92+
};
93+
BigInt::from_biguint(sign, mag)
94+
}

0 commit comments

Comments
 (0)