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}