malachite_base/num/arithmetic/
mod_op.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::{
10    CeilingMod, CeilingModAssign, Mod, ModAssign, NegMod, NegModAssign, UnsignedAbs,
11};
12use crate::num::basic::signeds::PrimitiveSigned;
13use crate::num::basic::unsigneds::PrimitiveUnsigned;
14use crate::num::conversion::traits::ExactFrom;
15
16fn neg_mod_unsigned<T: PrimitiveUnsigned>(x: T, other: T) -> T {
17    let remainder = x % other;
18    if remainder == T::ZERO {
19        T::ZERO
20    } else {
21        other - remainder
22    }
23}
24
25fn neg_mod_assign_unsigned<T: PrimitiveUnsigned>(x: &mut T, other: T) {
26    *x %= other;
27    if *x != T::ZERO {
28        *x = other - *x;
29    }
30}
31
32macro_rules! impl_mod_unsigned {
33    ($t:ident) => {
34        impl Mod<$t> for $t {
35            type Output = $t;
36
37            /// Divides a number by another number, returning just the remainder.
38            ///
39            /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$
40            /// and $0 \leq r < y$.
41            ///
42            /// $$
43            /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor.
44            /// $$
45            ///
46            /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword.
47            ///
48            /// # Worst-case complexity
49            /// Constant time and additional memory.
50            ///
51            /// # Panics
52            /// Panics if `other` is 0.
53            ///
54            /// # Examples
55            /// See [here](super::mod_op#mod_op).
56            #[inline]
57            fn mod_op(self, other: $t) -> $t {
58                self % other
59            }
60        }
61
62        impl ModAssign<$t> for $t {
63            /// Divides a number by another number, replacing the first number by the remainder.
64            ///
65            /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$
66            /// and $0 \leq r < y$.
67            ///
68            /// $$
69            /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor.
70            /// $$
71            ///
72            /// # Worst-case complexity
73            /// Constant time and additional memory.
74            ///
75            /// # Panics
76            /// Panics if `other` is 0.
77            ///
78            /// # Examples
79            /// See [here](super::mod_op#mod_assign).
80            #[inline]
81            fn mod_assign(&mut self, other: $t) {
82                *self %= other;
83            }
84        }
85
86        impl NegMod<$t> for $t {
87            type Output = $t;
88
89            /// Divides the negative of a number by another number, returning just the remainder.
90            ///
91            /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$
92            /// and $0 \leq r < y$.
93            ///
94            /// $$
95            /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x.
96            /// $$
97            ///
98            /// # Worst-case complexity
99            /// Constant time and additional memory.
100            ///
101            /// # Panics
102            /// Panics if `other` is 0.
103            ///
104            /// # Examples
105            /// See [here](super::mod_op#neg_mod).
106            #[inline]
107            fn neg_mod(self, other: $t) -> $t {
108                neg_mod_unsigned(self, other)
109            }
110        }
111
112        impl NegModAssign<$t> for $t {
113            /// Divides the negative of a number by another number, returning just the remainder.
114            ///
115            /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$
116            /// and $0 \leq r < y$.
117            ///
118            /// $$
119            /// x \gets y\left \lceil \frac{x}{y} \right \rceil - x.
120            /// $$
121            ///
122            /// # Worst-case complexity
123            /// Constant time and additional memory.
124            ///
125            /// # Panics
126            /// Panics if `other` is 0.
127            ///
128            /// # Examples
129            /// See [here](super::mod_op#neg_mod_assign).
130            #[inline]
131            fn neg_mod_assign(&mut self, other: $t) {
132                neg_mod_assign_unsigned(self, other);
133            }
134        }
135    };
136}
137apply_to_unsigneds!(impl_mod_unsigned);
138
139fn mod_op_signed<
140    U: PrimitiveUnsigned,
141    S: ExactFrom<U> + PrimitiveSigned + UnsignedAbs<Output = U>,
142>(
143    x: S,
144    other: S,
145) -> S {
146    let remainder = if (x >= S::ZERO) == (other >= S::ZERO) {
147        x.unsigned_abs() % other.unsigned_abs()
148    } else {
149        x.unsigned_abs().neg_mod(other.unsigned_abs())
150    };
151    if other >= S::ZERO {
152        S::exact_from(remainder)
153    } else {
154        -S::exact_from(remainder)
155    }
156}
157
158fn ceiling_mod_signed<
159    U: PrimitiveUnsigned,
160    S: ExactFrom<U> + PrimitiveSigned + UnsignedAbs<Output = U>,
161>(
162    x: S,
163    other: S,
164) -> S {
165    let remainder = if (x >= S::ZERO) == (other >= S::ZERO) {
166        x.unsigned_abs().neg_mod(other.unsigned_abs())
167    } else {
168        x.unsigned_abs() % other.unsigned_abs()
169    };
170    if other >= S::ZERO {
171        -S::exact_from(remainder)
172    } else {
173        S::exact_from(remainder)
174    }
175}
176
177macro_rules! impl_mod_signed {
178    ($t:ident) => {
179        impl Mod<$t> for $t {
180            type Output = $t;
181
182            /// Divides a number by another number, returning just the remainder. The remainder has
183            /// the same sign as the second number.
184            ///
185            /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$
186            /// and $0 \leq |r| < |y|$.
187            ///
188            /// $$
189            /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor.
190            /// $$
191            ///
192            /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword.
193            ///
194            /// # Worst-case complexity
195            /// Constant time and additional memory.
196            ///
197            /// # Panics
198            /// Panics if `other` is 0.
199            ///
200            /// # Examples
201            /// See [here](super::mod_op#mod_op).
202            #[inline]
203            fn mod_op(self, other: $t) -> $t {
204                mod_op_signed(self, other)
205            }
206        }
207
208        impl ModAssign<$t> for $t {
209            /// Divides a number by another number, replacing the first number by the remainder. The
210            /// remainder has the same sign as the second number.
211            ///
212            /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$
213            /// and $0 \leq |r| < |y|$.
214            ///
215            /// $$
216            /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor.
217            /// $$
218            ///
219            /// # Worst-case complexity
220            /// Constant time and additional memory.
221            ///
222            /// # Panics
223            /// Panics if `other` is 0.
224            ///
225            /// # Examples
226            /// See [here](super::mod_op#mod_assign).
227            #[inline]
228            fn mod_assign(&mut self, other: $t) {
229                *self = self.mod_op(other);
230            }
231        }
232
233        impl CeilingMod<$t> for $t {
234            type Output = $t;
235
236            /// Divides a number by another number, returning just the remainder. The remainder has
237            /// the opposite sign as the second number.
238            ///
239            /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$
240            /// and $0 \leq |r| < |y|$.
241            ///
242            /// $$
243            /// f(x, y) =  x - y\left \lceil \frac{x}{y} \right \rceil.
244            /// $$
245            ///
246            /// # Worst-case complexity
247            /// Constant time and additional memory.
248            ///
249            /// # Panics
250            /// Panics if `other` is 0.
251            ///
252            /// # Examples
253            /// See [here](super::mod_op#ceiling_mod).
254            #[inline]
255            fn ceiling_mod(self, other: $t) -> $t {
256                ceiling_mod_signed(self, other)
257            }
258        }
259
260        impl CeilingModAssign<$t> for $t {
261            /// Divides a number by another number, replacing the first number by the remainder. The
262            /// remainder has the opposite sign as the second number.
263            ///
264            /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$
265            /// and $0 \leq |r| < |y|$.
266            ///
267            /// $$
268            /// x \gets x - y\left \lceil\frac{x}{y} \right \rceil.
269            /// $$
270            ///
271            /// # Worst-case complexity
272            /// Constant time and additional memory.
273            ///
274            /// # Panics
275            /// Panics if `other` is 0.
276            ///
277            /// # Examples
278            /// See [here](super::mod_op#ceiling_mod_assign).
279            #[inline]
280            fn ceiling_mod_assign(&mut self, other: $t) {
281                *self = self.ceiling_mod(other);
282            }
283        }
284    };
285}
286apply_to_signeds!(impl_mod_signed);