malachite_nz/natural/arithmetic/mod_power_of_2_add.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::natural::InnerNatural::{Large, Small};
10use crate::natural::arithmetic::add::{
11 limbs_add_limb, limbs_slice_add_greater_in_place_left, limbs_slice_add_limb_in_place,
12 limbs_slice_add_same_length_in_place_left, limbs_vec_add_in_place_left,
13};
14use crate::natural::logic::bit_access::limbs_clear_bit;
15use crate::natural::{Natural, bit_to_limb_count_ceiling};
16use crate::platform::Limb;
17use alloc::vec::Vec;
18use malachite_base::num::arithmetic::traits::{
19 ModPowerOf2Add, ModPowerOf2AddAssign, ModPowerOf2Shl, ModPowerOf2ShlAssign,
20};
21use malachite_base::num::basic::integers::PrimitiveInt;
22use malachite_base::num::basic::traits::Zero;
23use malachite_base::num::logic::traits::SignificantBits;
24
25// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the
26// limbs of the sum of the `Natural` and a `Limb`, mod `2 ^ pow`. Assumes the input is already
27// reduced mod `2 ^ pow`.
28//
29// # Worst-case complexity
30// $T(n) = O(n)$
31//
32// $M(n) = O(n)$
33//
34// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
35pub_test! {limbs_mod_power_of_2_add_limb(xs: &[Limb], y: Limb, pow: u64) -> Vec<Limb> {
36 if xs.len() < bit_to_limb_count_ceiling(pow) {
37 limbs_add_limb(xs, y)
38 } else {
39 let mut out = xs.to_vec();
40 if !limbs_slice_add_limb_in_place(&mut out, y) {
41 limbs_clear_bit(&mut out, pow);
42 }
43 out
44 }
45}}
46
47// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the
48// limbs of the sum of the `Natural` and a `Limb`, mod `2 ^ pow`, to the input slice. Returns
49// whether there is a carry. Assumes the input is already reduced mod `2 ^ pow`.
50//
51// # Worst-case complexity
52// $T(n) = O(n)$
53//
54// $M(n) = O(1)$
55//
56// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
57pub_test! {limbs_slice_mod_power_of_2_add_limb_in_place(
58 xs: &mut [Limb],
59 y: Limb,
60 pow: u64
61) -> bool {
62 if xs.len() < bit_to_limb_count_ceiling(pow) {
63 limbs_slice_add_limb_in_place(xs, y)
64 } else {
65 if !limbs_slice_add_limb_in_place(xs, y) {
66 limbs_clear_bit(xs, pow);
67 }
68 false
69 }
70}}
71
72// Interpreting a nonempty `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes
73// the limbs of the sum of the `Natural` and a `Limb`, mod `2 ^ pow`, to the input `Vec`. Assumes
74// the input is already reduced mod `2 ^ pow`.
75//
76// # Worst-case complexity
77// $T(n) = O(n)$
78//
79// $M(n) = O(1)$
80//
81// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
82//
83// # Panics
84// Panics if `xs` is empty.
85pub_crate_test! {limbs_vec_mod_power_of_2_add_limb_in_place(xs: &mut Vec<Limb>, y: Limb, pow: u64) {
86 assert!(!xs.is_empty());
87 if limbs_slice_mod_power_of_2_add_limb_in_place(xs, y, pow) {
88 xs.push(1);
89 }
90}}
91
92// Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, where the
93// first slice is at least as long as the second, returns a `Vec` of the limbs of the sum of the
94// `Natural`s mod `2 ^ pow`. Assumes the inputs are already reduced mod `2 ^ pow`.
95//
96// # Worst-case complexity
97// $T(n) = O(n)$
98//
99// $M(n) = O(n)$
100//
101// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
102//
103// # Panics
104// Panics if `xs` is shorter than `ys`.
105pub_test! {limbs_mod_power_of_2_add_greater(xs: &[Limb], ys: &[Limb], pow: u64) -> Vec<Limb> {
106 let mut out = xs.to_vec();
107 if limbs_slice_mod_power_of_2_add_greater_in_place_left(&mut out, ys, pow) {
108 out.push(1);
109 }
110 out
111}}
112
113// Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns a
114// `Vec` of the limbs of the sum of the `Natural`s mod `2 ^ pow`. Assumes the inputs are already
115// reduced mod `2 ^ pow`.
116//
117// # Worst-case complexity
118// $T(n) = O(n)$
119//
120// $M(n) = O(n)$
121//
122// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
123pub_test! {limbs_mod_power_of_2_add(xs: &[Limb], ys: &[Limb], pow: u64) -> Vec<Limb> {
124 if xs.len() >= ys.len() {
125 limbs_mod_power_of_2_add_greater(xs, ys, pow)
126 } else {
127 limbs_mod_power_of_2_add_greater(ys, xs, pow)
128 }
129}}
130
131// Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, where the
132// length of the first slice is greater than or equal to the length of the second, writes the
133// `xs.len()` least-significant limbs of the sum of the `Natural`s, mod `2 ^ pow`, to the first
134// (left) slice. Returns whether there is a carry. Assumes the inputs are already reduced mod `2 ^
135// pow`.
136//
137// # Worst-case complexity
138// $T(n) = O(n)$
139//
140// $M(n) = O(1)$
141//
142// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
143//
144// # Panics
145// Panics if `xs` is shorter than `ys`.
146pub_test! {limbs_slice_mod_power_of_2_add_greater_in_place_left(
147 xs: &mut [Limb],
148 ys: &[Limb],
149 pow: u64,
150) -> bool {
151 if xs.len() < bit_to_limb_count_ceiling(pow) {
152 limbs_slice_add_greater_in_place_left(xs, ys)
153 } else {
154 if !limbs_slice_add_greater_in_place_left(xs, ys) {
155 limbs_clear_bit(xs, pow);
156 }
157 false
158 }
159}}
160
161// Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of two
162// `Natural`s, writes the limbs of the sum of the `Natural`s, mod `2 ^ pow`, to the first (left)
163// slice. Assumes the inputs are already reduced mod `2 ^ pow`.
164//
165// # Worst-case complexity
166// $T(n) = O(n)$
167//
168// $M(m) = O(m)$
169//
170// where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1,
171// ys.len() - xs.len())`.
172pub_test! {limbs_vec_mod_power_of_2_add_in_place_left(xs: &mut Vec<Limb>, ys: &[Limb], pow: u64) {
173 let xs_len = xs.len();
174 let ys_len = ys.len();
175 let max_len =bit_to_limb_count_ceiling(pow);
176 if xs_len < max_len && ys_len < max_len {
177 limbs_vec_add_in_place_left(xs, ys);
178 } else {
179 let carry = if xs_len >= ys_len {
180 limbs_slice_mod_power_of_2_add_greater_in_place_left(xs, ys, pow)
181 } else {
182 let (ys_lo, ys_hi) = ys.split_at(xs_len);
183 let mut carry = limbs_slice_add_same_length_in_place_left(xs, ys_lo);
184 xs.extend_from_slice(ys_hi);
185 if carry {
186 carry = limbs_slice_add_limb_in_place(&mut xs[xs_len..], 1);
187 }
188 carry
189 };
190 if !carry {
191 limbs_clear_bit(xs, pow);
192 }
193 }
194}}
195
196// Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes
197// the limbs of the sum of the `Natural`s, mod `2 ^ pow`, to the longer slice (or the first one, if
198// they are equally long). Returns a `bool` which is `false` when the output is to the first `Vec`
199// and `true` when it's to the second `Vec`. Assumes the inputs are already reduced mod `2 ^ pow`.
200//
201// # Worst-case complexity
202// $T(n) = O(n)$
203//
204// $M(n) = O(1)$
205//
206// where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`.
207pub_test! {limbs_mod_power_of_2_add_in_place_either(
208 xs: &mut Vec<Limb>,
209 ys: &mut Vec<Limb>,
210 pow: u64,
211) -> bool {
212 if xs.len() >= ys.len() {
213 if limbs_slice_mod_power_of_2_add_greater_in_place_left(xs, ys, pow) {
214 xs.push(1);
215 }
216 false
217 } else {
218 if limbs_slice_mod_power_of_2_add_greater_in_place_left(ys, xs, pow) {
219 ys.push(1);
220 }
221 true
222 }
223}}
224
225impl Natural {
226 fn mod_power_of_2_add_limb_ref(&self, y: Limb, pow: u64) -> Self {
227 match (self, y, pow) {
228 (_, 0, _) => self.clone(),
229 (&Self::ZERO, _, _) => Self(Small(y)),
230 (&Self(Small(small)), other, pow) if pow <= Limb::WIDTH => {
231 Self(Small(small.mod_power_of_2_add(other, pow)))
232 }
233 (&Self(Small(small)), other, _) => {
234 let (sum, overflow) = small.overflowing_add(other);
235 if overflow {
236 Self(Large(vec![sum, 1]))
237 } else {
238 Self(Small(sum))
239 }
240 }
241 (&Self(Large(ref limbs)), other, pow) => {
242 Self::from_owned_limbs_asc(limbs_mod_power_of_2_add_limb(limbs, other, pow))
243 }
244 }
245 }
246
247 fn mod_power_of_2_add_assign_limb(&mut self, y: Limb, pow: u64) {
248 match (&mut *self, y, pow) {
249 (_, 0, _) => {}
250 (&mut Self::ZERO, _, _) => *self = Self(Small(y)),
251 (&mut Self(Small(ref mut small)), other, pow) if pow <= Limb::WIDTH => {
252 small.mod_power_of_2_add_assign(other, pow);
253 }
254 (&mut Self(Small(ref mut small)), other, _) => {
255 let (sum, overflow) = small.overflowing_add(other);
256 if overflow {
257 *self = Self(Large(vec![sum, 1]));
258 } else {
259 *small = sum;
260 }
261 }
262 (&mut Self(Large(ref mut limbs)), y, pow) => {
263 limbs_vec_mod_power_of_2_add_limb_in_place(limbs, y, pow);
264 self.trim();
265 }
266 }
267 }
268}
269
270impl ModPowerOf2Add<Self> for Natural {
271 type Output = Self;
272
273 /// Adds two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. Both
274 /// [`Natural`]s are taken by value.
275 ///
276 /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$.
277 ///
278 /// # Worst-case complexity
279 /// $T(n) = O(n)$
280 ///
281 /// $M(n) = O(1)$
282 ///
283 /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(),
284 /// other.significant_bits())`.
285 ///
286 /// # Panics
287 /// Panics if `self` or `other` are greater than or equal to $2^k$.
288 ///
289 /// # Examples
290 /// ```
291 /// use malachite_base::num::arithmetic::traits::ModPowerOf2Add;
292 /// use malachite_base::num::basic::traits::Zero;
293 /// use malachite_nz::natural::Natural;
294 ///
295 /// assert_eq!(Natural::ZERO.mod_power_of_2_add(Natural::from(2u32), 5), 2);
296 /// assert_eq!(
297 /// Natural::from(10u32).mod_power_of_2_add(Natural::from(14u32), 4),
298 /// 8
299 /// );
300 /// ```
301 fn mod_power_of_2_add(mut self, other: Self, pow: u64) -> Self {
302 self.mod_power_of_2_add_assign(other, pow);
303 self
304 }
305}
306
307impl<'a> ModPowerOf2Add<&'a Self> for Natural {
308 type Output = Self;
309
310 /// Adds two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. The
311 /// first [`Natural`] is taken by value and the second by reference.
312 ///
313 /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$.
314 ///
315 /// # Worst-case complexity
316 /// $T(n) = O(n)$
317 ///
318 /// $M(n) = O(n)$
319 ///
320 /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`.
321 ///
322 /// # Panics
323 /// Panics if `self` or `other` are greater than or equal to $2^k$.
324 ///
325 /// # Examples
326 /// ```
327 /// use malachite_base::num::arithmetic::traits::ModPowerOf2Add;
328 /// use malachite_base::num::basic::traits::Zero;
329 /// use malachite_nz::natural::Natural;
330 ///
331 /// assert_eq!(Natural::ZERO.mod_power_of_2_add(&Natural::from(2u32), 5), 2);
332 /// assert_eq!(
333 /// Natural::from(10u32).mod_power_of_2_add(&Natural::from(14u32), 4),
334 /// 8
335 /// );
336 /// ```
337 #[inline]
338 fn mod_power_of_2_add(mut self, other: &'a Self, pow: u64) -> Self {
339 self.mod_power_of_2_add_assign(other, pow);
340 self
341 }
342}
343
344impl ModPowerOf2Add<Natural> for &Natural {
345 type Output = Natural;
346
347 /// Adds two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. The
348 /// first [`Natural`] is taken by reference and the second by value.
349 ///
350 /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$.
351 ///
352 /// # Worst-case complexity
353 /// $T(n) = O(n)$
354 ///
355 /// $M(n) = O(n)$
356 ///
357 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
358 ///
359 /// # Panics
360 /// Panics if `self` or `other` are greater than or equal to $2^k$.
361 ///
362 /// # Examples
363 /// ```
364 /// use malachite_base::num::arithmetic::traits::ModPowerOf2Add;
365 /// use malachite_base::num::basic::traits::Zero;
366 /// use malachite_nz::natural::Natural;
367 ///
368 /// assert_eq!(
369 /// (&Natural::ZERO).mod_power_of_2_add(Natural::from(2u32), 5),
370 /// 2
371 /// );
372 /// assert_eq!(
373 /// (&Natural::from(10u32)).mod_power_of_2_add(Natural::from(14u32), 4),
374 /// 8
375 /// );
376 /// ```
377 #[inline]
378 fn mod_power_of_2_add(self, mut other: Natural, pow: u64) -> Natural {
379 other.mod_power_of_2_add_assign(self, pow);
380 other
381 }
382}
383
384impl ModPowerOf2Add<&Natural> for &Natural {
385 type Output = Natural;
386
387 /// Adds two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. Both
388 /// [`Natural`]s are taken by reference.
389 ///
390 /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$.
391 ///
392 /// # Worst-case complexity
393 /// $T(n) = O(n)$
394 ///
395 /// $M(n) = O(n)$
396 ///
397 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
398 /// other.significant_bits())`.
399 ///
400 /// # Panics
401 /// Panics if `self` or `other` are greater than or equal to $2^k$.
402 ///
403 /// # Examples
404 /// ```
405 /// use malachite_base::num::arithmetic::traits::ModPowerOf2Add;
406 /// use malachite_base::num::basic::traits::Zero;
407 /// use malachite_nz::natural::Natural;
408 ///
409 /// assert_eq!(
410 /// (&Natural::ZERO).mod_power_of_2_add(&Natural::from(2u32), 5),
411 /// 2
412 /// );
413 /// assert_eq!(
414 /// (&Natural::from(10u32)).mod_power_of_2_add(&Natural::from(14u32), 4),
415 /// 8
416 /// );
417 /// ```
418 fn mod_power_of_2_add(self, other: &Natural, pow: u64) -> Natural {
419 assert!(
420 self.significant_bits() <= pow,
421 "self must be reduced mod 2^pow, but {self} >= 2^{pow}"
422 );
423 assert!(
424 other.significant_bits() <= pow,
425 "other must be reduced mod 2^pow, but {other} >= 2^{pow}"
426 );
427 match (self, other) {
428 (x, y) if core::ptr::eq(x, y) => self.mod_power_of_2_shl(1, pow),
429 (x, &Natural(Small(y))) => x.mod_power_of_2_add_limb_ref(y, pow),
430 (&Natural(Small(x)), y) => y.mod_power_of_2_add_limb_ref(x, pow),
431 (&Natural(Large(ref xs)), &Natural(Large(ref ys))) => {
432 Natural::from_owned_limbs_asc(limbs_mod_power_of_2_add(xs, ys, pow))
433 }
434 }
435 }
436}
437
438impl ModPowerOf2AddAssign<Self> for Natural {
439 /// Adds two [`Natural`]s modulo $2^k$, in place. The inputs must be already reduced modulo
440 /// $2^k$. The [`Natural`] on the right-hand side is taken by value.
441 ///
442 /// $x \gets z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$.
443 ///
444 /// # Worst-case complexity
445 /// $T(n) = O(n)$
446 ///
447 /// $M(n) = O(1)$
448 ///
449 /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(),
450 /// other.significant_bits())`.
451 ///
452 /// # Panics
453 /// Panics if `self` or `other` are greater than or equal to $2^k$.
454 ///
455 /// # Examples
456 /// ```
457 /// use malachite_base::num::arithmetic::traits::ModPowerOf2AddAssign;
458 /// use malachite_base::num::basic::traits::Zero;
459 /// use malachite_nz::natural::Natural;
460 ///
461 /// let mut x = Natural::ZERO;
462 /// x.mod_power_of_2_add_assign(Natural::from(2u32), 5);
463 /// assert_eq!(x, 2);
464 ///
465 /// let mut x = Natural::from(10u32);
466 /// x.mod_power_of_2_add_assign(Natural::from(14u32), 4);
467 /// assert_eq!(x, 8);
468 /// ```
469 fn mod_power_of_2_add_assign(&mut self, mut other: Self, pow: u64) {
470 assert!(
471 self.significant_bits() <= pow,
472 "self must be reduced mod 2^pow, but {self} >= 2^{pow}"
473 );
474 assert!(
475 other.significant_bits() <= pow,
476 "other must be reduced mod 2^pow, but {other} >= 2^{pow}"
477 );
478 match (&mut *self, &mut other) {
479 (x, &mut Self(Small(y))) => x.mod_power_of_2_add_assign_limb(y, pow),
480 (&mut Self(Small(x)), y) => *self = y.mod_power_of_2_add_limb_ref(x, pow),
481 (&mut Self(Large(ref mut xs)), _) => {
482 if let Self(Large(mut ys)) = other {
483 if limbs_mod_power_of_2_add_in_place_either(xs, &mut ys, pow) {
484 *xs = ys;
485 }
486 self.trim();
487 }
488 }
489 }
490 }
491}
492
493impl<'a> ModPowerOf2AddAssign<&'a Self> for Natural {
494 /// Adds two [`Natural`]s modulo $2^k$, in place. The inputs must be already reduced modulo
495 /// $2^k$. The [`Natural`] on the right-hand side is taken by reference.
496 ///
497 /// $x \gets z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$.
498 ///
499 /// # Worst-case complexity
500 /// $T(n) = O(n)$
501 ///
502 /// $M(n) = O(n)$
503 ///
504 /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`.
505 ///
506 /// # Panics
507 /// Panics if `self` or `other` are greater than or equal to $2^k$.
508 ///
509 /// # Examples
510 /// ```
511 /// use malachite_base::num::arithmetic::traits::ModPowerOf2AddAssign;
512 /// use malachite_base::num::basic::traits::Zero;
513 /// use malachite_nz::natural::Natural;
514 ///
515 /// let mut x = Natural::ZERO;
516 /// x.mod_power_of_2_add_assign(&Natural::from(2u32), 5);
517 /// assert_eq!(x, 2);
518 ///
519 /// let mut x = Natural::from(10u32);
520 /// x.mod_power_of_2_add_assign(&Natural::from(14u32), 4);
521 /// assert_eq!(x, 8);
522 /// ```
523 fn mod_power_of_2_add_assign(&mut self, other: &'a Self, pow: u64) {
524 assert!(
525 self.significant_bits() <= pow,
526 "self must be reduced mod 2^pow, but {self} >= 2^{pow}"
527 );
528 assert!(
529 other.significant_bits() <= pow,
530 "other must be reduced mod 2^pow, but {other} >= 2^{pow}"
531 );
532 match (&mut *self, other) {
533 (x, y) if core::ptr::eq(x, y) => {
534 self.mod_power_of_2_shl_assign(pow, 1);
535 }
536 (x, &Self(Small(y))) => x.mod_power_of_2_add_assign_limb(y, pow),
537 (&mut Self(Small(x)), y) => *self = y.mod_power_of_2_add_limb_ref(x, pow),
538 (&mut Self(Large(ref mut xs)), &Self(Large(ref ys))) => {
539 limbs_vec_mod_power_of_2_add_in_place_left(xs, ys, pow);
540 self.trim();
541 }
542 }
543 }
544}