Skip to main content

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}