malachite_base/num/arithmetic/pow.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::num::arithmetic::traits::{Parity, Pow, PowAssign};
10use crate::num::conversion::traits::ExactFrom;
11
12macro_rules! impl_pow_unsigned {
13 ($t:ident) => {
14 impl Pow<u64> for $t {
15 type Output = $t;
16
17 /// This is a wrapper over the `pow` functions in the standard library, for example
18 /// [this one](u32::pow).
19 #[inline]
20 fn pow(self, exp: u64) -> $t {
21 if exp == 0 {
22 1
23 } else if self < 2 {
24 self
25 } else {
26 self.pow(u32::exact_from(exp))
27 }
28 }
29 }
30 };
31}
32apply_to_unsigneds!(impl_pow_unsigned);
33
34macro_rules! impl_pow_signed {
35 ($t:ident) => {
36 impl Pow<u64> for $t {
37 type Output = $t;
38
39 /// This is a wrapper over the `pow` functions in the standard library, for example
40 /// [this one](i32::pow).
41 #[inline]
42 fn pow(self, exp: u64) -> $t {
43 if exp == 0 {
44 1
45 } else if self == 0 || self == 1 {
46 self
47 } else if self == -1 {
48 if exp.even() { 1 } else { -1 }
49 } else {
50 self.pow(u32::exact_from(exp))
51 }
52 }
53 }
54 };
55}
56apply_to_signeds!(impl_pow_signed);
57
58macro_rules! impl_pow_primitive_int {
59 ($t:ident) => {
60 impl PowAssign<u64> for $t {
61 /// Raises a number to a power, in place.
62 ///
63 /// # Worst-case complexity
64 /// $T(n) = O(n)$
65 ///
66 /// $M(n) = O(1)$
67 ///
68 /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`.
69 /// The square-and-multiply ladder performs one or two multiplications per exponent bit.
70 ///
71 /// # Examples
72 /// See [here](super::pow#pow_assign).
73 #[inline]
74 fn pow_assign(&mut self, exp: u64) {
75 *self = Pow::pow(*self, exp);
76 }
77 }
78 };
79}
80apply_to_primitive_ints!(impl_pow_primitive_int);
81
82macro_rules! impl_pow_primitive_float {
83 ($t:ident) => {
84 impl Pow<i64> for $t {
85 type Output = $t;
86
87 /// This is a wrapper over the `powi` functions in the standard library, for example
88 /// [this one](f32::powi).
89 #[inline]
90 fn pow(self, exp: i64) -> $t {
91 libm::Libm::<$t>::pow(self, exp as $t)
92 }
93 }
94
95 impl PowAssign<i64> for $t {
96 /// Raises a number to a power, in place.
97 ///
98 /// # Worst-case complexity
99 /// Constant time and additional memory.
100 ///
101 /// # Examples
102 /// See [here](super::pow#pow_assign).
103 #[inline]
104 fn pow_assign(&mut self, exp: i64) {
105 *self = libm::Libm::<$t>::pow(*self, exp as $t);
106 }
107 }
108
109 impl Pow<$t> for $t {
110 type Output = $t;
111
112 /// This is a wrapper over the `powf` functions in the standard library, for example
113 /// [this one](f32::powf).
114 #[inline]
115 fn pow(self, exp: $t) -> $t {
116 libm::Libm::<$t>::pow(self, exp)
117 }
118 }
119
120 impl PowAssign<$t> for $t {
121 /// Raises a number to a power, in place.
122 ///
123 /// # Worst-case complexity
124 /// Constant time and additional memory.
125 ///
126 /// # Examples
127 /// See [here](super::pow#pow_assign).
128 #[inline]
129 fn pow_assign(&mut self, exp: $t) {
130 *self = libm::Libm::<$t>::pow(*self, exp);
131 }
132 }
133 };
134}
135apply_to_primitive_floats!(impl_pow_primitive_float);