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);