Skip to main content

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