Skip to main content

malachite_nz/natural/arithmetic/
mod_power_of_2.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MP Library.
4//
5//      Copyright © 1991, 1993-1995, 2001, 2002, 2012 Free Software Foundation, Inc.
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::integer::conversion::to_twos_complement_limbs::limbs_twos_complement_in_place;
14use crate::natural::InnerNatural::{Large, Small};
15use crate::natural::{Natural, bit_to_limb_count_ceiling, bit_to_limb_count_floor};
16use crate::platform::Limb;
17use alloc::vec::Vec;
18use malachite_base::num::arithmetic::traits::{
19    ModPowerOf2, ModPowerOf2Assign, NegModPowerOf2, NegModPowerOf2Assign, RemPowerOf2,
20    RemPowerOf2Assign,
21};
22use malachite_base::num::basic::integers::PrimitiveInt;
23use malachite_base::num::basic::traits::Zero;
24use malachite_base::num::conversion::traits::WrappingFrom;
25use malachite_base::slices::slice_set_zero;
26
27// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the
28// limbs of the `Natural` mod two raised to `pow`. Equivalently, retains only the least-significant
29// `pow` bits.
30//
31// # Worst-case complexity
32// $T(n) = O(n)$
33//
34// $M(n) = O(n)$
35//
36// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
37//
38// This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where in is
39// non-negative and the result is returned.
40pub_test! {limbs_mod_power_of_2(xs: &[Limb], pow: u64) -> Vec<Limb> {
41    if pow == 0 {
42        return Vec::new();
43    }
44    let leftover_bits = pow & Limb::WIDTH_MASK;
45    let result_size = bit_to_limb_count_floor(pow);
46    if result_size >= xs.len() {
47        return xs.to_vec();
48    }
49    let mut result = xs[..result_size].to_vec();
50    if leftover_bits != 0 {
51        result.push(xs[result_size].mod_power_of_2(leftover_bits));
52    }
53    result
54}}
55
56// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the
57// limbs of the `Natural` mod two raised to `pow` to the input slice. Equivalently, retains only the
58// least-significant `pow` bits. If the upper limbs of the input slice are no longer needed, they
59// are set to zero.
60//
61// # Worst-case complexity
62// Constant time and additional memory.
63//
64// This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where `in` is
65// non-negative, `res == in`, and instead of possibly being truncated, the high limbs of `res` are
66// possibly filled with zeros.
67pub_crate_test! {limbs_slice_mod_power_of_2_in_place(xs: &mut [Limb], pow: u64) {
68    if pow == 0 {
69        slice_set_zero(xs);
70        return;
71    }
72    let new_size = bit_to_limb_count_ceiling(pow);
73    if new_size > xs.len() {
74        return;
75    }
76    slice_set_zero(&mut xs[new_size..]);
77    let leftover_bits = pow & Limb::WIDTH_MASK;
78    if leftover_bits != 0 {
79        xs[new_size - 1].mod_power_of_2_assign(leftover_bits);
80    }
81}}
82
83// Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the
84// limbs of the `Natural` mod two raised to `pow` to the input `Vec`. Equivalently, retains only the
85// least-significant `pow` bits.
86//
87// # Worst-case complexity
88// Constant time and additional memory.
89//
90// This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where `in` is
91// non-negative and `res == in`.
92pub_crate_test! {limbs_vec_mod_power_of_2_in_place(xs: &mut Vec<Limb>, pow: u64) {
93    if pow == 0 {
94        xs.clear();
95        return;
96    }
97    let new_size = bit_to_limb_count_ceiling(pow);
98    if new_size > xs.len() {
99        return;
100    }
101    xs.truncate(new_size);
102    let leftover_bits = pow & Limb::WIDTH_MASK;
103    if leftover_bits != 0 {
104        xs[new_size - 1].mod_power_of_2_assign(leftover_bits);
105    }
106}}
107
108// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the
109// limbs of the negative of the `Natural` mod two raised to `pow`. Equivalently, takes the two's
110// complement and retains only the least-significant `pow` bits.
111//
112// # Worst-case complexity
113// $T(n) = O(n)$
114//
115// $M(n) = O(n)$
116//
117// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
118//
119// This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where `in` is
120// negative and the result is returned. `xs` is the limbs of `-in`.
121pub_crate_test! {limbs_neg_mod_power_of_2(xs: &[Limb], pow: u64) -> Vec<Limb> {
122    let mut result = xs.to_vec();
123    limbs_neg_mod_power_of_2_in_place(&mut result, pow);
124    result
125}}
126
127// Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the
128// limbs of the negative of the `Natural` mod two raised to `pow` to the input `Vec`. Equivalently,
129// takes the two's complement and retains only the least-significant `pow` bits.
130//
131// # Worst-case complexity
132// $T(n) = O(n)$
133//
134// $M(n) = O(n)$
135//
136// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
137//
138// This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where `in` is
139// negative and `res == in`. `xs` is the limbs of `-in`.
140pub_crate_test! {limbs_neg_mod_power_of_2_in_place(xs: &mut Vec<Limb>, pow: u64) {
141    let new_size = bit_to_limb_count_ceiling(pow);
142    xs.resize(new_size, 0);
143    limbs_twos_complement_in_place(xs);
144    let leftover_bits = pow & Limb::WIDTH_MASK;
145    if leftover_bits != 0 {
146        xs[new_size - 1].mod_power_of_2_assign(leftover_bits);
147    }
148}}
149
150impl ModPowerOf2 for Natural {
151    type Output = Self;
152
153    /// Divides a [`Natural`] by $2^k$, returning just the remainder. The [`Natural`] is taken by
154    /// value.
155    ///
156    /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and
157    /// $0 \leq r < 2^k$.
158    ///
159    /// $$
160    /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
161    /// $$
162    ///
163    /// # Worst-case complexity
164    /// Constant time and additional memory.
165    ///
166    /// # Examples
167    /// ```
168    /// use malachite_base::num::arithmetic::traits::ModPowerOf2;
169    /// use malachite_nz::natural::Natural;
170    ///
171    /// // 1 * 2^8 + 4 = 260
172    /// assert_eq!(Natural::from(260u32).mod_power_of_2(8), 4);
173    ///
174    /// // 100 * 2^4 + 11 = 1611
175    /// assert_eq!(Natural::from(1611u32).mod_power_of_2(4), 11);
176    /// ```
177    #[inline]
178    fn mod_power_of_2(mut self, pow: u64) -> Self {
179        self.mod_power_of_2_assign(pow);
180        self
181    }
182}
183
184impl ModPowerOf2 for &Natural {
185    type Output = Natural;
186
187    /// Divides a [`Natural`] by $2^k$, returning just the remainder. The [`Natural`] is taken by
188    /// reference.
189    ///
190    /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and
191    /// $0 \leq r < 2^k$.
192    ///
193    /// # Worst-case complexity
194    /// $T(n) = O(n)$
195    ///
196    /// $M(n) = O(n)$
197    ///
198    /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
199    ///
200    /// # Examples
201    /// ```
202    /// use malachite_base::num::arithmetic::traits::ModPowerOf2;
203    /// use malachite_nz::natural::Natural;
204    ///
205    /// // 1 * 2^8 + 4 = 260
206    /// assert_eq!((&Natural::from(260u32)).mod_power_of_2(8), 4);
207    /// // 100 * 2^4 + 11 = 1611
208    /// assert_eq!((&Natural::from(1611u32)).mod_power_of_2(4), 11);
209    /// ```
210    fn mod_power_of_2(self, pow: u64) -> Natural {
211        match self {
212            Natural(Small(small)) => Natural(Small(small.mod_power_of_2(pow))),
213            Natural(Large(limbs)) => {
214                Natural::from_owned_limbs_asc(limbs_mod_power_of_2(limbs, pow))
215            }
216        }
217    }
218}
219
220impl ModPowerOf2Assign for Natural {
221    /// Divides a [`Natural`]by $2^k$, replacing the [`Natural`] by the remainder.
222    ///
223    /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and
224    /// $0 \leq r < 2^k$.
225    ///
226    /// # Worst-case complexity
227    /// Constant time and additional memory.
228    ///
229    /// # Examples
230    /// ```
231    /// use malachite_base::num::arithmetic::traits::ModPowerOf2Assign;
232    /// use malachite_nz::natural::Natural;
233    ///
234    /// // 1 * 2^8 + 4 = 260
235    /// let mut x = Natural::from(260u32);
236    /// x.mod_power_of_2_assign(8);
237    /// assert_eq!(x, 4);
238    ///
239    /// // 100 * 2^4 + 11 = 1611
240    /// let mut x = Natural::from(1611u32);
241    /// x.mod_power_of_2_assign(4);
242    /// assert_eq!(x, 11);
243    /// ```
244    fn mod_power_of_2_assign(&mut self, pow: u64) {
245        match &mut *self {
246            Self(Small(small)) => small.mod_power_of_2_assign(pow),
247            Self(Large(limbs)) => {
248                limbs_vec_mod_power_of_2_in_place(limbs, pow);
249                self.trim();
250            }
251        }
252    }
253}
254
255impl RemPowerOf2 for Natural {
256    type Output = Self;
257
258    /// Divides a [`Natural`] by $2^k$, returning just the remainder. The [`Natural`] is taken by
259    /// value.
260    ///
261    /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and
262    /// $0 \leq r < 2^k$.
263    ///
264    /// $$
265    /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
266    /// $$
267    ///
268    /// For [`Natural`]s, `rem_power_of_2` is equivalent to
269    /// [`mod_power_of_2`](ModPowerOf2::mod_power_of_2).
270    ///
271    /// # Worst-case complexity
272    /// Constant time and additional memory.
273    ///
274    /// # Examples
275    /// ```
276    /// use malachite_base::num::arithmetic::traits::RemPowerOf2;
277    /// use malachite_nz::natural::Natural;
278    ///
279    /// // 1 * 2^8 + 4 = 260
280    /// assert_eq!(Natural::from(260u32).rem_power_of_2(8), 4);
281    ///
282    /// // 100 * 2^4 + 11 = 1611
283    /// assert_eq!(Natural::from(1611u32).rem_power_of_2(4), 11);
284    /// ```
285    #[inline]
286    fn rem_power_of_2(self, pow: u64) -> Self {
287        self.mod_power_of_2(pow)
288    }
289}
290
291impl RemPowerOf2 for &Natural {
292    type Output = Natural;
293
294    /// Divides a [`Natural`] by $2^k$, returning just the remainder. The [`Natural`] is taken by
295    /// reference.
296    ///
297    /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and
298    /// $0 \leq r < 2^k$.
299    ///
300    /// $$
301    /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
302    /// $$
303    ///
304    /// For [`Natural`]s, `rem_power_of_2` is equivalent to
305    /// [`mod_power_of_2`](ModPowerOf2::mod_power_of_2).
306    ///
307    /// # Worst-case complexity
308    /// $T(n) = O(n)$
309    ///
310    /// $M(n) = O(n)$
311    ///
312    /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
313    ///
314    /// # Examples
315    /// ```
316    /// use malachite_base::num::arithmetic::traits::RemPowerOf2;
317    /// use malachite_nz::natural::Natural;
318    ///
319    /// // 1 * 2^8 + 4 = 260
320    /// assert_eq!((&Natural::from(260u32)).rem_power_of_2(8), 4);
321    /// // 100 * 2^4 + 11 = 1611
322    /// assert_eq!((&Natural::from(1611u32)).rem_power_of_2(4), 11);
323    /// ```
324    #[inline]
325    fn rem_power_of_2(self, pow: u64) -> Natural {
326        self.mod_power_of_2(pow)
327    }
328}
329
330impl RemPowerOf2Assign for Natural {
331    /// Divides a [`Natural`] by $2^k$, replacing the first [`Natural`] by the remainder.
332    ///
333    /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and
334    /// $0 \leq r < 2^k$.
335    ///
336    /// $$
337    /// x \gets x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
338    /// $$
339    ///
340    /// For [`Natural`]s, `rem_power_of_2_assign` is equivalent to
341    /// [`mod_power_of_2_assign`](ModPowerOf2Assign::mod_power_of_2_assign).
342    ///
343    /// # Worst-case complexity
344    /// Constant time and additional memory.
345    ///
346    /// # Examples
347    /// ```
348    /// use malachite_base::num::arithmetic::traits::RemPowerOf2Assign;
349    /// use malachite_nz::natural::Natural;
350    ///
351    /// // 1 * 2^8 + 4 = 260
352    /// let mut x = Natural::from(260u32);
353    /// x.rem_power_of_2_assign(8);
354    /// assert_eq!(x, 4);
355    ///
356    /// // 100 * 2^4 + 11 = 1611
357    /// let mut x = Natural::from(1611u32);
358    /// x.rem_power_of_2_assign(4);
359    /// assert_eq!(x, 11);
360    /// ```
361    #[inline]
362    fn rem_power_of_2_assign(&mut self, pow: u64) {
363        self.mod_power_of_2_assign(pow);
364    }
365}
366
367impl NegModPowerOf2 for Natural {
368    type Output = Self;
369
370    /// Divides the negative of a [`Natural`] by a $2^k$, returning just the remainder. The
371    /// [`Natural`] is taken by value.
372    ///
373    /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - r$ and
374    /// $0 \leq r < 2^k$.
375    ///
376    /// $$
377    /// f(x, k) = 2^k\left \lceil \frac{x}{2^k} \right \rceil - x.
378    /// $$
379    ///
380    /// # Worst-case complexity
381    /// $T(n) = O(n)$
382    ///
383    /// $M(n) = O(n)$
384    ///
385    /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
386    ///
387    /// # Examples
388    /// ```
389    /// use malachite_base::num::arithmetic::traits::NegModPowerOf2;
390    /// use malachite_nz::natural::Natural;
391    ///
392    /// // 2 * 2^8 - 252 = 260
393    /// assert_eq!(Natural::from(260u32).neg_mod_power_of_2(8), 252);
394    ///
395    /// // 101 * 2^4 - 5 = 1611
396    /// assert_eq!(Natural::from(1611u32).neg_mod_power_of_2(4), 5);
397    /// ```
398    #[inline]
399    fn neg_mod_power_of_2(mut self, pow: u64) -> Self {
400        self.neg_mod_power_of_2_assign(pow);
401        self
402    }
403}
404
405impl NegModPowerOf2 for &Natural {
406    type Output = Natural;
407
408    /// Divides the negative of a [`Natural`] by a $2^k$, returning just the remainder. The
409    /// [`Natural`] is taken by reference.
410    ///
411    /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - r$ and
412    /// $0 \leq r < 2^k$.
413    ///
414    /// $$
415    /// f(x, k) = 2^k\left \lceil \frac{x}{2^k} \right \rceil - x.
416    /// $$
417    ///
418    /// # Worst-case complexity
419    /// $T(n) = O(n)$
420    ///
421    /// $M(n) = O(n)$
422    ///
423    /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
424    ///
425    /// # Examples
426    /// ```
427    /// use malachite_base::num::arithmetic::traits::NegModPowerOf2;
428    /// use malachite_nz::natural::Natural;
429    ///
430    /// // 2 * 2^8 - 252 = 260
431    /// assert_eq!((&Natural::from(260u32)).neg_mod_power_of_2(8), 252);
432    /// // 101 * 2^4 - 5 = 1611
433    /// assert_eq!((&Natural::from(1611u32)).neg_mod_power_of_2(4), 5);
434    /// ```
435    fn neg_mod_power_of_2(self, pow: u64) -> Natural {
436        match (self, pow) {
437            (&Natural::ZERO, _) => Natural::ZERO,
438            (_, pow) if pow <= Limb::WIDTH => {
439                Natural::from(Limb::wrapping_from(self).neg_mod_power_of_2(pow))
440            }
441            (Natural(Small(small)), pow) => {
442                Natural::from_owned_limbs_asc(limbs_neg_mod_power_of_2(&[*small], pow))
443            }
444            (Natural(Large(limbs)), pow) => {
445                Natural::from_owned_limbs_asc(limbs_neg_mod_power_of_2(limbs, pow))
446            }
447        }
448    }
449}
450
451impl NegModPowerOf2Assign for Natural {
452    /// Divides the negative of a [`Natural`] by $2^k$, returning just the remainder.
453    ///
454    /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - r$ and
455    /// $0 \leq r < 2^k$.
456    ///
457    /// $$
458    /// x \gets 2^k\left \lceil \frac{x}{2^k} \right \rceil - x.
459    /// $$
460    ///
461    /// # Worst-case complexity
462    /// $T(n) = O(n)$
463    ///
464    /// $M(n) = O(n)$
465    ///
466    /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
467    ///
468    /// # Examples
469    /// ```
470    /// use malachite_base::num::arithmetic::traits::NegModPowerOf2Assign;
471    /// use malachite_nz::natural::Natural;
472    ///
473    /// // 2 * 2^8 - 252 = 260
474    /// let mut x = Natural::from(260u32);
475    /// x.neg_mod_power_of_2_assign(8);
476    /// assert_eq!(x, 252);
477    ///
478    /// // 101 * 2^4 - 5 = 1611
479    /// let mut x = Natural::from(1611u32);
480    /// x.neg_mod_power_of_2_assign(4);
481    /// assert_eq!(x, 5);
482    /// ```
483    fn neg_mod_power_of_2_assign(&mut self, pow: u64) {
484        if *self == 0 {
485        } else if pow <= Limb::WIDTH {
486            *self = Self::from(Limb::wrapping_from(&*self).neg_mod_power_of_2(pow));
487        } else {
488            let limbs = self.promote_in_place();
489            limbs_neg_mod_power_of_2_in_place(limbs, pow);
490            self.trim();
491        }
492    }
493}