malachite_base/num/arithmetic/
mod_power_of_2_neg.rs

1// Copyright © 2025 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::num::arithmetic::traits::{ModPowerOf2Neg, ModPowerOf2NegAssign};
10use crate::num::basic::unsigneds::PrimitiveUnsigned;
11
12fn mod_power_of_2_neg<T: PrimitiveUnsigned>(x: T, pow: u64) -> T {
13    assert!(pow <= T::WIDTH);
14    assert!(
15        x.significant_bits() <= pow,
16        "x must be reduced mod 2^pow, but {x} >= 2^{pow}"
17    );
18    x.wrapping_neg().mod_power_of_2(pow)
19}
20
21fn mod_power_of_2_neg_assign<T: PrimitiveUnsigned>(x: &mut T, pow: u64) {
22    assert!(pow <= T::WIDTH);
23    assert!(
24        x.significant_bits() <= pow,
25        "x must be reduced mod 2^pow, but {x} >= 2^{pow}"
26    );
27    x.wrapping_neg_assign();
28    x.mod_power_of_2_assign(pow);
29}
30
31macro_rules! impl_mod_power_of_2_neg {
32    ($t:ident) => {
33        impl ModPowerOf2Neg for $t {
34            type Output = $t;
35
36            /// Negates a number modulo another number $2^k$. The input must be already reduced
37            /// modulo $2^k$.
38            ///
39            /// $f(x, k) = y$, where $x, y < 2^k$ and $-x \equiv y \mod 2^k$.
40            ///
41            /// # Worst-case complexity
42            /// Constant time and additional memory.
43            ///
44            /// # Panics
45            /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than or equal
46            /// to $2^k$.
47            ///
48            /// # Examples
49            /// See [here](super::mod_power_of_2_neg#mod_power_of_2_neg).
50            #[inline]
51            fn mod_power_of_2_neg(self, pow: u64) -> $t {
52                mod_power_of_2_neg(self, pow)
53            }
54        }
55
56        impl ModPowerOf2NegAssign for $t {
57            /// Negates a number modulo another number $2^k$, in place. The input must be already
58            /// reduced modulo $2^k$.
59            ///
60            /// $x \gets y$, where $x, y < 2^k$ and $-x \equiv y \mod 2^k$.
61            ///
62            /// # Worst-case complexity
63            /// Constant time and additional memory.
64            ///
65            /// # Panics
66            /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than or equal
67            /// to $2^k$.
68            ///
69            /// # Examples
70            /// See [here](super::mod_power_of_2_neg#mod_power_of_2_neg_assign).
71            #[inline]
72            fn mod_power_of_2_neg_assign(&mut self, pow: u64) {
73                mod_power_of_2_neg_assign(self, pow);
74            }
75        }
76    };
77}
78apply_to_unsigneds!(impl_mod_power_of_2_neg);