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