malachite_nz/integer/arithmetic/mod_euclidean.rs
1// Copyright © 2026 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::integer::Integer;
10use crate::natural::Natural;
11use malachite_base::num::arithmetic::traits::{
12 Mod, ModAssign, ModEuclidean, ModEuclideanAssign, UnsignedAbs,
13};
14
15impl ModEuclidean<Self> for Integer {
16 type Output = Natural;
17
18 /// Divides an [`Integer`] by another [`Integer`], taking both by value and returning just the
19 /// remainder. The remainder is nonnegative and is returned as a [`Natural`].
20 ///
21 /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0
22 /// \leq r < |y|$.
23 ///
24 /// $$
25 /// f(x, y) = x - y \operatorname{sgn}(y) \left \lfloor \frac{x}{|y|} \right \rfloor.
26 /// $$
27 ///
28 /// # Worst-case complexity
29 /// $T(n) = O(n \log n \log \log n)$
30 ///
31 /// $M(n) = O(n \log n)$
32 ///
33 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
34 ///
35 /// # Panics
36 /// Panics if `other` is zero.
37 ///
38 /// # Examples
39 /// ```
40 /// use malachite_base::num::arithmetic::traits::ModEuclidean;
41 /// use malachite_nz::integer::Integer;
42 ///
43 /// // 2 * 10 + 3 = 23
44 /// assert_eq!(Integer::from(23).mod_euclidean(Integer::from(10)), 3);
45 ///
46 /// // 3 * -10 + 7 = -23
47 /// assert_eq!(Integer::from(-23).mod_euclidean(Integer::from(-10)), 7);
48 /// ```
49 #[inline]
50 fn mod_euclidean(self, other: Self) -> Natural {
51 let r = self.mod_op(&other);
52 if r < 0u32 {
53 (r - other).unsigned_abs()
54 } else {
55 r.unsigned_abs()
56 }
57 }
58}
59
60impl ModEuclidean<&Self> for Integer {
61 type Output = Natural;
62
63 /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by
64 /// reference and returning just the remainder. The remainder is nonnegative and is returned as
65 /// a [`Natural`].
66 ///
67 /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0
68 /// \leq r < |y|$.
69 ///
70 /// $$
71 /// f(x, y) = x - y \operatorname{sgn}(y) \left \lfloor \frac{x}{|y|} \right \rfloor.
72 /// $$
73 ///
74 /// # Worst-case complexity
75 /// $T(n) = O(n \log n \log \log n)$
76 ///
77 /// $M(n) = O(n \log n)$
78 ///
79 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
80 ///
81 /// # Panics
82 /// Panics if `other` is zero.
83 ///
84 /// # Examples
85 /// ```
86 /// use malachite_base::num::arithmetic::traits::ModEuclidean;
87 /// use malachite_nz::integer::Integer;
88 ///
89 /// // -3 * 10 + 7 = -23
90 /// assert_eq!(Integer::from(-23).mod_euclidean(&Integer::from(10)), 7);
91 /// ```
92 #[inline]
93 fn mod_euclidean(self, other: &Self) -> Natural {
94 let r = self.mod_op(other);
95 if r < 0u32 {
96 (r - other).unsigned_abs()
97 } else {
98 r.unsigned_abs()
99 }
100 }
101}
102
103impl ModEuclidean<Integer> for &Integer {
104 type Output = Natural;
105
106 /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second
107 /// by value and returning just the remainder. The remainder is nonnegative and is returned as a
108 /// [`Natural`].
109 ///
110 /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0
111 /// \leq r < |y|$.
112 ///
113 /// $$
114 /// f(x, y) = x - y \operatorname{sgn}(y) \left \lfloor \frac{x}{|y|} \right \rfloor.
115 /// $$
116 ///
117 /// # Worst-case complexity
118 /// $T(n) = O(n \log n \log \log n)$
119 ///
120 /// $M(n) = O(n \log n)$
121 ///
122 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
123 ///
124 /// # Panics
125 /// Panics if `other` is zero.
126 ///
127 /// # Examples
128 /// ```
129 /// use malachite_base::num::arithmetic::traits::ModEuclidean;
130 /// use malachite_nz::integer::Integer;
131 ///
132 /// // -2 * -10 + 3 = 23
133 /// assert_eq!((&Integer::from(23)).mod_euclidean(Integer::from(-10)), 3);
134 /// ```
135 #[inline]
136 fn mod_euclidean(self, other: Integer) -> Natural {
137 let r = self.mod_op(&other);
138 if r < 0u32 {
139 (r - other).unsigned_abs()
140 } else {
141 r.unsigned_abs()
142 }
143 }
144}
145
146impl ModEuclidean<&Integer> for &Integer {
147 type Output = Natural;
148
149 /// Divides an [`Integer`] by another [`Integer`], taking both by reference and returning just
150 /// the remainder. The remainder is nonnegative and is returned as a [`Natural`].
151 ///
152 /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0
153 /// \leq r < |y|$.
154 ///
155 /// $$
156 /// f(x, y) = x - y \operatorname{sgn}(y) \left \lfloor \frac{x}{|y|} \right \rfloor.
157 /// $$
158 ///
159 /// # Worst-case complexity
160 /// $T(n) = O(n \log n \log \log n)$
161 ///
162 /// $M(n) = O(n \log n)$
163 ///
164 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
165 ///
166 /// # Panics
167 /// Panics if `other` is zero.
168 ///
169 /// # Examples
170 /// ```
171 /// use malachite_base::num::arithmetic::traits::ModEuclidean;
172 /// use malachite_nz::integer::Integer;
173 ///
174 /// // 3 * -10 + 7 = -23
175 /// assert_eq!((&Integer::from(-23)).mod_euclidean(&Integer::from(-10)), 7);
176 /// ```
177 #[inline]
178 fn mod_euclidean(self, other: &Integer) -> Natural {
179 let r = self.mod_op(other);
180 if r < 0u32 {
181 (r - other).unsigned_abs()
182 } else {
183 r.unsigned_abs()
184 }
185 }
186}
187
188impl ModEuclideanAssign<Self> for Integer {
189 /// Divides an [`Integer`] by another [`Integer`], taking the [`Integer`] on the right-hand side
190 /// by value and replacing the first [`Integer`] by the remainder. The remainder is nonnegative.
191 ///
192 /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0
193 /// \leq r < |y|$.
194 ///
195 /// $$
196 /// x \gets x - y \operatorname{sgn}(y) \left \lfloor \frac{x}{|y|} \right \rfloor.
197 /// $$
198 ///
199 /// # Worst-case complexity
200 /// $T(n) = O(n \log n \log \log n)$
201 ///
202 /// $M(n) = O(n \log n)$
203 ///
204 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
205 ///
206 /// # Panics
207 /// Panics if `other` is zero.
208 ///
209 /// # Examples
210 /// ```
211 /// use malachite_base::num::arithmetic::traits::ModEuclideanAssign;
212 /// use malachite_nz::integer::Integer;
213 ///
214 /// // -3 * 10 + 7 = -23
215 /// let mut x = Integer::from(-23);
216 /// x.mod_euclidean_assign(Integer::from(10));
217 /// assert_eq!(x, 7);
218 ///
219 /// // 3 * -10 + 7 = -23
220 /// let mut x = Integer::from(-23);
221 /// x.mod_euclidean_assign(Integer::from(-10));
222 /// assert_eq!(x, 7);
223 /// ```
224 #[inline]
225 fn mod_euclidean_assign(&mut self, other: Self) {
226 self.mod_assign(&other);
227 if *self < 0u32 {
228 *self -= other;
229 }
230 }
231}
232
233impl ModEuclideanAssign<&Self> for Integer {
234 /// Divides an [`Integer`] by another [`Integer`], taking the [`Integer`] on the right-hand side
235 /// by reference and replacing the first [`Integer`] by the remainder. The remainder is
236 /// nonnegative.
237 ///
238 /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0
239 /// \leq r < |y|$.
240 ///
241 /// $$
242 /// x \gets x - y \operatorname{sgn}(y) \left \lfloor \frac{x}{|y|} \right \rfloor.
243 /// $$
244 ///
245 /// # Worst-case complexity
246 /// $T(n) = O(n \log n \log \log n)$
247 ///
248 /// $M(n) = O(n \log n)$
249 ///
250 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
251 ///
252 /// # Panics
253 /// Panics if `other` is zero.
254 ///
255 /// # Examples
256 /// ```
257 /// use malachite_base::num::arithmetic::traits::ModEuclideanAssign;
258 /// use malachite_nz::integer::Integer;
259 ///
260 /// // 3 * -10 + 7 = -23
261 /// let mut x = Integer::from(-23);
262 /// x.mod_euclidean_assign(&Integer::from(-10));
263 /// assert_eq!(x, 7);
264 /// ```
265 #[inline]
266 fn mod_euclidean_assign(&mut self, other: &Self) {
267 self.mod_assign(other);
268 if *self < 0u32 {
269 *self -= other;
270 }
271 }
272}