Skip to main content

malachite_nz/natural/arithmetic/
mod_pow.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MP Library.
4//
5//      `getbits`, `MPN_REDC_1`, `win_size`, `redcify`, `mpn_powm`, and `mpz_powm` contributed to
6//      the GNU project by Torbjörn Granlund.
7//
8//      Copyright (C) 2000-2002, 2004, 2007–2012 Free Software Foundation, Inc.
9//
10// This file is part of Malachite.
11//
12// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
13// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
14// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
15
16use crate::natural::InnerNatural::Small;
17use crate::natural::arithmetic::add::{
18    limbs_add_same_length_to_out, limbs_add_to_out_aliased,
19    limbs_slice_add_same_length_in_place_left,
20};
21use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left;
22use crate::natural::arithmetic::div_exact::{
23    limbs_modular_invert, limbs_modular_invert_limb, limbs_modular_invert_scratch_len,
24};
25use crate::natural::arithmetic::div_mod::limbs_div_limb_to_out_mod;
26use crate::natural::arithmetic::mod_op::limbs_mod_to_out;
27use crate::natural::arithmetic::mod_power_of_2_pow::limbs_pow_low;
28use crate::natural::arithmetic::mul::mul_low::limbs_mul_low_same_length;
29use crate::natural::arithmetic::mul::mul_mod::{
30    limbs_mul_mod_base_pow_n_minus_1, limbs_mul_mod_base_pow_n_minus_1_next_size,
31    limbs_mul_mod_base_pow_n_minus_1_scratch_len,
32};
33use crate::natural::arithmetic::mul::{
34    limbs_mul_greater_to_out_basecase, limbs_mul_same_length_to_out,
35    limbs_mul_same_length_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len,
36};
37use crate::natural::arithmetic::shr::limbs_shr_to_out;
38use crate::natural::arithmetic::square::{
39    limbs_square_to_out, limbs_square_to_out_basecase, limbs_square_to_out_scratch_len,
40};
41use crate::natural::arithmetic::sub::{
42    limbs_sub_greater_in_place_left, limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left,
43    limbs_sub_same_length_to_out,
44};
45use crate::natural::comparison::cmp::limbs_cmp_same_length;
46use crate::natural::logic::bit_access::limbs_get_bit;
47use crate::natural::logic::significant_bits::limbs_significant_bits;
48use crate::natural::{Natural, bit_to_limb_count_floor, limb_to_bit_count};
49use crate::platform::{Limb, MUL_TOOM22_THRESHOLD, SQR_BASECASE_THRESHOLD, SQR_TOOM2_THRESHOLD};
50use alloc::vec::Vec;
51use core::cmp::{Ordering::*, max, min};
52use malachite_base::fail_on_untested_path;
53use malachite_base::num::arithmetic::traits::{
54    ModPow, ModPowAssign, ModPowerOf2, ModPowerOf2Assign, Parity, PowerOf2, WrappingNegAssign,
55};
56use malachite_base::num::basic::integers::PrimitiveInt;
57use malachite_base::num::basic::traits::{One, Zero};
58use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, WrappingFrom};
59use malachite_base::num::logic::traits::TrailingZeros;
60use malachite_base::slices::{slice_leading_zeros, slice_set_zero};
61
62// Equivalent to limbs_slice_get_bits(xs, end.saturating_sub(len), end)[0]
63//
64// # Worst-case complexity
65// Constant time and additional memory.
66//
67// This is equivalent to `getbits` from `mpn/generic/powm.c` and `mpn/generic/powlo.c`, GMP 6.2.1.
68// Investigate changes from 6.1.2?
69pub(crate) fn get_bits(xs: &[Limb], mut end: u64, len: u64) -> usize {
70    usize::exact_from(if end < len {
71        xs[0].mod_power_of_2(end)
72    } else {
73        end -= len;
74        let i = bit_to_limb_count_floor(end);
75        end &= Limb::WIDTH_MASK;
76        let mut bits = xs[i] >> end;
77        let coend = Limb::WIDTH - end;
78        if coend < len {
79            bits += xs[i + 1] << coend;
80        }
81        bits.mod_power_of_2(len)
82    })
83}
84
85// # Worst-case complexity
86// $T(n) = O(n^2)$
87//
88// $M(n) = O(1)$
89//
90// where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`.
91//
92// This is equivalent to `mpn_redc_1` from `mpn/generic/redc_1.c`, GMP 6.2.1.
93#[allow(clippy::redundant_slicing)]
94fn limbs_redc_limb_raw(out: &mut [Limb], xs: &mut [Limb], ms: &[Limb], m_inv: Limb) -> bool {
95    let len = ms.len();
96    assert_ne!(len, 0);
97    let xs = &mut xs[..len << 1];
98    let mut xs_tail = &mut xs[..]; // force borrow rather than move
99    for _ in 0..len {
100        let product = xs_tail[0].wrapping_mul(m_inv);
101        let carry =
102            limbs_slice_add_mul_limb_same_length_in_place_left(&mut xs_tail[..len], ms, product);
103        assert_eq!(xs_tail[0], 0);
104        xs_tail[0] = carry;
105        xs_tail = &mut xs_tail[1..];
106    }
107    let (xs_lo, xs_hi) = xs.split_at(len);
108    limbs_add_same_length_to_out(out, xs_hi, xs_lo)
109}
110
111// # Worst-case complexity
112// $T(n) = O(n^2)$
113//
114// $M(n) = O(1)$
115//
116// where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`.
117//
118// This is equivalent to `MPN_REDC_1` from `mpn/generic/powm.c`, GMP 6.2.1. Investigate changes from
119// 6.1.2?
120fn limbs_redc_limb(out: &mut [Limb], xs: &mut [Limb], ms: &[Limb], m_inv: Limb) {
121    if limbs_redc_limb_raw(out, xs, ms, m_inv) {
122        limbs_sub_same_length_in_place_left(&mut out[..ms.len()], ms);
123    }
124}
125
126const WIDTH_LIMITS: [u64; 10] = [7, 25, 81, 241, 673, 1793, 4609, 11521, 28161, u64::MAX];
127
128// # Worst-case complexity
129// Constant time and additional memory.
130//
131// This is equivalent to `win_size` from `mpn/generic/powm.c`, 6.2.1. Investigate changes from
132// 6.1.2?
133pub(crate) fn get_window_size(width: u64) -> u64 {
134    u64::wrapping_from(
135        WIDTH_LIMITS
136            .iter()
137            .position(|&limit| width <= limit)
138            .unwrap()
139            + 1,
140    )
141}
142
143// # Worst-case complexity
144// $T(n) = O(n \log n \log\log n)$
145//
146// $M(n) = O(n \log n)$
147//
148// where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`.
149//
150// This is equivalent to `mpn_redc_n` from `mpn/generic/redc_n.c`, GMP 6.2.1.
151fn limbs_redc(out: &mut [Limb], xs: &[Limb], ms: &[Limb], is: &[Limb]) {
152    let ms_len = ms.len();
153    assert!(ms_len > 8);
154    let n = limbs_mul_mod_base_pow_n_minus_1_next_size(ms_len);
155    let mut scratch =
156        vec![0; limbs_mul_mod_base_pow_n_minus_1_scratch_len(n, ms_len, ms_len) + ms_len + n];
157    let (scratch_0, scratch) = scratch.split_at_mut(ms_len);
158    limbs_mul_low_same_length(scratch_0, &xs[..ms_len], &is[..ms_len]);
159    let (scratch_1, scratch_2) = scratch.split_at_mut(n);
160    limbs_mul_mod_base_pow_n_minus_1(scratch_1, n, scratch_0, ms, scratch_2);
161    let two_ms_len = ms_len << 1;
162    assert!(two_ms_len > n);
163    let m = two_ms_len - n;
164    let carry = limbs_sub_same_length_to_out(scratch_2, &scratch_1[..m], &xs[..m]);
165    let scratch = &mut scratch[..two_ms_len];
166    if carry {
167        assert!(!limbs_sub_limb_in_place(&mut scratch[m..], 1));
168    }
169    if limbs_sub_same_length_to_out(out, &xs[ms_len..two_ms_len], &scratch[ms_len..]) {
170        limbs_slice_add_same_length_in_place_left(&mut out[..ms_len], ms);
171    }
172}
173
174// Convert U to REDC form, U_r = B^n * U mod M
175//
176// # Worst-case complexity
177// $T(n) = O(n \log n \log\log n)$
178//
179// $M(n) = O(n \log n)$
180//
181// where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`.
182//
183// This is equivalent to `redcify` from `mpn/generic/powm.c`, 6.2.1. Investigate changes from 6.1.2?
184fn to_redc(out: &mut [Limb], xs: &[Limb], ms: &[Limb]) {
185    let xs_len = xs.len();
186    let ms_len = ms.len();
187    if ms_len == 1 {
188        let mut scratch = vec![0; (xs_len << 1) + ms_len + 1];
189        let (scratch, qs) = scratch.split_at_mut(xs_len + ms_len);
190        scratch[ms_len..].copy_from_slice(xs);
191        out[0] = limbs_div_limb_to_out_mod(qs, scratch, ms[0]);
192    } else {
193        let mut scratch = vec![0; xs_len + ms_len];
194        scratch[ms_len..].copy_from_slice(xs);
195        limbs_mod_to_out(out, &scratch, ms);
196    }
197}
198
199// TODO tune
200const REDC_1_TO_REDC_N_THRESHOLD: usize = 100;
201
202// # Worst-case complexity
203// Constant time and additional memory.
204pub_test! {limbs_mod_pow_odd_scratch_len(n: usize) -> usize {
205    max(limbs_modular_invert_scratch_len(n), n << 1)
206}}
207
208// # Worst-case complexity
209// $T(n) = O(n \log n \log\log n)$
210//
211// $M(n) = O(n \log n)$
212//
213// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
214fn square_using_basecase_mul(out: &mut [Limb], xs: &[Limb]) {
215    limbs_mul_greater_to_out_basecase(out, xs, xs);
216}
217
218// # Worst-case complexity
219// $T(n) = O(n^2)$
220//
221// $M(n) = O(1)$
222//
223// where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`.
224fn limbs_redc_limb_helper(out: &mut [Limb], xs: &mut [Limb], ms: &[Limb], is: &[Limb]) {
225    limbs_redc_limb(out, xs, ms, is[0]);
226}
227
228// # Worst-case complexity
229// $T(n) = O(n \log n \log\log n)$
230//
231// $M(n) = O(n \log n)$
232//
233// where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`.
234fn limbs_redc_helper(out: &mut [Limb], xs: &mut [Limb], ms: &[Limb], is: &[Limb]) {
235    limbs_redc(out, xs, ms, is);
236}
237
238// # Worst-case complexity
239// Constant time and additional memory.
240#[allow(clippy::absurd_extreme_comparisons, clippy::type_complexity)]
241fn select_fns(
242    ms_len: usize,
243) -> (
244    &'static dyn Fn(&mut [Limb], &[Limb], &[Limb]),
245    &'static dyn Fn(&mut [Limb], &[Limb]),
246    &'static dyn Fn(&mut [Limb], &mut [Limb], &[Limb], &[Limb]),
247) {
248    if REDC_1_TO_REDC_N_THRESHOLD < MUL_TOOM22_THRESHOLD {
249        if ms_len < REDC_1_TO_REDC_N_THRESHOLD {
250            (
251                &limbs_mul_greater_to_out_basecase,
252                if REDC_1_TO_REDC_N_THRESHOLD < SQR_BASECASE_THRESHOLD
253                    || !(SQR_BASECASE_THRESHOLD..=SQR_TOOM2_THRESHOLD).contains(&ms_len)
254                {
255                    &square_using_basecase_mul
256                } else {
257                    &limbs_square_to_out_basecase
258                },
259                &limbs_redc_limb_helper,
260            )
261        } else if ms_len < MUL_TOOM22_THRESHOLD {
262            (
263                &limbs_mul_greater_to_out_basecase,
264                if MUL_TOOM22_THRESHOLD < SQR_BASECASE_THRESHOLD
265                    || !(SQR_BASECASE_THRESHOLD..=SQR_TOOM2_THRESHOLD).contains(&ms_len)
266                {
267                    &square_using_basecase_mul
268                } else {
269                    &limbs_square_to_out_basecase
270                },
271                &limbs_redc_helper,
272            )
273        } else {
274            (
275                &|out, xs, ys| {
276                    let mut mul_scratch =
277                        vec![0; limbs_mul_same_length_to_out_scratch_len(xs.len())];
278                    limbs_mul_same_length_to_out(out, xs, ys, &mut mul_scratch);
279                },
280                &|out, xs| {
281                    let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(xs.len())];
282                    limbs_square_to_out(out, xs, &mut square_scratch);
283                },
284                &limbs_redc_helper,
285            )
286        }
287    } else if ms_len < MUL_TOOM22_THRESHOLD {
288        (
289            &limbs_mul_greater_to_out_basecase,
290            if MUL_TOOM22_THRESHOLD < SQR_BASECASE_THRESHOLD
291                || !(SQR_BASECASE_THRESHOLD..=SQR_TOOM2_THRESHOLD).contains(&ms_len)
292            {
293                &square_using_basecase_mul
294            } else {
295                &limbs_square_to_out_basecase
296            },
297            &limbs_redc_limb_helper,
298        )
299    } else {
300        (
301            &|out, xs, ys| {
302                let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(xs.len())];
303                limbs_mul_same_length_to_out(out, xs, ys, &mut mul_scratch);
304            },
305            &|out, xs| {
306                let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(xs.len())];
307                limbs_square_to_out(out, xs, &mut square_scratch);
308            },
309            if ms_len < REDC_1_TO_REDC_N_THRESHOLD {
310                &limbs_redc_limb_helper
311            } else {
312                &limbs_redc_helper
313            },
314        )
315    }
316}
317
318// Given the limbs of $x$, $E$, and odd $m$, writes the limbs of $x^E \mod m$ to an output slice.
319//
320// `xs`, `es`, and `ms` must be nonempty and their last elements must be nonzero. $m$ must be odd,
321// $E$ must be greater than 1, and `out` must be at least as long as `ms`. It is not required than
322// `xs` be less than `ms`.
323//
324// # Worst-case complexity
325// $T(n, m) = O(mn \log n \log\log n)$
326//
327// $M(n) = O(n \log n)$
328//
329// where $T$ is time, $M$ is additional memory, $n$ is `ms.len()`, and $m$ is `es.len()`.
330//
331// # Panics
332// Panics if `xs`, `es`, or `ms` are empty, if `xs` is longer than `ms`, if the first element of
333// `ms` is even, or if $E$ less than 2.
334//
335// This is equivalent to `mpn_powm` from `mpn/generic/powm.c`, GMP 6.2.1.
336pub_test! {limbs_mod_pow_odd(
337    out: &mut [Limb],
338    xs: &[Limb],
339    es: &[Limb],
340    ms: &[Limb],
341    scratch: &mut [Limb],
342) {
343    let xs_len = xs.len();
344    let es_len = es.len();
345    let ms_len = ms.len();
346    assert_ne!(xs_len, 0);
347    assert_ne!(es_len, 0);
348    if es_len == 1 {
349        assert!(es[0] > 1);
350    }
351    assert!(ms[0].odd());
352    let out = &mut out[..ms_len];
353    let width = limbs_significant_bits(es);
354    let window_size = get_window_size(width);
355    let mut small_is = [0; 2];
356    let mut is_vec;
357    let is: &mut [Limb];
358    let redc_fn: &dyn Fn(&mut [Limb], &mut [Limb], &[Limb], &[Limb]);
359    if ms_len < REDC_1_TO_REDC_N_THRESHOLD {
360        is = &mut small_is;
361        is[0] = limbs_modular_invert_limb(ms[0]);
362        is[0].wrapping_neg_assign();
363        redc_fn = &limbs_redc_limb_helper;
364    } else {
365        is_vec = vec![0; ms_len];
366        is = &mut is_vec;
367        limbs_modular_invert(is, ms, scratch);
368        redc_fn = &limbs_redc_helper;
369    }
370    let mut powers = vec![0; ms_len << (window_size - 1)];
371    let mut powers: Vec<&mut [Limb]> = powers.chunks_mut(ms_len).collect();
372    to_redc(powers[0], xs, ms);
373    // Store x ^ 2 at `out`.
374    let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(powers[0].len())];
375    limbs_square_to_out(scratch, powers[0], &mut square_scratch);
376    redc_fn(out, scratch, ms, is);
377    // Precompute odd powers of x and put them in `powers`.
378    let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(out.len())];
379    for i in 1..usize::power_of_2(window_size - 1) {
380        let (powers_lo, powers_hi) = powers.split_at_mut(i);
381        limbs_mul_same_length_to_out(scratch, powers_lo[i - 1], out, &mut mul_scratch);
382        redc_fn(powers_hi[0], scratch, ms, is);
383    }
384    let exp_bits = get_bits(es, width, window_size);
385    let mut bit_index = if width < window_size {
386        fail_on_untested_path("limbs_mod_pow_odd, width < window_size");
387        0
388    } else {
389        width - window_size
390    };
391    let trailing_zeros = TrailingZeros::trailing_zeros(Limb::exact_from(exp_bits));
392    bit_index += trailing_zeros;
393    out.copy_from_slice(powers[exp_bits >> trailing_zeros >> 1]);
394    let (mul_fn, square_fn, reduce_fn) = select_fns(ms_len);
395    'outer: while bit_index != 0 {
396        while !limbs_get_bit(es, bit_index - 1) {
397            square_fn(scratch, out);
398            reduce_fn(out, scratch, ms, is);
399            bit_index -= 1;
400            if bit_index == 0 {
401                break 'outer;
402            }
403        }
404        // The next bit of the exponent is 1. Now extract the largest block of bits <= window_size,
405        // and such that the least significant bit is 1.
406        let exp_bits = get_bits(es, bit_index, window_size);
407        let mut this_window_size = window_size;
408        if bit_index < window_size {
409            this_window_size -= window_size - bit_index;
410            bit_index = 0;
411        } else {
412            bit_index -= window_size;
413        }
414        let trailing_zeros = TrailingZeros::trailing_zeros(Limb::exact_from(exp_bits));
415        bit_index += trailing_zeros;
416        for _ in 0..this_window_size - trailing_zeros {
417            square_fn(scratch, out);
418            reduce_fn(out, scratch, ms, is);
419        }
420        mul_fn(scratch, out, powers[exp_bits >> trailing_zeros >> 1]);
421        reduce_fn(out, scratch, ms, is);
422    }
423    let (scratch_lo, scratch_hi) = scratch.split_at_mut(ms_len);
424    scratch_lo.copy_from_slice(out);
425    slice_set_zero(&mut scratch_hi[..ms_len]);
426    redc_fn(out, scratch, ms, is);
427    if limbs_cmp_same_length(out, ms) != Less {
428        limbs_sub_same_length_in_place_left(out, ms);
429    }
430}}
431
432// Interpreting a `Vec<Limb>` and two `&[Limb]` as the limbs (in ascending order) of three
433// `Natural`s, `x`, `exp`, and `m`, writes the limbs of `x ^ exp` mod `2 ^ m` to an output slice.
434// Assumes the input is already reduced mod `m`. No input may be empty or have trailing zeros, the
435// exponent must be greater than 1, and the output slice must be at least as long as `ms`.
436//
437// # Worst-case complexity
438// $T(n, m) = O(mn \log n \log\log n)$
439//
440// $M(n) = O(n \log n)$
441//
442// where $T$ is time, $M$ is additional memory, $n$ is `ms.len()`, and $m$ is `es.len()`.
443//
444// # Panics
445// Panics if the exponent has trailing zeros or is 1.
446//
447// This is equivalent to `mpz_powm` from `mpn/generic/powm.c`, GMP 6.2.1, where `b`, `e`, and `m`
448// are non-negative. Investigate changes from 6.1.2?
449pub_test! {limbs_mod_pow(out: &mut [Limb], xs: &[Limb], es: &[Limb], ms: &[Limb]) {
450    let ms_len = ms.len();
451    let es_len = es.len();
452    let xs_len = xs.len();
453    let mut ms_zero_len = slice_leading_zeros(ms);
454    let mut ms = &ms[ms_zero_len..];
455    let mut ms_nonzero_len = ms_len - ms_zero_len;
456    let mut ms_vec;
457    let mut ms_twos = 0;
458    if ms[0].even() {
459        ms_vec = vec![0; ms_nonzero_len];
460        ms_twos = TrailingZeros::trailing_zeros(ms[0]);
461        limbs_shr_to_out(&mut ms_vec, &ms[..ms_nonzero_len], ms_twos);
462        if ms_vec[ms_nonzero_len - 1] == 0 {
463            ms_nonzero_len -= 1;
464        }
465        ms = &ms_vec;
466        ms_zero_len += 1;
467    }
468    let scratch_len = if ms_zero_len != 0 {
469        // We will call both `limbs_mod_pow_odd` and `limbs_pow_low`.
470        let max_invert_len = max(ms_zero_len, ms_nonzero_len);
471        let invert_scratch_len = limbs_modular_invert_scratch_len(max_invert_len);
472        (ms_len << 1) + max(invert_scratch_len, ms_len << 1)
473    } else {
474        // We will call just `limbs_mod_pow_odd`.
475        let invert_scratch_len = limbs_modular_invert_scratch_len(ms_nonzero_len);
476        max(invert_scratch_len, ms_len << 1)
477    };
478    let mut scratch = vec![0; scratch_len];
479    limbs_mod_pow_odd(out, xs, es, &ms[..ms_nonzero_len], &mut scratch);
480    let mut xs_vec;
481    let mut xs = xs;
482    if ms_zero_len != 0 {
483        if xs_len < ms_zero_len {
484            xs_vec = vec![0; ms_zero_len];
485            xs_vec[..xs_len].copy_from_slice(xs);
486            xs = &xs_vec;
487        }
488        let mut do_pow_low = true;
489        let (scratch_lo, scratch_hi) = scratch.split_at_mut(ms_zero_len);
490        if xs[0].even() {
491            if es_len > 1 {
492                slice_set_zero(scratch_lo);
493                do_pow_low = false;
494            } else {
495                assert_eq!(es_len, 1);
496                let t = if ms_twos == 0 {
497                    limb_to_bit_count(ms_zero_len)
498                } else {
499                    limb_to_bit_count(ms_zero_len - 1) + ms_twos
500                };
501                // Count number of low zero bits in `xs`, up to 3.
502                let bits =
503                    (Limb::exact_from(0x1213) >> (xs[0].mod_power_of_2(3) << 1)).mod_power_of_2(2);
504                // Note that es[0] * bits might overflow, but that just results in a missed
505                // optimization.
506                #[cfg(feature = "32_bit_limbs")]
507                if let Ok(t) = Limb::try_from(t)
508                    && es[0].wrapping_mul(bits) >= t
509                {
510                    slice_set_zero(scratch_lo);
511                    do_pow_low = false;
512                }
513                #[cfg(not(feature = "32_bit_limbs"))]
514                if es[0].wrapping_mul(bits) >= t {
515                    slice_set_zero(scratch_lo);
516                    do_pow_low = false;
517                }
518            }
519        }
520        if do_pow_low {
521            scratch_lo.copy_from_slice(&xs[..ms_zero_len]);
522            limbs_pow_low(scratch_lo, &es[..es_len], scratch_hi);
523        }
524        let mut ms_vec;
525        if ms_nonzero_len < ms_zero_len {
526            ms_vec = vec![0; ms_zero_len];
527            ms_vec[..ms_nonzero_len].copy_from_slice(&ms[..ms_nonzero_len]);
528            ms = &ms_vec;
529        }
530        let (scratch_0_1, scratch_2) = scratch.split_at_mut(ms_len << 1);
531        let (scratch_0, scratch_1) = scratch_0_1.split_at_mut(ms_len);
532        let scratch_0 = &mut scratch_0[..ms_zero_len];
533        limbs_modular_invert(scratch_1, &ms[..ms_zero_len], scratch_2);
534        limbs_sub_greater_in_place_left(scratch_0, &out[..min(ms_zero_len, ms_nonzero_len)]);
535        limbs_mul_low_same_length(scratch_2, &scratch_1[..ms_zero_len], scratch_0);
536        if ms_twos != 0 {
537            scratch_2[ms_zero_len - 1].mod_power_of_2_assign(ms_twos);
538        }
539        let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(ms_zero_len, ms_nonzero_len)];
540        limbs_mul_to_out(
541            scratch_0_1,
542            &scratch_2[..ms_zero_len],
543            &ms[..ms_nonzero_len],
544            &mut mul_scratch,
545        );
546        limbs_add_to_out_aliased(out, ms_nonzero_len, &scratch_0_1[..ms_len]);
547    }
548}}
549
550impl ModPow<Self, Self> for Natural {
551    type Output = Self;
552
553    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be
554    /// already reduced modulo $m$. All three [`Natural`]s are taken by value.
555    ///
556    /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$.
557    ///
558    /// # Worst-case complexity
559    /// $T(n, m) = O(mn \log n \log\log n)$
560    ///
561    /// $M(n) = O(n \log n)$
562    ///
563    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
564    /// `exp.significant_bits()`.
565    ///
566    /// # Panics
567    /// Panics if `self` is greater than or equal to `m`.
568    ///
569    /// # Examples
570    /// ```
571    /// use malachite_base::num::arithmetic::traits::ModPow;
572    /// use malachite_nz::natural::Natural;
573    ///
574    /// assert_eq!(
575    ///     Natural::from(4u32).mod_pow(Natural::from(13u32), Natural::from(497u32)),
576    ///     445
577    /// );
578    /// assert_eq!(
579    ///     Natural::from(10u32).mod_pow(Natural::from(1000u32), Natural::from(30u32)),
580    ///     10
581    /// );
582    /// ```
583    #[inline]
584    fn mod_pow(mut self, exp: Self, m: Self) -> Self {
585        self.mod_pow_assign(exp, m);
586        self
587    }
588}
589
590impl<'a> ModPow<Self, &'a Self> for Natural {
591    type Output = Self;
592
593    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be
594    /// already reduced modulo $m$. The first two [`Natural`]s are taken by value and the third by
595    /// reference.
596    ///
597    /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$.
598    ///
599    /// # Worst-case complexity
600    /// $T(n, m) = O(mn \log n \log\log n)$
601    ///
602    /// $M(n) = O(n \log n)$
603    ///
604    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
605    /// `exp.significant_bits()`.
606    ///
607    /// # Panics
608    /// Panics if `self` is greater than or equal to `m`.
609    ///
610    /// # Examples
611    /// ```
612    /// use malachite_base::num::arithmetic::traits::ModPow;
613    /// use malachite_nz::natural::Natural;
614    ///
615    /// assert_eq!(
616    ///     Natural::from(4u32).mod_pow(Natural::from(13u32), &Natural::from(497u32)),
617    ///     445
618    /// );
619    /// assert_eq!(
620    ///     Natural::from(10u32).mod_pow(Natural::from(1000u32), &Natural::from(30u32)),
621    ///     10
622    /// );
623    /// ```
624    #[inline]
625    fn mod_pow(mut self, exp: Self, m: &'a Self) -> Self {
626        self.mod_pow_assign(exp, m);
627        self
628    }
629}
630
631impl<'a> ModPow<&'a Self, Self> for Natural {
632    type Output = Self;
633
634    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be
635    /// already reduced modulo $m$. The first and third [`Natural`]s are taken by value and the
636    /// second by reference.
637    ///
638    /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$.
639    ///
640    /// # Worst-case complexity
641    /// $T(n, m) = O(mn \log n \log\log n)$
642    ///
643    /// $M(n) = O(n \log n)$
644    ///
645    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
646    /// `exp.significant_bits()`.
647    ///
648    /// # Panics
649    /// Panics if `self` is greater than or equal to `m`.
650    ///
651    /// # Examples
652    /// ```
653    /// use malachite_base::num::arithmetic::traits::ModPow;
654    /// use malachite_nz::natural::Natural;
655    ///
656    /// assert_eq!(
657    ///     Natural::from(4u32).mod_pow(&Natural::from(13u32), Natural::from(497u32)),
658    ///     445
659    /// );
660    /// assert_eq!(
661    ///     Natural::from(10u32).mod_pow(&Natural::from(1000u32), Natural::from(30u32)),
662    ///     10
663    /// );
664    /// ```
665    #[inline]
666    fn mod_pow(mut self, exp: &'a Self, m: Self) -> Self {
667        self.mod_pow_assign(exp, m);
668        self
669    }
670}
671
672impl<'a, 'b> ModPow<&'a Self, &'b Self> for Natural {
673    type Output = Self;
674
675    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be
676    /// already reduced modulo $m$. The first [`Natural`] is taken by value and the second and third
677    /// by reference.
678    ///
679    /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$.
680    ///
681    /// # Worst-case complexity
682    /// $T(n, m) = O(mn \log n \log\log n)$
683    ///
684    /// $M(n) = O(n \log n)$
685    ///
686    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
687    /// `exp.significant_bits()`.
688    ///
689    /// # Panics
690    /// Panics if `self` is greater than or equal to `m`.
691    ///
692    /// # Examples
693    /// ```
694    /// use malachite_base::num::arithmetic::traits::ModPow;
695    /// use malachite_nz::natural::Natural;
696    ///
697    /// assert_eq!(
698    ///     Natural::from(4u32).mod_pow(&Natural::from(13u32), &Natural::from(497u32)),
699    ///     445
700    /// );
701    /// assert_eq!(
702    ///     Natural::from(10u32).mod_pow(&Natural::from(1000u32), &Natural::from(30u32)),
703    ///     10
704    /// );
705    /// ```
706    #[inline]
707    fn mod_pow(mut self, exp: &'a Self, m: &'b Self) -> Self {
708        self.mod_pow_assign(exp, m);
709        self
710    }
711}
712
713impl ModPow<Natural, Natural> for &Natural {
714    type Output = Natural;
715
716    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`]$m$. The base must be
717    /// already reduced modulo $m$. The first [`Natural`] is taken by reference and the second and
718    /// third by value.
719    ///
720    /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$.
721    ///
722    /// # Worst-case complexity
723    /// $T(n, m) = O(mn \log n \log\log n)$
724    ///
725    /// $M(n) = O(n \log n)$
726    ///
727    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
728    /// `exp.significant_bits()`.
729    ///
730    /// # Panics
731    /// Panics if `self` is greater than or equal to `m`.
732    ///
733    /// # Examples
734    /// ```
735    /// use malachite_base::num::arithmetic::traits::ModPow;
736    /// use malachite_nz::natural::Natural;
737    ///
738    /// assert_eq!(
739    ///     (&Natural::from(4u32)).mod_pow(Natural::from(13u32), Natural::from(497u32)),
740    ///     445
741    /// );
742    /// assert_eq!(
743    ///     (&Natural::from(10u32)).mod_pow(Natural::from(1000u32), Natural::from(30u32)),
744    ///     10
745    /// );
746    /// ```
747    #[allow(clippy::match_same_arms)] // matches are order-dependent
748    fn mod_pow(self, mut exp: Natural, mut m: Natural) -> Natural {
749        assert!(*self < m, "self must be reduced mod m, but {self} >= {m}");
750        match (self, &exp, &m) {
751            (_, _, &Natural::ONE) => Natural::ZERO,
752            (_, &Natural::ZERO, _) => Natural::ONE,
753            (&Natural::ZERO, _, _) => Natural::ZERO,
754            (x, &Natural::ONE, _) => x.clone(),
755            (&Natural::ONE, _, _) => Natural::ONE,
756            (Natural(Small(x)), Natural(Small(e)), Natural(Small(m)))
757                if u64::convertible_from(*e) =>
758            {
759                Natural::from(x.mod_pow(u64::wrapping_from(*e), *m))
760            }
761            _ => {
762                let ms = m.promote_in_place();
763                let mut out = vec![0; ms.len()];
764                limbs_mod_pow(&mut out, self.as_limbs_asc(), exp.promote_in_place(), ms);
765                Natural::from_owned_limbs_asc(out)
766            }
767        }
768    }
769}
770
771impl ModPow<Natural, &Natural> for &Natural {
772    type Output = Natural;
773
774    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be
775    /// already reduced modulo $m$. The first and third [`Natural`]s are taken by reference and the
776    /// second by value.
777    ///
778    /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$.
779    ///
780    /// # Worst-case complexity
781    /// $T(n, m) = O(mn \log n \log\log n)$
782    ///
783    /// $M(n) = O(n \log n)$
784    ///
785    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
786    /// `exp.significant_bits()`.
787    ///
788    /// # Panics
789    /// Panics if `self` is greater than or equal to `m`.
790    ///
791    /// # Examples
792    /// ```
793    /// use malachite_base::num::arithmetic::traits::ModPow;
794    /// use malachite_nz::natural::Natural;
795    ///
796    /// assert_eq!(
797    ///     (&Natural::from(4u32)).mod_pow(Natural::from(13u32), &Natural::from(497u32)),
798    ///     445
799    /// );
800    /// assert_eq!(
801    ///     (&Natural::from(10u32)).mod_pow(Natural::from(1000u32), &Natural::from(30u32)),
802    ///     10
803    /// );
804    /// ```
805    #[allow(clippy::match_same_arms)] // matches are order-dependent
806    fn mod_pow(self, mut exp: Natural, m: &Natural) -> Natural {
807        assert!(self < m, "self must be reduced mod m, but {self} >= {m}");
808        match (self, &exp, m) {
809            (_, _, &Natural::ONE) => Natural::ZERO,
810            (_, &Natural::ZERO, _) => Natural::ONE,
811            (&Natural::ZERO, _, _) => Natural::ZERO,
812            (x, &Natural::ONE, _) => x.clone(),
813            (&Natural::ONE, _, _) => Natural::ONE,
814            (Natural(Small(x)), Natural(Small(e)), Natural(Small(m)))
815                if u64::convertible_from(*e) =>
816            {
817                Natural::from(x.mod_pow(u64::wrapping_from(*e), *m))
818            }
819            _ => {
820                let ms = m.as_limbs_asc();
821                let mut out = vec![0; ms.len()];
822                limbs_mod_pow(&mut out, self.as_limbs_asc(), exp.promote_in_place(), ms);
823                Natural::from_owned_limbs_asc(out)
824            }
825        }
826    }
827}
828
829impl ModPow<&Natural, Natural> for &Natural {
830    type Output = Natural;
831
832    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be
833    /// already reduced modulo $m$. The first two [`Natural`]s are taken by reference and the third
834    /// by value.
835    ///
836    /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$.
837    ///
838    /// # Worst-case complexity
839    /// $T(n, m) = O(mn \log n \log\log n)$
840    ///
841    /// $M(n) = O(n \log n)$
842    ///
843    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
844    /// `exp.significant_bits()`.
845    ///
846    /// # Panics
847    /// Panics if `self` is greater than or equal to `m`.
848    ///
849    /// # Examples
850    /// ```
851    /// use malachite_base::num::arithmetic::traits::ModPow;
852    /// use malachite_nz::natural::Natural;
853    ///
854    /// assert_eq!(
855    ///     (&Natural::from(4u32)).mod_pow(&Natural::from(13u32), Natural::from(497u32)),
856    ///     445
857    /// );
858    /// assert_eq!(
859    ///     (&Natural::from(10u32)).mod_pow(&Natural::from(1000u32), Natural::from(30u32)),
860    ///     10
861    /// );
862    /// ```
863    #[allow(clippy::match_same_arms)] // matches are order-dependent
864    fn mod_pow(self, exp: &Natural, mut m: Natural) -> Natural {
865        assert!(*self < m, "self must be reduced mod m, but {self} >= {m}");
866        match (self, exp, &m) {
867            (_, _, &Natural::ONE) => Natural::ZERO,
868            (_, &Natural::ZERO, _) => Natural::ONE,
869            (&Natural::ZERO, _, _) => Natural::ZERO,
870            (x, &Natural::ONE, _) => x.clone(),
871            (&Natural::ONE, _, _) => Natural::ONE,
872            (Natural(Small(x)), Natural(Small(e)), Natural(Small(m)))
873                if u64::convertible_from(*e) =>
874            {
875                Natural::from(x.mod_pow(u64::wrapping_from(*e), *m))
876            }
877            _ => {
878                let ms = m.promote_in_place();
879                let mut out = vec![0; ms.len()];
880                limbs_mod_pow(&mut out, self.as_limbs_asc(), exp.as_limbs_asc(), ms);
881                Natural::from_owned_limbs_asc(out)
882            }
883        }
884    }
885}
886
887impl ModPow<&Natural, &Natural> for &Natural {
888    type Output = Natural;
889
890    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be
891    /// already reduced modulo $m$. All three [`Natural`]s are taken by reference.
892    ///
893    /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$.
894    ///
895    /// # Worst-case complexity
896    /// $T(n, m) = O(mn \log n \log\log n)$
897    ///
898    /// $M(n) = O(n \log n)$
899    ///
900    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
901    /// `exp.significant_bits()`.
902    ///
903    /// # Panics
904    /// Panics if `self` is greater than or equal to `m`.
905    ///
906    /// # Examples
907    /// ```
908    /// use malachite_base::num::arithmetic::traits::ModPow;
909    /// use malachite_nz::natural::Natural;
910    ///
911    /// assert_eq!(
912    ///     (&Natural::from(4u32)).mod_pow(&Natural::from(13u32), &Natural::from(497u32)),
913    ///     445
914    /// );
915    /// assert_eq!(
916    ///     (&Natural::from(10u32)).mod_pow(&Natural::from(1000u32), &Natural::from(30u32)),
917    ///     10
918    /// );
919    /// ```
920    #[allow(clippy::match_same_arms)] // matches are order-dependent
921    fn mod_pow(self, exp: &Natural, m: &Natural) -> Natural {
922        assert!(self < m, "self must be reduced mod m, but {self} >= {m}");
923        match (self, exp, m) {
924            (_, _, &Natural::ONE) => Natural::ZERO,
925            (_, &Natural::ZERO, _) => Natural::ONE,
926            (&Natural::ZERO, _, _) => Natural::ZERO,
927            (x, &Natural::ONE, _) => x.clone(),
928            (&Natural::ONE, _, _) => Natural::ONE,
929            (Natural(Small(x)), Natural(Small(e)), Natural(Small(m)))
930                if u64::convertible_from(*e) =>
931            {
932                Natural::from(x.mod_pow(u64::wrapping_from(*e), *m))
933            }
934            _ => {
935                let ms = m.as_limbs_asc();
936                let mut out = vec![0; ms.len()];
937                limbs_mod_pow(&mut out, self.as_limbs_asc(), exp.as_limbs_asc(), ms);
938                Natural::from_owned_limbs_asc(out)
939            }
940        }
941    }
942}
943
944impl ModPowAssign<Self, Self> for Natural {
945    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$, in place. The
946    /// base must be already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken
947    /// by value.
948    ///
949    /// $x \gets y$, where $x, y < m$ and $x^n \equiv y \mod m$.
950    ///
951    /// # Worst-case complexity
952    /// $T(n, m) = O(mn \log n \log\log n)$
953    ///
954    /// $M(n) = O(n \log n)$
955    ///
956    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
957    /// `exp.significant_bits()`.
958    ///
959    /// # Panics
960    /// Panics if `self` is greater than or equal to `m`.
961    ///
962    /// # Examples
963    /// ```
964    /// use malachite_base::num::arithmetic::traits::ModPowAssign;
965    /// use malachite_nz::natural::Natural;
966    ///
967    /// let mut x = Natural::from(4u32);
968    /// x.mod_pow_assign(Natural::from(13u32), Natural::from(497u32));
969    /// assert_eq!(x, 445);
970    ///
971    /// let mut x = Natural::from(10u32);
972    /// x.mod_pow_assign(Natural::from(1000u32), Natural::from(30u32));
973    /// assert_eq!(x, 10);
974    /// ```
975    #[allow(clippy::match_same_arms)] // matches are order-dependent
976    fn mod_pow_assign(&mut self, mut exp: Self, mut m: Self) {
977        assert!(*self < m, "self must be reduced mod m, but {self} >= {m}");
978        match (&mut *self, &exp, &m) {
979            (_, _, &Self::ONE) => *self = Self::ZERO,
980            (_, &Self::ZERO, _) => *self = Self::ONE,
981            (&mut (Self::ZERO | Self::ONE), _, _) | (_, &Self::ONE, _) => {}
982            (Self(Small(x)), Self(Small(e)), Self(Small(m))) if u64::convertible_from(*e) => {
983                x.mod_pow_assign(u64::wrapping_from(*e), *m);
984            }
985            _ => {
986                let ms = m.promote_in_place();
987                let mut out = vec![0; ms.len()];
988                limbs_mod_pow(
989                    &mut out,
990                    self.promote_in_place(),
991                    exp.promote_in_place(),
992                    ms,
993                );
994                *self = Self::from_owned_limbs_asc(out);
995            }
996        }
997    }
998}
999
1000impl<'a> ModPowAssign<Self, &'a Self> for Natural {
1001    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$, in place. The
1002    /// base must be already reduced modulo $m$. The first [`Natural`] on the right-hand side is
1003    /// taken by value and the second by reference.
1004    ///
1005    /// $x \gets y$, where $x, y < m$ and $x^n \equiv y \mod m$.
1006    ///
1007    /// # Worst-case complexity
1008    /// $T(n, m) = O(mn \log n \log\log n)$
1009    ///
1010    /// $M(n) = O(n \log n)$
1011    ///
1012    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
1013    /// `exp.significant_bits()`.
1014    ///
1015    /// # Panics
1016    /// Panics if `self` is greater than or equal to `m`.
1017    ///
1018    /// # Examples
1019    /// ```
1020    /// use malachite_base::num::arithmetic::traits::ModPowAssign;
1021    /// use malachite_nz::natural::Natural;
1022    ///
1023    /// let mut x = Natural::from(4u32);
1024    /// x.mod_pow_assign(Natural::from(13u32), &Natural::from(497u32));
1025    /// assert_eq!(x, 445);
1026    ///
1027    /// let mut x = Natural::from(10u32);
1028    /// x.mod_pow_assign(Natural::from(1000u32), &Natural::from(30u32));
1029    /// assert_eq!(x, 10);
1030    /// ```
1031    #[allow(clippy::match_same_arms)] // matches are order-dependent
1032    fn mod_pow_assign(&mut self, mut exp: Self, m: &'a Self) {
1033        assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}");
1034        match (&mut *self, &exp, m) {
1035            (_, _, &Self::ONE) => *self = Self::ZERO,
1036            (_, &Self::ZERO, _) => *self = Self::ONE,
1037            (&mut (Self::ZERO | Self::ONE), _, _) | (_, &Self::ONE, _) => {}
1038            (Self(Small(x)), Self(Small(e)), Self(Small(m))) if u64::convertible_from(*e) => {
1039                x.mod_pow_assign(u64::wrapping_from(*e), *m);
1040            }
1041            _ => {
1042                let ms = m.as_limbs_asc();
1043                let mut out = vec![0; ms.len()];
1044                limbs_mod_pow(
1045                    &mut out,
1046                    self.promote_in_place(),
1047                    exp.promote_in_place(),
1048                    ms,
1049                );
1050                *self = Self::from_owned_limbs_asc(out);
1051            }
1052        }
1053    }
1054}
1055
1056impl<'a> ModPowAssign<&'a Self, Self> for Natural {
1057    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$, in place. The
1058    /// base must be already reduced modulo $m$. The first [`Natural`] on the right-hand side is
1059    /// taken by reference and the second by value.
1060    ///
1061    /// $x \gets y$, where $x, y < m$ and $x^n \equiv y \mod m$.
1062    ///
1063    /// # Worst-case complexity
1064    /// $T(n, m) = O(mn \log n \log\log n)$
1065    ///
1066    /// $M(n) = O(n \log n)$
1067    ///
1068    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
1069    /// `exp.significant_bits()`.
1070    ///
1071    /// # Panics
1072    /// Panics if `self` is greater than or equal to `m`.
1073    ///
1074    /// # Examples
1075    /// ```
1076    /// use malachite_base::num::arithmetic::traits::ModPowAssign;
1077    /// use malachite_nz::natural::Natural;
1078    ///
1079    /// let mut x = Natural::from(4u32);
1080    /// x.mod_pow_assign(&Natural::from(13u32), Natural::from(497u32));
1081    /// assert_eq!(x, 445);
1082    ///
1083    /// let mut x = Natural::from(10u32);
1084    /// x.mod_pow_assign(&Natural::from(1000u32), Natural::from(30u32));
1085    /// assert_eq!(x, 10);
1086    /// ```
1087    #[allow(clippy::match_same_arms)] // matches are order-dependent
1088    fn mod_pow_assign(&mut self, exp: &'a Self, mut m: Self) {
1089        assert!(*self < m, "self must be reduced mod m, but {self} >= {m}");
1090        match (&mut *self, exp, &m) {
1091            (_, _, &Self::ONE) => *self = Self::ZERO,
1092            (_, &Self::ZERO, _) => *self = Self::ONE,
1093            (&mut (Self::ZERO | Self::ONE), _, _) | (_, &Self::ONE, _) => {}
1094            (Self(Small(x)), Self(Small(e)), Self(Small(m))) if u64::convertible_from(*e) => {
1095                x.mod_pow_assign(u64::wrapping_from(*e), *m);
1096            }
1097            _ => {
1098                let ms = m.promote_in_place();
1099                let mut out = vec![0; ms.len()];
1100                limbs_mod_pow(&mut out, self.promote_in_place(), exp.as_limbs_asc(), ms);
1101                *self = Self::from_owned_limbs_asc(out);
1102            }
1103        }
1104    }
1105}
1106
1107impl<'a, 'b> ModPowAssign<&'a Self, &'b Self> for Natural {
1108    /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$, in place. The
1109    /// base must be already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken
1110    /// by reference.
1111    ///
1112    /// $x \gets y$, where $x, y < m$ and $x^n \equiv y \mod m$.
1113    ///
1114    /// # Worst-case complexity
1115    /// $T(n, m) = O(mn \log n \log\log n)$
1116    ///
1117    /// $M(n) = O(n \log n)$
1118    ///
1119    /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is
1120    /// `exp.significant_bits()`.
1121    ///
1122    /// # Panics
1123    /// Panics if `self` is greater than or equal to `m`.
1124    ///
1125    /// # Examples
1126    /// ```
1127    /// use malachite_base::num::arithmetic::traits::ModPowAssign;
1128    /// use malachite_nz::natural::Natural;
1129    ///
1130    /// let mut x = Natural::from(4u32);
1131    /// x.mod_pow_assign(&Natural::from(13u32), &Natural::from(497u32));
1132    /// assert_eq!(x, 445);
1133    ///
1134    /// let mut x = Natural::from(10u32);
1135    /// x.mod_pow_assign(&Natural::from(1000u32), &Natural::from(30u32));
1136    /// assert_eq!(x, 10);
1137    /// ```
1138    #[allow(clippy::match_same_arms)] // matches are order-dependent
1139    fn mod_pow_assign(&mut self, exp: &'a Self, m: &'b Self) {
1140        assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}");
1141        match (&mut *self, exp, m) {
1142            (_, _, &Self::ONE) => *self = Self::ZERO,
1143            (_, &Self::ZERO, _) => *self = Self::ONE,
1144            (&mut (Self::ZERO | Self::ONE), _, _) | (_, &Self::ONE, _) => {}
1145            (Self(Small(x)), Self(Small(e)), Self(Small(m))) if u64::convertible_from(*e) => {
1146                x.mod_pow_assign(u64::wrapping_from(*e), *m);
1147            }
1148            _ => {
1149                let ms = m.as_limbs_asc();
1150                let mut out = vec![0; ms.len()];
1151                limbs_mod_pow(&mut out, self.promote_in_place(), exp.as_limbs_asc(), ms);
1152                *self = Self::from_owned_limbs_asc(out);
1153            }
1154        }
1155    }
1156}