malachite_base/num/arithmetic/
mod_neg.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// Uses code adopted from the FLINT Library.
4//
5//      Copyright © 2010 William Hart
6//
7//      Copyright © 2021 Fredrik Johansson
8//
9// This file is part of Malachite.
10//
11// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
12// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
13// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
14
15use crate::num::arithmetic::traits::{ModNeg, ModNegAssign};
16use crate::num::basic::unsigneds::PrimitiveUnsigned;
17
18fn mod_neg<T: PrimitiveUnsigned>(x: T, m: T) -> T {
19    assert!(x < m, "x must be reduced mod m, but {x} >= {m}");
20    if x == T::ZERO { T::ZERO } else { m - x }
21}
22
23fn mod_neg_assign<T: PrimitiveUnsigned>(x: &mut T, m: T) {
24    assert!(*x < m, "x must be reduced mod m, but {x} >= {m}");
25    if *x != T::ZERO {
26        *x = m - *x;
27    }
28}
29
30macro_rules! impl_mod_neg {
31    ($t:ident) => {
32        impl ModNeg for $t {
33            type Output = $t;
34
35            /// Negates a number modulo another number $m$, in place. The input must be already
36            /// reduced modulo $m$.
37            ///
38            /// $f(x, m) = y$, where $x, y < m$ and $-x \equiv y \mod m$.
39            ///
40            /// # Worst-case complexity
41            /// Constant time and additional memory.
42            ///
43            /// # Examples
44            /// See [here](super::mod_neg#mod_neg).
45            ///
46            /// This is equivalent to `nmod_neg` from `nmod.h`, FLINT 2.7.1.
47            #[inline]
48            fn mod_neg(self, m: $t) -> $t {
49                mod_neg(self, m)
50            }
51        }
52
53        impl ModNegAssign for $t {
54            /// Negates a number modulo another number $m$. The input must be already reduced modulo
55            /// $m$.
56            ///
57            /// $x \gets y$, where $x, y < m$ and $-x \equiv y \mod m$.
58            ///
59            /// # Worst-case complexity
60            /// Constant time and additional memory.
61            ///
62            /// # Examples
63            /// See [here](super::mod_neg#mod_neg_assign).
64            ///
65            /// This is equivalent to `nmod_neg` from `nmod.h`, FLINT 2.7.1, where the output is
66            /// assigned to `a`.
67            #[inline]
68            fn mod_neg_assign(&mut self, m: $t) {
69                mod_neg_assign(self, m)
70            }
71        }
72    };
73}
74apply_to_unsigneds!(impl_mod_neg);