malachite_base/num/arithmetic/
wrapping_pow.rs1use crate::num::arithmetic::traits::{Parity, UnsignedAbs, WrappingPow, WrappingPowAssign};
10use crate::num::basic::signeds::PrimitiveSigned;
11use crate::num::basic::unsigneds::PrimitiveUnsigned;
12use crate::num::conversion::traits::WrappingFrom;
13use crate::num::logic::traits::BitIterable;
14
15fn wrapping_pow_unsigned<T: PrimitiveUnsigned>(x: T, exp: u64) -> T {
16 if exp == 0 {
17 T::ONE
18 } else if x < T::TWO {
19 x
20 } else {
21 let mut power = x;
22 for bit in exp.bits().rev().skip(1) {
23 power.wrapping_square_assign();
24 if bit {
25 power.wrapping_mul_assign(x);
26 }
27 }
28 power
29 }
30}
31
32fn wrapping_pow_signed<
33 U: PrimitiveUnsigned,
34 S: PrimitiveSigned + UnsignedAbs<Output = U> + WrappingFrom<U>,
35>(
36 x: S,
37 exp: u64,
38) -> S {
39 let p_abs = x.unsigned_abs().wrapping_pow(exp);
40 if x >= S::ZERO || exp.even() {
41 S::wrapping_from(p_abs)
42 } else {
43 S::wrapping_from(p_abs).wrapping_neg()
44 }
45}
46
47macro_rules! impl_wrapping_pow_unsigned {
48 ($t:ident) => {
49 impl WrappingPow<u64> for $t {
50 type Output = $t;
51
52 #[inline]
55 fn wrapping_pow(self, exp: u64) -> $t {
56 wrapping_pow_unsigned(self, exp)
57 }
58 }
59 };
60}
61apply_to_unsigneds!(impl_wrapping_pow_unsigned);
62
63macro_rules! impl_wrapping_pow_signed {
64 ($t:ident) => {
65 impl WrappingPow<u64> for $t {
66 type Output = $t;
67
68 #[inline]
71 fn wrapping_pow(self, exp: u64) -> $t {
72 wrapping_pow_signed(self, exp)
73 }
74 }
75 };
76}
77apply_to_signeds!(impl_wrapping_pow_signed);
78
79macro_rules! impl_wrapping_pow_primitive_int {
80 ($t:ident) => {
81 impl WrappingPowAssign<u64> for $t {
82 #[inline]
92 fn wrapping_pow_assign(&mut self, exp: u64) {
93 *self = WrappingPow::wrapping_pow(*self, exp);
94 }
95 }
96 };
97}
98apply_to_primitive_ints!(impl_wrapping_pow_primitive_int);