malachite_base/num/arithmetic/
pow.rs

1// Copyright © 2025 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            ///
70            /// # Examples
71            /// See [here](super::pow#pow_assign).
72            #[inline]
73            fn pow_assign(&mut self, exp: u64) {
74                *self = Pow::pow(*self, exp);
75            }
76        }
77    };
78}
79apply_to_primitive_ints!(impl_pow_primitive_int);
80
81macro_rules! impl_pow_primitive_float {
82    ($t:ident) => {
83        impl Pow<i64> for $t {
84            type Output = $t;
85
86            /// This is a wrapper over the `powi` functions in the standard library, for example
87            /// [this one](f32::powi).
88            #[inline]
89            fn pow(self, exp: i64) -> $t {
90                libm::Libm::<$t>::pow(self, exp as $t)
91            }
92        }
93
94        impl PowAssign<i64> for $t {
95            /// Raises a number to a power, in place.
96            ///
97            /// # Worst-case complexity
98            /// Constant time and additional memory.
99            ///
100            /// # Examples
101            /// See [here](super::pow#pow_assign).
102            #[inline]
103            fn pow_assign(&mut self, exp: i64) {
104                *self = libm::Libm::<$t>::pow(*self, exp as $t);
105            }
106        }
107
108        impl Pow<$t> for $t {
109            type Output = $t;
110
111            /// This is a wrapper over the `powf` functions in the standard library, for example
112            /// [this one](f32::powf).
113            #[inline]
114            fn pow(self, exp: $t) -> $t {
115                libm::Libm::<$t>::pow(self, exp)
116            }
117        }
118
119        impl PowAssign<$t> for $t {
120            /// Raises a number to a power, in place.
121            ///
122            /// # Worst-case complexity
123            /// Constant time and additional memory.
124            ///
125            /// # Examples
126            /// See [here](super::pow#pow_assign).
127            #[inline]
128            fn pow_assign(&mut self, exp: $t) {
129                *self = libm::Libm::<$t>::pow(*self, exp);
130            }
131        }
132    };
133}
134apply_to_primitive_floats!(impl_pow_primitive_float);