malachite_base/num/arithmetic/
mod_sub.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::{ModSub, ModSubAssign};
16use crate::num::basic::unsigneds::PrimitiveUnsigned;
17
18fn mod_sub<T: PrimitiveUnsigned>(x: T, y: T, m: T) -> T {
19    assert!(x < m, "x must be reduced mod m, but {x} >= {m}");
20    assert!(y < m, "y must be reduced mod m, but {y} >= {m}");
21    let diff = x.wrapping_sub(y);
22    if x < y { m.wrapping_add(diff) } else { diff }
23}
24
25macro_rules! impl_mod_sub {
26    ($t:ident) => {
27        impl ModSub<$t> for $t {
28            type Output = $t;
29
30            /// Subtracts two numbers modulo a third number $m$. The inputs must be already reduced
31            /// modulo $m$.
32            ///
33            /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$.
34            ///
35            /// # Worst-case complexity
36            /// Constant time and additional memory.
37            ///
38            /// # Panics
39            /// Panics if `self` or `other` are greater than or equal to `m`.
40            ///
41            /// # Examples
42            /// See [here](super::mod_sub#mod_sub).
43            ///
44            /// This is equivalent to `nmod_sub` from `nmod.h`, FLINT 2.7.1.
45            #[inline]
46            fn mod_sub(self, other: $t, m: $t) -> $t {
47                mod_sub(self, other, m)
48            }
49        }
50
51        impl ModSubAssign<$t> for $t {
52            /// Subtracts two numbers modulo a third number $m$, in place. The inputs must be
53            /// already reduced modulo $m$.
54            ///
55            /// $x \gets z$, where $x, y, z < m$ and $x - y \equiv z \mod m$.
56            ///
57            /// # Worst-case complexity
58            /// Constant time and additional memory.
59            ///
60            /// # Panics
61            /// Panics if `self` or `other` are greater than or equal to `m`.
62            ///
63            /// # Examples
64            /// See [here](super::mod_sub#mod_sub_assign).
65            ///
66            /// This is equivalent to `nmod_sub` from `nmod.h`, FLINT 2.7.1, where the result is
67            /// assigned to `a`.
68            #[inline]
69            fn mod_sub_assign(&mut self, other: $t, m: $t) {
70                *self = self.mod_sub(other, m);
71            }
72        }
73    };
74}
75apply_to_unsigneds!(impl_mod_sub);