malachite_nz/natural/arithmetic/mod_power_of_2_pow.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MP Library.
4//
5// Copyright © 2007-2009, 2012, 2015, 2016, 2018 Free Software Foundation, Inc.
6//
7// This file is part of Malachite.
8//
9// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
10// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
11// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
12
13use crate::natural::InnerNatural::{Large, Small};
14use crate::natural::arithmetic::mod_pow::{get_bits, get_window_size};
15use crate::natural::arithmetic::mod_power_of_2::limbs_vec_mod_power_of_2_in_place;
16use crate::natural::arithmetic::mod_power_of_2_square::limbs_square_low;
17use crate::natural::arithmetic::mul::mul_low::limbs_mul_low_same_length;
18use crate::natural::logic::bit_access::limbs_get_bit;
19use crate::natural::logic::significant_bits::limbs_significant_bits;
20use crate::natural::{Natural, bit_to_limb_count_ceiling};
21use crate::platform::Limb;
22use alloc::vec::Vec;
23use malachite_base::num::arithmetic::traits::{ModPowerOf2Pow, ModPowerOf2PowAssign, PowerOf2};
24use malachite_base::num::basic::integers::PrimitiveInt;
25use malachite_base::num::basic::traits::{One, Zero};
26use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, WrappingFrom};
27use malachite_base::num::logic::traits::{SignificantBits, TrailingZeros};
28
29// Raise an n-limb number to a power and return the lowest n limbs of the result.
30//
31// # Worst-case complexity
32// $T(n, m) = O(mn \log n \log\log n)$
33//
34// $M(n) = O(n \log n)$
35//
36// where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `es.len()`.
37//
38// This is equivalent to `mpn_powlo` from `mpn/generic/powlo.c`, GMP 6.2.1, where `rp == bp`.
39// Investigate changes from 6.1.2?
40pub_crate_test! {limbs_pow_low(xs: &mut [Limb], es: &[Limb], scratch: &mut [Limb]) {
41 let xs_len = xs.len();
42 assert_ne!(xs_len, 0);
43 let scratch = &mut scratch[..xs_len];
44 let es_len = es.len();
45 assert_ne!(es_len, 0);
46 assert_ne!(es[es_len - 1], 0);
47 assert!(es_len > 1 || es_len == 1 && es[0] > 1);
48 let mut bit_index = limbs_significant_bits(es);
49 let window_size = get_window_size(bit_index);
50 assert!(window_size < bit_index);
51 let mut powers = vec![0; xs_len << (window_size - 1)];
52 let mut powers: Vec<&mut [Limb]> = powers.chunks_mut(xs_len).collect();
53 powers[0].copy_from_slice(xs);
54 // Store x ^ 2 in scratch.
55 limbs_square_low(scratch, xs);
56 // Precompute odd powers of x and put them in `powers`.
57 for i in 1..usize::power_of_2(window_size - 1) {
58 let (powers_lo, powers_hi) = powers.split_at_mut(i);
59 limbs_mul_low_same_length(powers_hi[0], powers_lo[i - 1], scratch);
60 }
61 let mut exp_bits = get_bits(es, bit_index, window_size);
62 let trailing_zeros = TrailingZeros::trailing_zeros(Limb::exact_from(exp_bits));
63 bit_index += trailing_zeros;
64 bit_index -= window_size;
65 xs.copy_from_slice(powers[exp_bits >> trailing_zeros >> 1]);
66 while bit_index != 0 {
67 while bit_index != 0 && !limbs_get_bit(es, bit_index - 1) {
68 limbs_square_low(scratch, xs);
69 xs.copy_from_slice(scratch);
70 bit_index -= 1;
71 }
72 if bit_index == 0 {
73 break;
74 }
75 // The next bit of the exponent is 1. Now extract the largest block of bits <= window_size,
76 // and such that the least significant bit is 1.
77 exp_bits = get_bits(es, bit_index, window_size);
78 let mut this_windowsize = window_size;
79 if bit_index < window_size {
80 this_windowsize -= window_size - bit_index;
81 bit_index = 0;
82 } else {
83 bit_index -= window_size;
84 }
85 let trailing_zeros = TrailingZeros::trailing_zeros(Limb::exact_from(exp_bits));
86 this_windowsize -= trailing_zeros;
87 bit_index += trailing_zeros;
88 while this_windowsize > 1 {
89 limbs_square_low(scratch, xs);
90 limbs_square_low(xs, scratch);
91 this_windowsize -= 2;
92 }
93 if this_windowsize == 1 {
94 limbs_square_low(scratch, xs);
95 } else {
96 scratch.copy_from_slice(xs);
97 }
98 limbs_mul_low_same_length(xs, scratch, powers[exp_bits >> trailing_zeros >> 1]);
99 }
100}}
101
102// Interpreting a `Vec<Limb>` and a `&[Limb]` as the limbs (in ascending order) of two `Natural`s,
103// writes the limbs of the first `Natural` raised to the second, mod $2^k$, to the input `Vec`.
104// Assumes the input is already reduced mod $2^k$. Neither input may be empty or have trailing
105// zeros, and the exponent must be greater than 1.
106//
107// # Worst-case complexity
108// $T(n, m) = O(mn \log n \log\log n)$
109//
110// $M(n) = O(n \log n)$
111//
112// where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `es.len()`.
113//
114// # Panics
115// Panics if the exponent has trailing zeros or is 1.
116pub_test! {limbs_mod_power_of_2_pow(xs: &mut Vec<Limb>, es: &[Limb], pow: u64) {
117 let out_len = bit_to_limb_count_ceiling(pow);
118 xs.resize(out_len, 0);
119 let mut scratch = vec![0; out_len];
120 limbs_pow_low(xs, es, &mut scratch);
121 limbs_vec_mod_power_of_2_in_place(xs, pow);
122}}
123
124impl ModPowerOf2Pow<Self> for Natural {
125 type Output = Self;
126
127 /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$. The base must be already reduced
128 /// modulo $2^k$. Both [`Natural`]s are taken by value.
129 ///
130 /// $f(x, n, k) = y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$.
131 ///
132 /// # Worst-case complexity
133 /// $T(n, m) = O(mn \log n \log\log n)$
134 ///
135 /// $M(n) = O(n \log n)$
136 ///
137 /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is
138 /// `exp.significant_bits()`.
139 ///
140 /// # Panics
141 /// Panics if `self` is greater than or equal to $2^k$.
142 ///
143 /// # Examples
144 /// ```
145 /// use malachite_base::num::arithmetic::traits::ModPowerOf2Pow;
146 /// use malachite_nz::natural::Natural;
147 ///
148 /// assert_eq!(
149 /// Natural::from(3u32).mod_power_of_2_pow(Natural::from(10u32), 8),
150 /// 169
151 /// );
152 /// assert_eq!(
153 /// Natural::from(11u32).mod_power_of_2_pow(Natural::from(1000u32), 30),
154 /// 289109473
155 /// );
156 /// ```
157 #[inline]
158 fn mod_power_of_2_pow(mut self, exp: Self, pow: u64) -> Self {
159 self.mod_power_of_2_pow_assign(exp, pow);
160 self
161 }
162}
163
164impl ModPowerOf2Pow<&Self> for Natural {
165 type Output = Self;
166
167 /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$. The base must be already reduced
168 /// modulo $2^k$. The first [`Natural`] is taken by value and the second by reference.
169 ///
170 /// $f(x, n, k) = y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$.
171 ///
172 /// # Worst-case complexity
173 /// $T(n, m) = O(mn \log n \log\log n)$
174 ///
175 /// $M(n) = O(n \log n)$
176 ///
177 /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is
178 /// `exp.significant_bits()`.
179 ///
180 /// # Panics
181 /// Panics if `self` is greater than or equal to $2^k$.
182 ///
183 /// # Examples
184 /// ```
185 /// use malachite_base::num::arithmetic::traits::ModPowerOf2Pow;
186 /// use malachite_nz::natural::Natural;
187 ///
188 /// assert_eq!(
189 /// Natural::from(3u32).mod_power_of_2_pow(&Natural::from(10u32), 8),
190 /// 169
191 /// );
192 /// assert_eq!(
193 /// Natural::from(11u32).mod_power_of_2_pow(&Natural::from(1000u32), 30),
194 /// 289109473
195 /// );
196 /// ```
197 #[inline]
198 fn mod_power_of_2_pow(mut self, exp: &Self, pow: u64) -> Self {
199 self.mod_power_of_2_pow_assign(exp, pow);
200 self
201 }
202}
203
204impl ModPowerOf2Pow<Natural> for &Natural {
205 type Output = Natural;
206
207 /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$. The base must be already reduced
208 /// modulo $2^k$. The first [`Natural`] is taken by reference and the second by value.
209 ///
210 /// $f(x, n, k) = y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$.
211 ///
212 /// # Worst-case complexity
213 /// $T(n, m) = O(mn \log n \log\log n)$
214 ///
215 /// $M(n) = O(n \log n)$
216 ///
217 /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is
218 /// `exp.significant_bits()`.
219 ///
220 /// # Panics
221 /// Panics if `self` is greater than or equal to $2^k$.
222 ///
223 /// # Examples
224 /// ```
225 /// use malachite_base::num::arithmetic::traits::ModPowerOf2Pow;
226 /// use malachite_nz::natural::Natural;
227 ///
228 /// assert_eq!(
229 /// (&Natural::from(3u32)).mod_power_of_2_pow(Natural::from(10u32), 8),
230 /// 169
231 /// );
232 /// assert_eq!(
233 /// (&Natural::from(11u32)).mod_power_of_2_pow(Natural::from(1000u32), 30),
234 /// 289109473
235 /// );
236 /// ```
237 #[inline]
238 fn mod_power_of_2_pow(self, exp: Natural, pow: u64) -> Natural {
239 self.mod_power_of_2_pow(&exp, pow)
240 }
241}
242
243impl ModPowerOf2Pow<&Natural> for &Natural {
244 type Output = Natural;
245
246 /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$. The base must be already reduced
247 /// modulo $2^k$. Both [`Natural`]s are taken by reference.
248 ///
249 /// # Worst-case complexity
250 /// $T(n, m) = O(mn \log n \log\log n)$
251 ///
252 /// $M(n) = O(n \log n)$
253 ///
254 /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is
255 /// `exp.significant_bits()`.
256 ///
257 /// # Panics
258 /// Panics if `self` is greater than or equal to $2^k$.
259 ///
260 /// # Examples
261 /// ```
262 /// use malachite_base::num::arithmetic::traits::ModPowerOf2Pow;
263 /// use malachite_nz::natural::Natural;
264 ///
265 /// assert_eq!(
266 /// (&Natural::from(3u32)).mod_power_of_2_pow(&Natural::from(10u32), 8),
267 /// 169
268 /// );
269 /// assert_eq!(
270 /// (&Natural::from(11u32)).mod_power_of_2_pow(&Natural::from(1000u32), 30),
271 /// 289109473
272 /// );
273 /// ```
274 #[inline]
275 fn mod_power_of_2_pow(self, exp: &Natural, pow: u64) -> Natural {
276 assert!(
277 self.significant_bits() <= pow,
278 "self must be reduced mod 2^pow, but {self} >= 2^{pow}"
279 );
280 match (self, exp) {
281 _ if pow == 0 => Natural::ZERO,
282 (_, &Natural::ZERO) => Natural::ONE,
283 (&Natural::ZERO | &Natural::ONE, _) | (_, &Natural::ONE) => self.clone(),
284 (Natural(Small(x)), Natural(Small(e)))
285 if pow <= Limb::WIDTH && u64::convertible_from(*e) =>
286 {
287 Natural(Small(x.mod_power_of_2_pow(u64::wrapping_from(*e), pow)))
288 }
289 (_, Natural(Small(e))) => {
290 let mut xs = self.to_limbs_asc();
291 limbs_mod_power_of_2_pow(&mut xs, &[*e], pow);
292 Natural::from_owned_limbs_asc(xs)
293 }
294 (_, Natural(Large(es))) => {
295 let mut xs = self.to_limbs_asc();
296 limbs_mod_power_of_2_pow(&mut xs, es, pow);
297 Natural::from_owned_limbs_asc(xs)
298 }
299 }
300 }
301}
302
303impl ModPowerOf2PowAssign<Self> for Natural {
304 /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$, in place. The base must be already
305 /// reduced modulo $2^k$. The [`Natural`] on the right-hand side is taken by value.
306 ///
307 /// $x \gets y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$.
308 ///
309 /// # Worst-case complexity
310 /// $T(n, m) = O(mn \log n \log\log n)$
311 ///
312 /// $M(n) = O(n \log n)$
313 ///
314 /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is
315 /// `exp.significant_bits()`.
316 ///
317 /// # Panics
318 /// Panics if `self` is greater than or equal to $2^k$.
319 ///
320 /// # Examples
321 /// ```
322 /// use malachite_base::num::arithmetic::traits::ModPowerOf2PowAssign;
323 /// use malachite_nz::natural::Natural;
324 ///
325 /// let mut x = Natural::from(3u32);
326 /// x.mod_power_of_2_pow_assign(Natural::from(10u32), 8);
327 /// assert_eq!(x, 169);
328 ///
329 /// let mut x = Natural::from(11u32);
330 /// x.mod_power_of_2_pow_assign(Natural::from(1000u32), 30);
331 /// assert_eq!(x, 289109473);
332 /// ```
333 #[inline]
334 fn mod_power_of_2_pow_assign(&mut self, exp: Self, pow: u64) {
335 self.mod_power_of_2_pow_assign(&exp, pow);
336 }
337}
338
339impl ModPowerOf2PowAssign<&Self> for Natural {
340 /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$, in place. The base must be already
341 /// reduced modulo $2^k$. The [`Natural`] on the right-hand side is taken by reference.
342 ///
343 /// $x \gets y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$.
344 ///
345 /// # Worst-case complexity
346 /// $T(n, m) = O(mn \log n \log\log n)$
347 ///
348 /// $M(n) = O(n \log n)$
349 ///
350 /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is
351 /// `exp.significant_bits()`.
352 ///
353 /// # Panics
354 /// Panics if `self` is greater than or equal to $2^k$.
355 ///
356 /// # Examples
357 /// ```
358 /// use malachite_base::num::arithmetic::traits::ModPowerOf2PowAssign;
359 /// use malachite_nz::natural::Natural;
360 ///
361 /// let mut x = Natural::from(3u32);
362 /// x.mod_power_of_2_pow_assign(&Natural::from(10u32), 8);
363 /// assert_eq!(x, 169);
364 ///
365 /// let mut x = Natural::from(11u32);
366 /// x.mod_power_of_2_pow_assign(&Natural::from(1000u32), 30);
367 /// assert_eq!(x, 289109473);
368 /// ```
369 fn mod_power_of_2_pow_assign(&mut self, exp: &Self, pow: u64) {
370 assert!(
371 self.significant_bits() <= pow,
372 "self must be reduced mod 2^pow, but {self} >= 2^{pow}"
373 );
374 match (&mut *self, exp) {
375 _ if pow == 0 => *self = Self::ZERO,
376 (_, &Self::ZERO) => *self = Self::ONE,
377 (&mut (Self::ZERO | Self::ONE), _) | (_, &Self::ONE) => {}
378 (Self(Small(x)), Self(Small(e))) if pow <= Limb::WIDTH && u64::convertible_from(*e) => {
379 x.mod_power_of_2_pow_assign(u64::wrapping_from(*e), pow);
380 }
381 (_, Self(Small(e))) => {
382 let xs = self.promote_in_place();
383 limbs_mod_power_of_2_pow(xs, &[*e], pow);
384 self.trim();
385 }
386 (_, Self(Large(es))) => {
387 let xs = self.promote_in_place();
388 limbs_mod_power_of_2_pow(xs, es, pow);
389 self.trim();
390 }
391 }
392 }
393}