Skip to main content

malachite_nz/natural/arithmetic/
mod_mul.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the FLINT Library.
4//
5//      Copyright © 2019 Daniel Schultz
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::Natural;
15use crate::natural::arithmetic::div_mod::limbs_div_mod_by_two_limb_normalized;
16use crate::platform::{DoubleLimb, Limb};
17use malachite_base::num::arithmetic::traits::{
18    ModMul, ModMulAssign, ModMulPrecomputed, ModMulPrecomputedAssign, ModPowerOf2Mul,
19    ModPowerOf2MulAssign, PowerOf2, XMulYToZZ, XXXAddYYYToZZZ, XXXSubYYYToZZZ, XXXXAddYYYYToZZZZ,
20};
21use malachite_base::num::basic::integers::PrimitiveInt;
22use malachite_base::num::basic::traits::{One, Zero};
23use malachite_base::num::conversion::traits::{JoinHalves, SplitInHalf};
24use malachite_base::num::logic::traits::LeadingZeros;
25
26// m_1 cannot be zero, and we cannot have m_1 == 1 and m_0 == 0.
27//
28// # Worst-case complexity
29// Constant time and additional memory.
30//
31// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1.
32pub_test! {limbs_precompute_mod_mul_two_limbs(m_1: Limb, m_0: Limb) -> (Limb, Limb, Limb) {
33    let xs = &mut [0; 5];
34    let out = &mut [0; 3];
35    let bits = LeadingZeros::leading_zeros(m_1);
36    if bits == 0 {
37        xs[4] = 1;
38        assert!(!limbs_div_mod_by_two_limb_normalized(out, xs, &[m_0, m_1]));
39    } else {
40        xs[4] = Limb::power_of_2(bits);
41        assert!(!limbs_div_mod_by_two_limb_normalized(
42            out,
43            xs,
44            &[m_0 << bits, (m_1 << bits) | (m_0 >> (Limb::WIDTH - bits))]
45        ));
46    }
47    assert_ne!(out[2], 0);
48    (out[2], out[1], out[0])
49}}
50
51// Standard Barrett reduction: (set r = `Limb::WIDTH`)
52//
53// We have m fits into 2 words and 2 ^ r < m < 2 ^ (2 * r). Therefore 2 ^ (3 * r) > 2 ^ (4 * r) / m
54// > 2 ^ (2 * r) and the precomputed number inv = floor(2 ^ (4 * r) / m) fits into 3 words. The
55// inputs x and y are < m and therefore fit into 2 words.
56//
57// The computation of a = x*y mod m is:
58// ```
59// w = x * y               x < m ^ 2 and therefore fits into 4 words
60// z = (w >> r) * inv      z <= m * 2 ^ (3 * r) and therefore fits into 5 words
61// q = (z >> (3 * r)) * n  q fits into 4 words
62// w = w - q               w fits into 3 words after the subtraction
63// ```
64//
65// at this point the canonical reduction in the range [0, m) is one of a = w, a = w - n, or a = w -
66// 2 * m
67//
68// # Worst-case complexity
69// Constant time and additional memory.
70//
71// This is equivalent to `_fmpz_mod_mul2` from `fmpz_mod/mul.c`, FLINT 2.7.1.
72pub_test! {limbs_mod_mul_two_limbs(
73    x_1: Limb,
74    x_0: Limb,
75    y_1: Limb,
76    y_0: Limb,
77    m_1: Limb,
78    m_0: Limb,
79    inv_2: Limb,
80    inv_1: Limb,
81    inv_0: Limb,
82) -> (Limb, Limb) {
83    // w[3:0] = x[1:0] * y[1:0]
84    let (w_3, w_2) = Limb::x_mul_y_to_zz(x_1, y_1);
85    let (w_1, w_0) = Limb::x_mul_y_to_zz(x_0, y_0);
86    let (t, carry) = (DoubleLimb::from(x_1) * DoubleLimb::from(y_0))
87        .overflowing_add(DoubleLimb::from(x_0) * DoubleLimb::from(y_1));
88    let (t_2, t_1) = t.split_in_half();
89    let (w_3, w_2, w_1) = Limb::xxx_add_yyy_to_zzz(w_3, w_2, w_1, Limb::from(carry), t_2, t_1);
90
91    // z[5:0] = w[3:1] * ninv[2:0], z[5] should end up zero
92    let (z_3, z_2) = Limb::x_mul_y_to_zz(w_2, inv_1);
93    let (t, carry) = (DoubleLimb::from(w_1) * DoubleLimb::from(inv_2))
94        .overflowing_add(DoubleLimb::from(w_3) * DoubleLimb::from(inv_0));
95    let (t_3, t_2) = t.split_in_half();
96    let (u_2, u_1) = Limb::x_mul_y_to_zz(w_2, inv_0);
97    let (u_4, u_3) = Limb::x_mul_y_to_zz(w_3, inv_1);
98    let (z_4, z_3, z_2) = Limb::xxx_add_yyy_to_zzz(
99        w_3.wrapping_mul(inv_2),
100        z_3,
101        z_2,
102        Limb::from(carry),
103        t_3,
104        t_2,
105    );
106    let (v_2, v_1) = Limb::x_mul_y_to_zz(w_1, inv_1);
107    let (v_4, v_3) = Limb::x_mul_y_to_zz(w_2, inv_2);
108    let (z_4, z_3, z_2, z_1) = Limb::xxxx_add_yyyy_to_zzzz(
109        z_4,
110        z_3,
111        z_2,
112        (DoubleLimb::from(w_1) * DoubleLimb::from(inv_0)).upper_half(),
113        u_4,
114        u_3,
115        u_2,
116        u_1,
117    );
118    let (z_4, z_3, _, _) = Limb::xxxx_add_yyyy_to_zzzz(z_4, z_3, z_2, z_1, v_4, v_3, v_2, v_1);
119
120    // - q[3:0] = z[4:3] * n[1:0], q[3] is not needed
121    // - x[3:0] -= q[3:0], w[3] should end up zero
122    let (q_1, q_0) = Limb::x_mul_y_to_zz(z_3, m_0);
123    let (w_2, w_1) = DoubleLimb::join_halves(w_2, w_1)
124        .wrapping_sub(DoubleLimb::from(z_4) * DoubleLimb::from(m_0))
125        .wrapping_sub(DoubleLimb::from(z_3) * DoubleLimb::from(m_1))
126        .split_in_half();
127    let (w_2, w_1, w_0) = Limb::xxx_sub_yyy_to_zzz(w_2, w_1, w_0, z_4.wrapping_mul(m_1), q_1, q_0);
128
129    // at most two subtractions of n, use q as temp space
130    let (q_2, q_1, q_0) = Limb::xxx_sub_yyy_to_zzz(w_2, w_1, w_0, 0, m_1, m_0);
131    if q_2.get_highest_bit() {
132        (w_1, w_0)
133    } else {
134        let (w_2, w_1, w_0) = Limb::xxx_sub_yyy_to_zzz(q_2, q_1, q_0, 0, m_1, m_0);
135        if w_2.get_highest_bit() {
136            (q_1, q_0)
137        } else {
138            (w_1, w_0)
139        }
140    }
141}}
142
143#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
144#[doc(hidden)]
145pub enum ModMulData {
146    OneLimb(Limb),
147    MinTwoLimbs,
148    TwoLimbs(Limb, Limb, Limb),
149    MoreThanTwoLimbs,
150}
151
152fn precompute_mod_mul_data_helper(m: &Natural) -> ModMulData {
153    match *m {
154        Natural::ZERO => panic!("division by zero"),
155        Natural(Small(ref x)) => ModMulData::OneLimb(Limb::precompute_mod_mul_data(x)),
156        Natural(Large(ref xs)) => match xs[..] {
157            [0, 1] => ModMulData::MinTwoLimbs,
158            [m_0, m_1] => {
159                let (inv_2, inv_1, inv_0) = limbs_precompute_mod_mul_two_limbs(m_1, m_0);
160                ModMulData::TwoLimbs(inv_2, inv_1, inv_0)
161            }
162            _ => ModMulData::MoreThanTwoLimbs,
163        },
164    }
165}
166
167impl Natural {
168    fn mod_mul_precomputed_two_limbs(
169        &self,
170        y: &Self,
171        m: &Self,
172        inv_2: Limb,
173        inv_1: Limb,
174        inv_0: Limb,
175    ) -> Self {
176        let (r_1, r_0) = match (self, y, m) {
177            (&Self(Small(x)), &Self(Small(y)), &Self(Large(ref ms))) => {
178                limbs_mod_mul_two_limbs(0, x, 0, y, ms[1], ms[0], inv_2, inv_1, inv_0)
179            }
180            (&Self(Large(ref xs)), &Self(Small(y)), &Self(Large(ref ms)))
181            | (&Self(Small(y)), &Self(Large(ref xs)), &Self(Large(ref ms))) => {
182                limbs_mod_mul_two_limbs(xs[1], xs[0], 0, y, ms[1], ms[0], inv_2, inv_1, inv_0)
183            }
184            (&Self(Large(ref xs)), &Self(Large(ref ys)), &Self(Large(ref ms))) => {
185                limbs_mod_mul_two_limbs(
186                    xs[1], xs[0], ys[1], ys[0], ms[1], ms[0], inv_2, inv_1, inv_0,
187                )
188            }
189            _ => unreachable!(),
190        };
191        Self::from_owned_limbs_asc(vec![r_0, r_1])
192    }
193
194    fn mod_mul_precomputed_two_limbs_assign(
195        &mut self,
196        y: &Self,
197        m: &Self,
198        inv_2: Limb,
199        inv_1: Limb,
200        inv_0: Limb,
201    ) {
202        match (&mut *self, y, m) {
203            (&mut Self(Small(x)), &Self(Small(y)), &Self(Large(ref ms))) => {
204                let (r_1, r_0) =
205                    limbs_mod_mul_two_limbs(0, x, 0, y, ms[1], ms[0], inv_2, inv_1, inv_0);
206                *self = Self::from_owned_limbs_asc(vec![r_0, r_1]);
207            }
208            (&mut Self(Small(x)), &Self(Large(ref ys)), &Self(Large(ref ms))) => {
209                let (r_1, r_0) =
210                    limbs_mod_mul_two_limbs(0, x, ys[1], ys[0], ms[1], ms[0], inv_2, inv_1, inv_0);
211                *self = Self::from_owned_limbs_asc(vec![r_0, r_1]);
212            }
213            (&mut Self(Large(ref mut xs)), &Self(Small(y)), &Self(Large(ref ms))) => {
214                let (r_1, r_0) =
215                    limbs_mod_mul_two_limbs(xs[1], xs[0], 0, y, ms[1], ms[0], inv_2, inv_1, inv_0);
216                *xs = vec![r_0, r_1];
217                self.trim();
218            }
219            (&mut Self(Large(ref mut xs)), &Self(Large(ref ys)), &Self(Large(ref ms))) => {
220                let (r_1, r_0) = limbs_mod_mul_two_limbs(
221                    xs[1], xs[0], ys[1], ys[0], ms[1], ms[0], inv_2, inv_1, inv_0,
222                );
223                *xs = vec![r_0, r_1];
224                self.trim();
225            }
226            _ => unreachable!(),
227        }
228    }
229}
230
231impl ModMulPrecomputed<Self, Self> for Natural {
232    type Output = Self;
233    type Data = ModMulData;
234
235    /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and
236    /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign).
237    ///
238    /// # Worst-case complexity
239    /// Constant time and additional memory.
240    ///
241    /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1.
242    #[inline]
243    fn precompute_mod_mul_data(m: &Self) -> ModMulData {
244        precompute_mod_mul_data_helper(m)
245    }
246
247    /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already
248    /// reduced modulo $m$. All three [`Natural`]s are taken by value.
249    ///
250    /// Some precomputed data is provided; this speeds up computations involving several modular
251    /// multiplications with the same modulus. The precomputed data should be obtained using
252    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
253    ///
254    /// # Worst-case complexity
255    /// $T(n) = O(n \log n \log\log n)$
256    ///
257    /// $M(n) = O(n \log n)$
258    ///
259    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
260    ///
261    /// # Panics
262    /// Panics if `self` or `other` are greater than or equal to `m`.
263    ///
264    /// # Examples
265    /// ```
266    /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed;
267    /// use malachite_nz::natural::Natural;
268    ///
269    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
270    /// assert_eq!(
271    ///     Natural::from(6u8).mod_mul_precomputed(
272    ///         Natural::from(7u32),
273    ///         Natural::from(10u32),
274    ///         &data
275    ///     ),
276    ///     2
277    /// );
278    /// assert_eq!(
279    ///     Natural::from(9u8).mod_mul_precomputed(
280    ///         Natural::from(9u32),
281    ///         Natural::from(10u32),
282    ///         &data
283    ///     ),
284    ///     1
285    /// );
286    /// assert_eq!(
287    ///     Natural::from(4u8).mod_mul_precomputed(
288    ///         Natural::from(7u32),
289    ///         Natural::from(10u32),
290    ///         &data
291    ///     ),
292    ///     8
293    /// );
294    /// ```
295    ///
296    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`,
297    /// and `m` are taken by value.
298    fn mod_mul_precomputed(mut self, other: Self, m: Self, data: &ModMulData) -> Self {
299        self.mod_mul_precomputed_assign(other, m, data);
300        self
301    }
302}
303
304impl<'a> ModMulPrecomputed<Self, &'a Self> for Natural {
305    type Output = Self;
306    type Data = ModMulData;
307
308    /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and
309    /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign).
310    ///
311    /// # Worst-case complexity
312    /// Constant time and additional memory.
313    ///
314    /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1.
315    #[inline]
316    fn precompute_mod_mul_data(m: &&Self) -> ModMulData {
317        precompute_mod_mul_data_helper(m)
318    }
319
320    /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already
321    /// reduced modulo $m$. The first two [`Natural`]s are taken by value and the third by
322    /// reference.
323    ///
324    /// Some precomputed data is provided; this speeds up computations involving several modular
325    /// multiplications with the same modulus. The precomputed data should be obtained using
326    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
327    ///
328    /// # Worst-case complexity
329    /// $T(n) = O(n \log n \log\log n)$
330    ///
331    /// $M(n) = O(n \log n)$
332    ///
333    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
334    ///
335    /// # Panics
336    /// Panics if `self` or `other` are greater than or equal to `m`.
337    ///
338    /// # Examples
339    /// ```
340    /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed;
341    /// use malachite_nz::natural::Natural;
342    ///
343    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
344    /// assert_eq!(
345    ///     Natural::from(6u8).mod_mul_precomputed(
346    ///         Natural::from(7u32),
347    ///         &Natural::from(10u32),
348    ///         &data
349    ///     ),
350    ///     2
351    /// );
352    /// assert_eq!(
353    ///     Natural::from(9u8).mod_mul_precomputed(
354    ///         Natural::from(9u32),
355    ///         &Natural::from(10u32),
356    ///         &data
357    ///     ),
358    ///     1
359    /// );
360    /// assert_eq!(
361    ///     Natural::from(4u8).mod_mul_precomputed(
362    ///         Natural::from(7u32),
363    ///         &Natural::from(10u32),
364    ///         &data
365    ///     ),
366    ///     8
367    /// );
368    /// ```
369    ///
370    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c`
371    /// are taken by value and `m` is taken by reference.
372    fn mod_mul_precomputed(mut self, other: Self, m: &'a Self, data: &ModMulData) -> Self {
373        self.mod_mul_precomputed_assign(other, m, data);
374        self
375    }
376}
377
378impl<'a> ModMulPrecomputed<&'a Self, Self> for Natural {
379    type Output = Self;
380    type Data = ModMulData;
381
382    /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and
383    /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign).
384    ///
385    /// # Worst-case complexity
386    /// Constant time and additional memory.
387    ///
388    /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1.
389    #[inline]
390    fn precompute_mod_mul_data(m: &Self) -> ModMulData {
391        precompute_mod_mul_data_helper(m)
392    }
393
394    /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already
395    /// reduced modulo $m$. The first and third [`Natural`]s are taken by value and the second by
396    /// reference.
397    ///
398    /// Some precomputed data is provided; this speeds up computations involving several modular
399    /// multiplications with the same modulus. The precomputed data should be obtained using
400    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
401    ///
402    /// # Worst-case complexity
403    /// $T(n) = O(n \log n \log\log n)$
404    ///
405    /// $M(n) = O(n \log n)$
406    ///
407    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
408    ///
409    /// # Panics
410    /// Panics if `self` or `other` are greater than or equal to `m`.
411    ///
412    /// # Examples
413    /// ```
414    /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed;
415    /// use malachite_nz::natural::Natural;
416    ///
417    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
418    /// assert_eq!(
419    ///     Natural::from(6u8).mod_mul_precomputed(
420    ///         &Natural::from(7u32),
421    ///         Natural::from(10u32),
422    ///         &data
423    ///     ),
424    ///     2
425    /// );
426    /// assert_eq!(
427    ///     Natural::from(9u8).mod_mul_precomputed(
428    ///         &Natural::from(9u32),
429    ///         Natural::from(10u32),
430    ///         &data
431    ///     ),
432    ///     1
433    /// );
434    /// assert_eq!(
435    ///     Natural::from(4u8).mod_mul_precomputed(
436    ///         &Natural::from(7u32),
437    ///         Natural::from(10u32),
438    ///         &data
439    ///     ),
440    ///     8
441    /// );
442    /// ```
443    ///
444    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m`
445    /// are taken by value and `c` is taken by reference.
446    fn mod_mul_precomputed(mut self, other: &'a Self, m: Self, data: &ModMulData) -> Self {
447        self.mod_mul_precomputed_assign(other, m, data);
448        self
449    }
450}
451
452impl<'a, 'b> ModMulPrecomputed<&'a Self, &'b Self> for Natural {
453    type Output = Self;
454    type Data = ModMulData;
455
456    /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and
457    /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign).
458    ///
459    /// # Worst-case complexity
460    /// Constant time and additional memory.
461    ///
462    /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1.
463    #[inline]
464    fn precompute_mod_mul_data(m: &&Self) -> ModMulData {
465        precompute_mod_mul_data_helper(m)
466    }
467
468    /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already
469    /// reduced modulo $m$. The first [`Natural`] is taken by value and the second and third by
470    /// reference.
471    ///
472    /// Some precomputed data is provided; this speeds up computations involving several modular
473    /// multiplications with the same modulus. The precomputed data should be obtained using
474    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
475    ///
476    /// # Worst-case complexity
477    /// $T(n) = O(n \log n \log\log n)$
478    ///
479    /// $M(n) = O(n \log n)$
480    ///
481    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
482    ///
483    /// # Panics
484    /// Panics if `self` or `other` are greater than or equal to `m`.
485    ///
486    /// # Examples
487    /// ```
488    /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed;
489    /// use malachite_nz::natural::Natural;
490    ///
491    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
492    /// assert_eq!(
493    ///     Natural::from(6u8).mod_mul_precomputed(
494    ///         &Natural::from(7u32),
495    ///         &Natural::from(10u32),
496    ///         &data
497    ///     ),
498    ///     2
499    /// );
500    /// assert_eq!(
501    ///     Natural::from(9u8).mod_mul_precomputed(
502    ///         &Natural::from(9u32),
503    ///         &Natural::from(10u32),
504    ///         &data
505    ///     ),
506    ///     1
507    /// );
508    /// assert_eq!(
509    ///     Natural::from(4u8).mod_mul_precomputed(
510    ///         &Natural::from(7u32),
511    ///         &Natural::from(10u32),
512    ///         &data
513    ///     ),
514    ///     8
515    /// );
516    /// ```
517    ///
518    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is
519    /// taken by value and `c` and `m` are taken by reference.
520    fn mod_mul_precomputed(mut self, other: &'a Self, m: &'b Self, data: &ModMulData) -> Self {
521        self.mod_mul_precomputed_assign(other, m, data);
522        self
523    }
524}
525
526impl ModMulPrecomputed<Natural, Natural> for &Natural {
527    type Output = Natural;
528    type Data = ModMulData;
529
530    /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and
531    /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign).
532    ///
533    /// # Worst-case complexity
534    /// Constant time and additional memory.
535    ///
536    /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1.
537    #[inline]
538    fn precompute_mod_mul_data(m: &Natural) -> ModMulData {
539        precompute_mod_mul_data_helper(m)
540    }
541
542    /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already
543    /// reduced modulo $m$. The first [`Natural`] is taken by reference and the second and third by
544    /// value.
545    ///
546    /// Some precomputed data is provided; this speeds up computations involving several modular
547    /// multiplications with the same modulus. The precomputed data should be obtained using
548    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
549    ///
550    /// # Worst-case complexity
551    /// $T(n) = O(n \log n \log\log n)$
552    ///
553    /// $M(n) = O(n \log n)$
554    ///
555    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
556    ///
557    /// # Panics
558    /// Panics if `self` or `other` are greater than or equal to `m`.
559    ///
560    /// # Examples
561    /// ```
562    /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed;
563    /// use malachite_nz::natural::Natural;
564    ///
565    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
566    /// assert_eq!(
567    ///     (&Natural::from(6u8)).mod_mul_precomputed(
568    ///         Natural::from(7u32),
569    ///         Natural::from(10u32),
570    ///         &data
571    ///     ),
572    ///     2
573    /// );
574    /// assert_eq!(
575    ///     (&Natural::from(9u8)).mod_mul_precomputed(
576    ///         Natural::from(9u32),
577    ///         Natural::from(10u32),
578    ///         &data
579    ///     ),
580    ///     1
581    /// );
582    /// assert_eq!(
583    ///     (&Natural::from(4u8)).mod_mul_precomputed(
584    ///         Natural::from(7u32),
585    ///         Natural::from(10u32),
586    ///         &data
587    ///     ),
588    ///     8
589    /// );
590    /// ```
591    ///
592    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is
593    /// taken by reference and `c` and `m` are taken by value.
594    fn mod_mul_precomputed(self, other: Natural, m: Natural, data: &ModMulData) -> Natural {
595        assert!(*self < m, "self must be reduced mod m, but {self} >= {m}");
596        assert!(other < m, "other must be reduced mod m, but {other} >= {m}");
597        match (self, other, m, data) {
598            (&Natural::ZERO, _, _, _) | (_, Natural::ZERO, _, _) => Natural::ZERO,
599            (x, Natural::ONE, _, _) => x.clone(),
600            (&Natural::ONE, y, _, _) => y,
601            (
602                &Natural(Small(x)),
603                Natural(Small(y)),
604                Natural(Small(m)),
605                &ModMulData::OneLimb(inv),
606            ) => Natural::from(x.mod_mul_precomputed(y, m, &inv)),
607            (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul(y, Limb::WIDTH),
608            (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => {
609                x.mod_mul_precomputed_two_limbs(&y, &m, inv_2, inv_1, inv_0)
610            }
611            (x, y, m, _) => x * y % m,
612        }
613    }
614}
615
616impl ModMulPrecomputed<Natural, &Natural> for &Natural {
617    type Output = Natural;
618    type Data = ModMulData;
619
620    /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and
621    /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign).
622    ///
623    /// # Worst-case complexity
624    /// Constant time and additional memory.
625    ///
626    /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1.
627    #[inline]
628    fn precompute_mod_mul_data(m: &&Natural) -> ModMulData {
629        precompute_mod_mul_data_helper(m)
630    }
631
632    /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already
633    /// reduced modulo $m$. The first and third [`Natural`]s are taken by reference and the second
634    /// by value.
635    ///
636    /// Some precomputed data is provided; this speeds up computations involving several modular
637    /// multiplications with the same modulus. The precomputed data should be obtained using
638    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
639    ///
640    /// # Panics
641    /// Panics if `self` or `other` are greater than or equal to `m`.
642    ///
643    /// # Worst-case complexity
644    /// $T(n) = O(n \log n \log\log n)$
645    ///
646    /// $M(n) = O(n \log n)$
647    ///
648    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
649    ///
650    /// # Examples
651    /// ```
652    /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed;
653    /// use malachite_nz::natural::Natural;
654    ///
655    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
656    /// assert_eq!(
657    ///     (&Natural::from(6u8)).mod_mul_precomputed(
658    ///         Natural::from(7u32),
659    ///         &Natural::from(10u32),
660    ///         &data
661    ///     ),
662    ///     2
663    /// );
664    /// assert_eq!(
665    ///     (&Natural::from(9u8)).mod_mul_precomputed(
666    ///         Natural::from(9u32),
667    ///         &Natural::from(10u32),
668    ///         &data
669    ///     ),
670    ///     1
671    /// );
672    /// assert_eq!(
673    ///     (&Natural::from(4u8)).mod_mul_precomputed(
674    ///         Natural::from(7u32),
675    ///         &Natural::from(10u32),
676    ///         &data
677    ///     ),
678    ///     8
679    /// );
680    /// ```
681    ///
682    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m`
683    /// are taken by reference and `c` is taken by value.
684    #[inline]
685    fn mod_mul_precomputed(self, other: Natural, m: &Natural, data: &ModMulData) -> Natural {
686        other.mod_mul_precomputed(self, m, data)
687    }
688}
689
690impl ModMulPrecomputed<&Natural, Natural> for &Natural {
691    type Output = Natural;
692    type Data = ModMulData;
693
694    /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and
695    /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign).
696    ///
697    /// # Worst-case complexity
698    /// Constant time and additional memory.
699    ///
700    /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1.
701    #[inline]
702    fn precompute_mod_mul_data(m: &Natural) -> ModMulData {
703        precompute_mod_mul_data_helper(m)
704    }
705
706    /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already
707    /// reduced modulo $m$. The first two [`Natural`]s are taken by reference and the third by
708    /// value.
709    ///
710    /// Some precomputed data is provided; this speeds up computations involving several modular
711    /// multiplications with the same modulus. The precomputed data should be obtained using
712    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
713    ///
714    /// # Worst-case complexity
715    /// $T(n) = O(n \log n \log\log n)$
716    ///
717    /// $M(n) = O(n \log n)$
718    ///
719    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
720    ///
721    /// # Panics
722    /// Panics if `self` or `other` are greater than or equal to `m`.
723    ///
724    /// # Examples
725    /// ```
726    /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed;
727    /// use malachite_nz::natural::Natural;
728    ///
729    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
730    /// assert_eq!(
731    ///     (&Natural::from(6u8)).mod_mul_precomputed(
732    ///         &Natural::from(7u32),
733    ///         Natural::from(10u32),
734    ///         &data
735    ///     ),
736    ///     2
737    /// );
738    /// assert_eq!(
739    ///     (&Natural::from(9u8)).mod_mul_precomputed(
740    ///         &Natural::from(9u32),
741    ///         Natural::from(10u32),
742    ///         &data
743    ///     ),
744    ///     1
745    /// );
746    /// assert_eq!(
747    ///     (&Natural::from(4u8)).mod_mul_precomputed(
748    ///         &Natural::from(7u32),
749    ///         Natural::from(10u32),
750    ///         &data
751    ///     ),
752    ///     8
753    /// );
754    /// ```
755    ///
756    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c`
757    /// are taken by reference and `m` is taken by value.
758    fn mod_mul_precomputed(self, other: &Natural, m: Natural, data: &ModMulData) -> Natural {
759        assert!(*self < m, "self must be reduced mod m, but {self} >= {m}");
760        assert!(
761            *other < m,
762            "other must be reduced mod m, but {other} >= {m}"
763        );
764        match (self, other, m, data) {
765            (&Natural::ZERO, _, _, _) | (_, &Natural::ZERO, _, _) => Natural::ZERO,
766            (x, &Natural::ONE, _, _) => x.clone(),
767            (&Natural::ONE, y, _, _) => y.clone(),
768            (
769                &Natural(Small(x)),
770                &Natural(Small(y)),
771                Natural(Small(m)),
772                &ModMulData::OneLimb(inv),
773            ) => Natural::from(x.mod_mul_precomputed(y, m, &inv)),
774            (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul(y, Limb::WIDTH),
775            (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => {
776                x.mod_mul_precomputed_two_limbs(y, &m, inv_2, inv_1, inv_0)
777            }
778            (x, y, m, _) => x * y % m,
779        }
780    }
781}
782
783impl ModMulPrecomputed<&Natural, &Natural> for &Natural {
784    type Output = Natural;
785    type Data = ModMulData;
786
787    /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and
788    /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign).
789    ///
790    /// # Worst-case complexity
791    /// Constant time and additional memory.
792    ///
793    /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1.
794    #[inline]
795    fn precompute_mod_mul_data(m: &&Natural) -> ModMulData {
796        precompute_mod_mul_data_helper(m)
797    }
798
799    /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already
800    /// reduced modulo $m$. All three [`Natural`]s are taken by reference.
801    ///
802    /// Some precomputed data is provided; this speeds up computations involving several modular
803    /// multiplications with the same modulus. The precomputed data should be obtained using
804    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
805    ///
806    /// # Worst-case complexity
807    /// $T(n) = O(n \log n \log\log n)$
808    ///
809    /// $M(n) = O(n \log n)$
810    ///
811    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
812    ///
813    /// # Panics
814    /// Panics if `self` or `other` are greater than or equal to `m`.
815    ///
816    /// # Examples
817    /// ```
818    /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed;
819    /// use malachite_nz::natural::Natural;
820    ///
821    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
822    /// assert_eq!(
823    ///     (&Natural::from(6u8)).mod_mul_precomputed(
824    ///         &Natural::from(7u32),
825    ///         &Natural::from(10u32),
826    ///         &data
827    ///     ),
828    ///     2
829    /// );
830    /// assert_eq!(
831    ///     (&Natural::from(9u8)).mod_mul_precomputed(
832    ///         &Natural::from(9u32),
833    ///         &Natural::from(10u32),
834    ///         &data
835    ///     ),
836    ///     1
837    /// );
838    /// assert_eq!(
839    ///     (&Natural::from(4u8)).mod_mul_precomputed(
840    ///         &Natural::from(7u32),
841    ///         &Natural::from(10u32),
842    ///         &data
843    ///     ),
844    ///     8
845    /// );
846    /// ```
847    ///
848    /// This is equivalent to `_fmpz_mod_mulN` from fmpz_mod/mul.c, FLINT 2.7.1, where `b`, `c`, and
849    /// `m` are taken by reference.
850    fn mod_mul_precomputed(self, other: &Natural, m: &Natural, data: &ModMulData) -> Natural {
851        assert!(self < m, "self must be reduced mod m, but {self} >= {m}");
852        assert!(other < m, "other must be reduced mod m, but {other} >= {m}");
853        match (self, other, m, data) {
854            (&Natural::ZERO, _, _, _) | (_, &Natural::ZERO, _, _) => Natural::ZERO,
855            (x, &Natural::ONE, _, _) => x.clone(),
856            (&Natural::ONE, y, _, _) => y.clone(),
857            (
858                &Natural(Small(x)),
859                &Natural(Small(y)),
860                &Natural(Small(m)),
861                &ModMulData::OneLimb(inv),
862            ) => Natural::from(x.mod_mul_precomputed(y, m, &inv)),
863            (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul(y, Limb::WIDTH),
864            (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => {
865                x.mod_mul_precomputed_two_limbs(y, m, inv_2, inv_1, inv_0)
866            }
867            (x, y, m, _) => x * y % m,
868        }
869    }
870}
871
872impl ModMulPrecomputedAssign<Self, Self> for Natural {
873    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be
874    /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by value.
875    ///
876    /// Some precomputed data is provided; this speeds up computations involving several modular
877    /// multiplications with the same modulus. The precomputed data should be obtained using
878    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
879    ///
880    /// # Worst-case complexity
881    /// $T(n) = O(n \log n \log\log n)$
882    ///
883    /// $M(n) = O(n \log n)$
884    ///
885    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
886    ///
887    /// # Panics
888    /// Panics if `self` or `other` are greater than or equal to `m`.
889    ///
890    /// # Examples
891    /// ```
892    /// use malachite_base::num::arithmetic::traits::{ModMulPrecomputed, ModMulPrecomputedAssign};
893    /// use malachite_nz::natural::Natural;
894    ///
895    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
896    ///
897    /// let mut x = Natural::from(6u8);
898    /// x.mod_mul_precomputed_assign(Natural::from(7u32), Natural::from(10u32), &data);
899    /// assert_eq!(x, 2);
900    ///
901    /// let mut x = Natural::from(9u8);
902    /// x.mod_mul_precomputed_assign(Natural::from(9u32), Natural::from(10u32), &data);
903    /// assert_eq!(x, 1);
904    ///
905    /// let mut x = Natural::from(4u8);
906    /// x.mod_mul_precomputed_assign(Natural::from(7u32), Natural::from(10u32), &data);
907    /// assert_eq!(x, 8);
908    /// ```
909    ///
910    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`,
911    /// and `m` are taken by value and `a == b`.
912    fn mod_mul_precomputed_assign(&mut self, other: Self, m: Self, data: &ModMulData) {
913        assert!(*self < m, "self must be reduced mod m, but {self} >= {m}");
914        assert!(other < m, "other must be reduced mod m, but {other} >= {m}");
915        match (&mut *self, other, m, data) {
916            (&mut Self::ZERO, _, _, _) | (_, Self::ONE, _, _) => {}
917            (x, Self::ZERO, _, _) => *x = Self::ZERO,
918            (&mut Self::ONE, y, _, _) => *self = y,
919            (&mut Self(Small(x)), Self(Small(y)), Self(Small(m)), &ModMulData::OneLimb(inv)) => {
920                *self = Self::from(x.mod_mul_precomputed(y, m, &inv));
921            }
922            (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul_assign(y, Limb::WIDTH),
923            (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => {
924                x.mod_mul_precomputed_two_limbs_assign(&y, &m, inv_2, inv_1, inv_0);
925            }
926            (x, y, m, _) => {
927                *x *= y;
928                *x %= m;
929            }
930        }
931    }
932}
933
934impl<'a> ModMulPrecomputedAssign<Self, &'a Self> for Natural {
935    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be
936    /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by value
937    /// and the second by reference.
938    ///
939    /// Some precomputed data is provided; this speeds up computations involving several modular
940    /// multiplications with the same modulus. The precomputed data should be obtained using
941    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
942    ///
943    /// # Worst-case complexity
944    /// $T(n) = O(n \log n \log\log n)$
945    ///
946    /// $M(n) = O(n \log n)$
947    ///
948    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
949    ///
950    /// # Panics
951    /// Panics if `self` or `other` are greater than or equal to `m`.
952    ///
953    /// # Examples
954    /// ```
955    /// use malachite_base::num::arithmetic::traits::{ModMulPrecomputed, ModMulPrecomputedAssign};
956    /// use malachite_nz::natural::Natural;
957    ///
958    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
959    ///
960    /// let mut x = Natural::from(6u8);
961    /// x.mod_mul_precomputed_assign(Natural::from(7u32), &Natural::from(10u32), &data);
962    /// assert_eq!(x, 2);
963    ///
964    /// let mut x = Natural::from(9u8);
965    /// x.mod_mul_precomputed_assign(Natural::from(9u32), &Natural::from(10u32), &data);
966    /// assert_eq!(x, 1);
967    ///
968    /// let mut x = Natural::from(4u8);
969    /// x.mod_mul_precomputed_assign(Natural::from(7u32), &Natural::from(10u32), &data);
970    /// assert_eq!(x, 8);
971    /// ```
972    ///
973    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c`
974    /// are taken by value, `m` is taken by reference, and `a == b`.
975    fn mod_mul_precomputed_assign(&mut self, other: Self, m: &'a Self, data: &ModMulData) {
976        assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}");
977        assert!(
978            other < *m,
979            "other must be reduced mod m, but {other} >= {m}"
980        );
981        match (&mut *self, other, m, data) {
982            (&mut Self::ZERO, _, _, _) | (_, Self::ONE, _, _) => {}
983            (x, Self::ZERO, _, _) => *x = Self::ZERO,
984            (&mut Self::ONE, y, _, _) => *self = y,
985            (&mut Self(Small(x)), Self(Small(y)), &Self(Small(m)), &ModMulData::OneLimb(inv)) => {
986                *self = Self::from(x.mod_mul_precomputed(y, m, &inv));
987            }
988            (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul_assign(y, Limb::WIDTH),
989            (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => {
990                x.mod_mul_precomputed_two_limbs_assign(&y, m, inv_2, inv_1, inv_0);
991            }
992            (x, y, m, _) => {
993                *x *= y;
994                *x %= m;
995            }
996        }
997    }
998}
999
1000impl<'a> ModMulPrecomputedAssign<&'a Self, Self> for Natural {
1001    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be
1002    /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by
1003    /// reference and the second by value.
1004    ///
1005    /// Some precomputed data is provided; this speeds up computations involving several modular
1006    /// multiplications with the same modulus. The precomputed data should be obtained using
1007    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
1008    ///
1009    /// # Worst-case complexity
1010    /// $T(n) = O(n \log n \log\log n)$
1011    ///
1012    /// $M(n) = O(n \log n)$
1013    ///
1014    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1015    ///
1016    /// # Panics
1017    /// Panics if `self` or `other` are greater than or equal to `m`.
1018    ///
1019    /// # Examples
1020    /// ```
1021    /// use malachite_base::num::arithmetic::traits::{ModMulPrecomputed, ModMulPrecomputedAssign};
1022    /// use malachite_nz::natural::Natural;
1023    ///
1024    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
1025    ///
1026    /// let mut x = Natural::from(6u8);
1027    /// x.mod_mul_precomputed_assign(&Natural::from(7u32), Natural::from(10u32), &data);
1028    /// assert_eq!(x, 2);
1029    ///
1030    /// let mut x = Natural::from(9u8);
1031    /// x.mod_mul_precomputed_assign(&Natural::from(9u32), Natural::from(10u32), &data);
1032    /// assert_eq!(x, 1);
1033    ///
1034    /// let mut x = Natural::from(4u8);
1035    /// x.mod_mul_precomputed_assign(&Natural::from(7u32), Natural::from(10u32), &data);
1036    /// assert_eq!(x, 8);
1037    /// ```
1038    ///
1039    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m`
1040    /// are taken by value, `c` is taken by reference, and `a == b`.
1041    fn mod_mul_precomputed_assign(&mut self, other: &'a Self, m: Self, data: &ModMulData) {
1042        assert!(*self < m, "self must be reduced mod m, but {self} >= {m}");
1043        assert!(
1044            *other < m,
1045            "other must be reduced mod m, but {other} >= {m}"
1046        );
1047        match (&mut *self, other, m, data) {
1048            (&mut Self::ZERO, _, _, _) | (_, &Self::ONE, _, _) => {}
1049            (x, &Self::ZERO, _, _) => *x = Self::ZERO,
1050            (&mut Self::ONE, y, _, _) => *self = y.clone(),
1051            (&mut Self(Small(x)), &Self(Small(y)), Self(Small(m)), &ModMulData::OneLimb(inv)) => {
1052                *self = Self::from(x.mod_mul_precomputed(y, m, &inv));
1053            }
1054            (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul_assign(y, Limb::WIDTH),
1055            (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => {
1056                x.mod_mul_precomputed_two_limbs_assign(y, &m, inv_2, inv_1, inv_0);
1057            }
1058            (x, y, m, _) => {
1059                *x *= y;
1060                *x %= m;
1061            }
1062        }
1063    }
1064}
1065
1066impl<'a, 'b> ModMulPrecomputedAssign<&'a Self, &'b Self> for Natural {
1067    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be
1068    /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by reference.
1069    ///
1070    /// Some precomputed data is provided; this speeds up computations involving several modular
1071    /// multiplications with the same modulus. The precomputed data should be obtained using
1072    /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data).
1073    ///
1074    /// # Worst-case complexity
1075    /// $T(n) = O(n \log n \log\log n)$
1076    ///
1077    /// $M(n) = O(n \log n)$
1078    ///
1079    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1080    ///
1081    /// # Panics
1082    /// Panics if `self` or `other` are greater than or equal to `m`.
1083    ///
1084    /// # Examples
1085    /// ```
1086    /// use malachite_base::num::arithmetic::traits::{ModMulPrecomputed, ModMulPrecomputedAssign};
1087    /// use malachite_nz::natural::Natural;
1088    ///
1089    /// let data = ModMulPrecomputed::<Natural>::precompute_mod_mul_data(&Natural::from(10u32));
1090    ///
1091    /// let mut x = Natural::from(6u8);
1092    /// x.mod_mul_precomputed_assign(&Natural::from(7u32), &Natural::from(10u32), &data);
1093    /// assert_eq!(x, 2);
1094    ///
1095    /// let mut x = Natural::from(9u8);
1096    /// x.mod_mul_precomputed_assign(&Natural::from(9u32), &Natural::from(10u32), &data);
1097    /// assert_eq!(x, 1);
1098    ///
1099    /// let mut x = Natural::from(4u8);
1100    /// x.mod_mul_precomputed_assign(&Natural::from(7u32), &Natural::from(10u32), &data);
1101    /// assert_eq!(x, 8);
1102    /// ```
1103    ///
1104    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is
1105    /// taken by value, `c` and `m` are taken by reference, and `a == b`.
1106    fn mod_mul_precomputed_assign(&mut self, other: &'a Self, m: &'b Self, data: &ModMulData) {
1107        assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}");
1108        assert!(other < m, "other must be reduced mod m, but {other} >= {m}");
1109        match (&mut *self, other, m, data) {
1110            (&mut Self::ZERO, _, _, _) | (_, &Self::ONE, _, _) => {}
1111            (x, &Self::ZERO, _, _) => *x = Self::ZERO,
1112            (&mut Self::ONE, y, _, _) => *self = y.clone(),
1113            (&mut Self(Small(x)), &Self(Small(y)), &Self(Small(m)), &ModMulData::OneLimb(inv)) => {
1114                *self = Self::from(x.mod_mul_precomputed(y, m, &inv));
1115            }
1116            (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul_assign(y, Limb::WIDTH),
1117            (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => {
1118                x.mod_mul_precomputed_two_limbs_assign(y, m, inv_2, inv_1, inv_0);
1119            }
1120            (x, y, m, _) => {
1121                *x *= y;
1122                *x %= m;
1123            }
1124        }
1125    }
1126}
1127
1128impl ModMul<Self, Self> for Natural {
1129    type Output = Self;
1130
1131    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already
1132    /// reduced modulo $m$. All three [`Natural`]s are taken by value.
1133    ///
1134    /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1135    ///
1136    /// # Worst-case complexity
1137    /// $T(n) = O(n \log n \log\log n)$
1138    ///
1139    /// $M(n) = O(n \log n)$
1140    ///
1141    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1142    ///
1143    /// # Panics
1144    /// Panics if `self` or `other` are greater than or equal to `m`.
1145    ///
1146    /// # Examples
1147    /// ```
1148    /// use malachite_base::num::arithmetic::traits::ModMul;
1149    /// use malachite_nz::natural::Natural;
1150    ///
1151    /// assert_eq!(
1152    ///     Natural::from(3u32).mod_mul(Natural::from(4u32), Natural::from(15u32)),
1153    ///     12
1154    /// );
1155    /// assert_eq!(
1156    ///     Natural::from(7u32).mod_mul(Natural::from(6u32), Natural::from(10u32)),
1157    ///     2
1158    /// );
1159    /// ```
1160    ///
1161    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`,
1162    /// and `m` are taken by value.
1163    #[inline]
1164    fn mod_mul(self, other: Self, m: Self) -> Self {
1165        let data = precompute_mod_mul_data_helper(&m);
1166        self.mod_mul_precomputed(other, m, &data)
1167    }
1168}
1169
1170impl<'a> ModMul<Self, &'a Self> for Natural {
1171    type Output = Self;
1172
1173    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already
1174    /// reduced modulo $m$. The first two [`Natural`]s are taken by value and the third by
1175    /// reference.
1176    ///
1177    /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1178    ///
1179    /// # Worst-case complexity
1180    /// $T(n) = O(n \log n \log\log n)$
1181    ///
1182    /// $M(n) = O(n \log n)$
1183    ///
1184    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1185    ///
1186    /// # Panics
1187    /// Panics if `self` or `other` are greater than or equal to `m`.
1188    ///
1189    /// # Examples
1190    /// ```
1191    /// use malachite_base::num::arithmetic::traits::ModMul;
1192    /// use malachite_nz::natural::Natural;
1193    ///
1194    /// assert_eq!(
1195    ///     Natural::from(3u32).mod_mul(Natural::from(4u32), &Natural::from(15u32)),
1196    ///     12
1197    /// );
1198    /// assert_eq!(
1199    ///     Natural::from(7u32).mod_mul(Natural::from(6u32), &Natural::from(10u32)),
1200    ///     2
1201    /// );
1202    /// ```
1203    ///
1204    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c`
1205    /// are taken by value and `m` is taken by reference.
1206    #[inline]
1207    fn mod_mul(self, other: Self, m: &'a Self) -> Self {
1208        self.mod_mul_precomputed(other, m, &precompute_mod_mul_data_helper(m))
1209    }
1210}
1211
1212impl<'a> ModMul<&'a Self, Self> for Natural {
1213    type Output = Self;
1214
1215    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already
1216    /// reduced modulo $m$. The first and third [`Natural`]s are taken by value and the second by
1217    /// reference.
1218    ///
1219    /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1220    ///
1221    /// # Worst-case complexity
1222    /// $T(n) = O(n \log n \log\log n)$
1223    ///
1224    /// $M(n) = O(n \log n)$
1225    ///
1226    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1227    ///
1228    /// # Panics
1229    /// Panics if `self` or `other` are greater than or equal to `m`.
1230    ///
1231    /// # Examples
1232    /// ```
1233    /// use malachite_base::num::arithmetic::traits::ModMul;
1234    /// use malachite_nz::natural::Natural;
1235    ///
1236    /// assert_eq!(
1237    ///     Natural::from(3u32).mod_mul(&Natural::from(4u32), Natural::from(15u32)),
1238    ///     12
1239    /// );
1240    /// assert_eq!(
1241    ///     Natural::from(7u32).mod_mul(&Natural::from(6u32), Natural::from(10u32)),
1242    ///     2
1243    /// );
1244    /// ```
1245    ///
1246    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m`
1247    /// are taken by value and `c` is taken by reference.
1248    #[inline]
1249    fn mod_mul(self, other: &'a Self, m: Self) -> Self {
1250        let data = precompute_mod_mul_data_helper(&m);
1251        self.mod_mul_precomputed(other, m, &data)
1252    }
1253}
1254
1255impl<'a, 'b> ModMul<&'a Self, &'b Self> for Natural {
1256    type Output = Self;
1257
1258    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already
1259    /// reduced modulo $m$. The first [`Natural`] is taken by value and the second and third by
1260    /// reference.
1261    ///
1262    /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1263    ///
1264    /// # Worst-case complexity
1265    /// $T(n) = O(n \log n \log\log n)$
1266    ///
1267    /// $M(n) = O(n \log n)$
1268    ///
1269    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1270    ///
1271    /// # Panics
1272    /// Panics if `self` or `other` are greater than or equal to `m`.
1273    ///
1274    /// # Examples
1275    /// ```
1276    /// use malachite_base::num::arithmetic::traits::ModMul;
1277    /// use malachite_nz::natural::Natural;
1278    ///
1279    /// assert_eq!(
1280    ///     Natural::from(3u32).mod_mul(&Natural::from(4u32), &Natural::from(15u32)),
1281    ///     12
1282    /// );
1283    /// assert_eq!(
1284    ///     Natural::from(7u32).mod_mul(&Natural::from(6u32), &Natural::from(10u32)),
1285    ///     2
1286    /// );
1287    /// ```
1288    ///
1289    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is
1290    /// taken by value and `c` and `m` are taken by reference.
1291    #[inline]
1292    fn mod_mul(self, other: &'a Self, m: &'b Self) -> Self {
1293        self.mod_mul_precomputed(other, m, &precompute_mod_mul_data_helper(m))
1294    }
1295}
1296
1297impl ModMul<Natural, Natural> for &Natural {
1298    type Output = Natural;
1299
1300    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already
1301    /// reduced modulo $m$. The first [`Natural`] is taken by reference and the second and third by
1302    /// value.
1303    ///
1304    /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1305    ///
1306    /// # Worst-case complexity
1307    /// $T(n) = O(n \log n \log\log n)$
1308    ///
1309    /// $M(n) = O(n \log n)$
1310    ///
1311    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1312    ///
1313    /// # Panics
1314    /// Panics if `self` or `other` are greater than or equal to `m`.
1315    ///
1316    /// # Examples
1317    /// ```
1318    /// use malachite_base::num::arithmetic::traits::ModMul;
1319    /// use malachite_nz::natural::Natural;
1320    ///
1321    /// assert_eq!(
1322    ///     (&Natural::from(3u32)).mod_mul(Natural::from(4u32), Natural::from(15u32)),
1323    ///     12
1324    /// );
1325    /// assert_eq!(
1326    ///     (&Natural::from(7u32)).mod_mul(Natural::from(6u32), Natural::from(10u32)),
1327    ///     2
1328    /// );
1329    /// ```
1330    ///
1331    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is
1332    /// taken by reference and `c` and `m` are taken by value.
1333    #[inline]
1334    fn mod_mul(self, other: Natural, m: Natural) -> Natural {
1335        let data = precompute_mod_mul_data_helper(&m);
1336        self.mod_mul_precomputed(other, m, &data)
1337    }
1338}
1339
1340impl ModMul<Natural, &Natural> for &Natural {
1341    type Output = Natural;
1342
1343    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already
1344    /// reduced modulo $m$. The first and third [`Natural`]s are taken by reference and the second
1345    /// by value.
1346    ///
1347    /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1348    ///
1349    /// # Worst-case complexity
1350    /// $T(n) = O(n \log n \log\log n)$
1351    ///
1352    /// $M(n) = O(n \log n)$
1353    ///
1354    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1355    ///
1356    /// # Panics
1357    /// Panics if `self` or `other` are greater than or equal to `m`.
1358    ///
1359    /// # Examples
1360    /// ```
1361    /// use malachite_base::num::arithmetic::traits::ModMul;
1362    /// use malachite_nz::natural::Natural;
1363    ///
1364    /// assert_eq!(
1365    ///     (&Natural::from(3u32)).mod_mul(Natural::from(4u32), &Natural::from(15u32)),
1366    ///     12
1367    /// );
1368    /// assert_eq!(
1369    ///     (&Natural::from(7u32)).mod_mul(Natural::from(6u32), &Natural::from(10u32)),
1370    ///     2
1371    /// );
1372    /// ```
1373    ///
1374    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m`
1375    /// are taken by reference and `c` is taken by value.
1376    #[inline]
1377    fn mod_mul(self, other: Natural, m: &Natural) -> Natural {
1378        self.mod_mul_precomputed(other, m, &precompute_mod_mul_data_helper(m))
1379    }
1380}
1381
1382impl ModMul<&Natural, Natural> for &Natural {
1383    type Output = Natural;
1384
1385    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already
1386    /// reduced modulo $m$. The first two [`Natural`]s are taken by reference and the third by
1387    /// value.
1388    ///
1389    /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1390    ///
1391    /// # Worst-case complexity
1392    /// $T(n) = O(n \log n \log\log n)$
1393    ///
1394    /// $M(n) = O(n \log n)$
1395    ///
1396    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1397    ///
1398    /// # Panics
1399    /// Panics if `self` or `other` are greater than or equal to `m`.
1400    ///
1401    /// # Examples
1402    /// ```
1403    /// use malachite_base::num::arithmetic::traits::ModMul;
1404    /// use malachite_nz::natural::Natural;
1405    ///
1406    /// assert_eq!(
1407    ///     (&Natural::from(3u32)).mod_mul(&Natural::from(4u32), Natural::from(15u32)),
1408    ///     12
1409    /// );
1410    /// assert_eq!(
1411    ///     (&Natural::from(7u32)).mod_mul(&Natural::from(6u32), Natural::from(10u32)),
1412    ///     2
1413    /// );
1414    /// ```
1415    ///
1416    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c`
1417    /// are taken by reference and `m` is taken by value.
1418    #[inline]
1419    fn mod_mul(self, other: &Natural, m: Natural) -> Natural {
1420        let data = precompute_mod_mul_data_helper(&m);
1421        self.mod_mul_precomputed(other, m, &data)
1422    }
1423}
1424
1425impl ModMul<&Natural, &Natural> for &Natural {
1426    type Output = Natural;
1427
1428    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already
1429    /// reduced modulo $m$. All three [`Natural`]s are taken by reference.
1430    ///
1431    /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1432    ///
1433    /// # Worst-case complexity
1434    /// $T(n) = O(n \log n \log\log n)$
1435    ///
1436    /// $M(n) = O(n \log n)$
1437    ///
1438    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1439    ///
1440    /// # Panics
1441    /// Panics if `self` or `other` are greater than or equal to `m`.
1442    ///
1443    /// # Examples
1444    /// ```
1445    /// use malachite_base::num::arithmetic::traits::ModMul;
1446    /// use malachite_nz::natural::Natural;
1447    ///
1448    /// assert_eq!(
1449    ///     (&Natural::from(3u32)).mod_mul(&Natural::from(4u32), &Natural::from(15u32)),
1450    ///     12
1451    /// );
1452    /// assert_eq!(
1453    ///     (&Natural::from(7u32)).mod_mul(&Natural::from(6u32), &Natural::from(10u32)),
1454    ///     2
1455    /// );
1456    /// ```
1457    ///
1458    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`,
1459    /// and `m` are taken by reference.
1460    #[inline]
1461    fn mod_mul(self, other: &Natural, m: &Natural) -> Natural {
1462        self.mod_mul_precomputed(other, m, &precompute_mod_mul_data_helper(m))
1463    }
1464}
1465
1466impl ModMulAssign<Self, Self> for Natural {
1467    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be
1468    /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by value.
1469    ///
1470    /// $x \gets z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1471    ///
1472    /// # Worst-case complexity
1473    /// $T(n) = O(n \log n \log\log n)$
1474    ///
1475    /// $M(n) = O(n \log n)$
1476    ///
1477    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1478    ///
1479    /// # Panics
1480    /// Panics if `self` or `other` are greater than or equal to `m`.
1481    ///
1482    /// # Examples
1483    /// ```
1484    /// use malachite_base::num::arithmetic::traits::ModMulAssign;
1485    /// use malachite_nz::natural::Natural;
1486    ///
1487    /// let mut x = Natural::from(3u32);
1488    /// x.mod_mul_assign(Natural::from(4u32), Natural::from(15u32));
1489    /// assert_eq!(x, 12);
1490    ///
1491    /// let mut x = Natural::from(7u32);
1492    /// x.mod_mul_assign(Natural::from(6u32), Natural::from(10u32));
1493    /// assert_eq!(x, 2);
1494    /// ```
1495    ///
1496    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`,
1497    /// and `m` are taken by value and `a == b`.
1498    #[inline]
1499    fn mod_mul_assign(&mut self, other: Self, m: Self) {
1500        let data = precompute_mod_mul_data_helper(&m);
1501        self.mod_mul_precomputed_assign(other, m, &data);
1502    }
1503}
1504
1505impl<'a> ModMulAssign<Self, &'a Self> for Natural {
1506    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be
1507    /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by value
1508    /// and the second by reference.
1509    ///
1510    /// $x \gets z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1511    ///
1512    /// # Worst-case complexity
1513    /// $T(n) = O(n \log n \log\log n)$
1514    ///
1515    /// $M(n) = O(n \log n)$
1516    ///
1517    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1518    ///
1519    /// # Panics
1520    /// Panics if `self` or `other` are greater than or equal to `m`.
1521    ///
1522    /// # Examples
1523    /// ```
1524    /// use malachite_base::num::arithmetic::traits::ModMulAssign;
1525    /// use malachite_nz::natural::Natural;
1526    ///
1527    /// let mut x = Natural::from(3u32);
1528    /// x.mod_mul_assign(Natural::from(4u32), &Natural::from(15u32));
1529    /// assert_eq!(x, 12);
1530    ///
1531    /// let mut x = Natural::from(7u32);
1532    /// x.mod_mul_assign(Natural::from(6u32), &Natural::from(10u32));
1533    /// assert_eq!(x, 2);
1534    /// ```
1535    ///
1536    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c`
1537    /// are taken by value, `m` is taken by reference, and `a == b`.
1538    #[inline]
1539    fn mod_mul_assign(&mut self, other: Self, m: &'a Self) {
1540        self.mod_mul_precomputed_assign(other, m, &precompute_mod_mul_data_helper(m));
1541    }
1542}
1543
1544impl<'a> ModMulAssign<&'a Self, Self> for Natural {
1545    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be
1546    /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by
1547    /// reference and the second by value.
1548    ///
1549    /// # Worst-case complexity
1550    /// $T(n) = O(n \log n \log\log n)$
1551    ///
1552    /// $M(n) = O(n \log n)$
1553    ///
1554    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1555    ///
1556    /// # Panics
1557    /// Panics if `self` or `other` are greater than or equal to `m`.
1558    ///
1559    /// # Examples
1560    /// ```
1561    /// use malachite_base::num::arithmetic::traits::ModMulAssign;
1562    /// use malachite_nz::natural::Natural;
1563    ///
1564    /// let mut x = Natural::from(3u32);
1565    /// x.mod_mul_assign(&Natural::from(4u32), Natural::from(15u32));
1566    /// assert_eq!(x, 12);
1567    ///
1568    /// let mut x = Natural::from(7u32);
1569    /// x.mod_mul_assign(&Natural::from(6u32), Natural::from(10u32));
1570    /// assert_eq!(x, 2);
1571    /// ```
1572    ///
1573    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m`
1574    /// are taken by value, `c` is taken by reference, and `a == b`.
1575    #[inline]
1576    fn mod_mul_assign(&mut self, other: &'a Self, m: Self) {
1577        let data = precompute_mod_mul_data_helper(&m);
1578        self.mod_mul_precomputed_assign(other, m, &data);
1579    }
1580}
1581
1582impl<'a, 'b> ModMulAssign<&'a Self, &'b Self> for Natural {
1583    /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be
1584    /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by reference.
1585    ///
1586    /// $x \gets z$, where $x, y, z < m$ and $xy \equiv z \mod m$.
1587    ///
1588    /// # Worst-case complexity
1589    /// $T(n) = O(n \log n \log\log n)$
1590    ///
1591    /// $M(n) = O(n \log n)$
1592    ///
1593    /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`.
1594    ///
1595    /// # Panics
1596    /// Panics if `self` or `other` are greater than or equal to `m`.
1597    ///
1598    /// # Examples
1599    /// ```
1600    /// use malachite_base::num::arithmetic::traits::ModMulAssign;
1601    /// use malachite_nz::natural::Natural;
1602    ///
1603    /// let mut x = Natural::from(3u32);
1604    /// x.mod_mul_assign(&Natural::from(4u32), &Natural::from(15u32));
1605    /// assert_eq!(x, 12);
1606    ///
1607    /// let mut x = Natural::from(7u32);
1608    /// x.mod_mul_assign(&Natural::from(6u32), &Natural::from(10u32));
1609    /// assert_eq!(x, 2);
1610    /// ```
1611    ///
1612    /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is
1613    /// taken by value, `c` and `m` are taken by reference, and `a == b`.
1614    #[inline]
1615    fn mod_mul_assign(&mut self, other: &'a Self, m: &'b Self) {
1616        self.mod_mul_precomputed_assign(other, m, &precompute_mod_mul_data_helper(m));
1617    }
1618}