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}