Skip to main content

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);