malachite_nz/gaussian_integer/arithmetic/rem.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::gaussian_integer::GaussianInteger;
10use crate::gaussian_integer::arithmetic::div_rem::{div_rem_ref_ref, div_rem_val_ref};
11use core::mem::take;
12use core::ops::{Rem, RemAssign};
13
14impl Rem<Self> for GaussianInteger {
15 type Output = Self;
16
17 /// Divides a [`GaussianInteger`] by another [`GaussianInteger`], taking both by value, and
18 /// returns the remainder.
19 ///
20 /// The quotient (which is not returned) is the Gaussian integer nearest to the exact quotient,
21 /// with each part rounded to the nearest integer and ties rounded up, and the remainder is what
22 /// is left over. The quotient and remainder satisfy $x = qy + r$ and $N(r) \leq N(y) / 2$,
23 /// where $N$ is the norm. To get both at once, use
24 /// [`div_rem`](malachite_base::num::arithmetic::traits::DivRem::div_rem).
25 ///
26 /// $$
27 /// f(x, y) = x - qy, \quad \text{where } q = \left \lfloor \frac{x \bar{y}}{N(y)} +
28 /// \frac{1 + i}{2} \right \rfloor
29 /// $$
30 /// and the floor is taken on each part.
31 ///
32 /// # Worst-case complexity
33 /// $T(n) = O(n \log n \log\log n)$
34 ///
35 /// $M(n) = O(n \log n)$
36 ///
37 /// where $T$ is time, $M$ is additional memory, and $n$ is the maximum number of significant
38 /// bits of the real and imaginary parts of `self` and `other`.
39 ///
40 /// # Panics
41 /// Panics if `other` is zero.
42 ///
43 /// # Examples
44 /// ```
45 /// use malachite_nz::gaussian_integer::GaussianInteger;
46 /// use std::str::FromStr;
47 ///
48 /// // (2+i)(3) + (-1) = 5+3i
49 /// let x = GaussianInteger::from_str("5+3i").unwrap();
50 /// let y = GaussianInteger::from_str("2+i").unwrap();
51 /// assert_eq!((x % y).to_string(), "-1");
52 /// ```
53 #[inline]
54 fn rem(self, other: Self) -> Self {
55 div_rem_val_ref(self, &other).1
56 }
57}
58
59impl Rem<&Self> for GaussianInteger {
60 type Output = Self;
61
62 /// Divides a [`GaussianInteger`] by another [`GaussianInteger`], taking the first by value and
63 /// the second by reference, and returns the remainder.
64 ///
65 /// The quotient (which is not returned) is the Gaussian integer nearest to the exact quotient,
66 /// with each part rounded to the nearest integer and ties rounded up, and the remainder is what
67 /// is left over. The quotient and remainder satisfy $x = qy + r$ and $N(r) \leq N(y) / 2$,
68 /// where $N$ is the norm. To get both at once, use
69 /// [`div_rem`](malachite_base::num::arithmetic::traits::DivRem::div_rem).
70 ///
71 /// $$
72 /// f(x, y) = x - qy, \quad \text{where } q = \left \lfloor \frac{x \bar{y}}{N(y)} +
73 /// \frac{1 + i}{2} \right \rfloor
74 /// $$
75 /// and the floor is taken on each part.
76 ///
77 /// # Worst-case complexity
78 /// $T(n) = O(n \log n \log\log n)$
79 ///
80 /// $M(n) = O(n \log n)$
81 ///
82 /// where $T$ is time, $M$ is additional memory, and $n$ is the maximum number of significant
83 /// bits of the real and imaginary parts of `self` and `other`.
84 ///
85 /// # Panics
86 /// Panics if `other` is zero.
87 ///
88 /// # Examples
89 /// ```
90 /// use malachite_nz::gaussian_integer::GaussianInteger;
91 /// use std::str::FromStr;
92 ///
93 /// // (2+i)(3) + (-1) = 5+3i
94 /// let x = GaussianInteger::from_str("5+3i").unwrap();
95 /// let y = GaussianInteger::from_str("2+i").unwrap();
96 /// assert_eq!((x % &y).to_string(), "-1");
97 /// ```
98 #[inline]
99 fn rem(self, other: &Self) -> Self {
100 div_rem_val_ref(self, other).1
101 }
102}
103
104impl Rem<GaussianInteger> for &GaussianInteger {
105 type Output = GaussianInteger;
106
107 /// Divides a [`GaussianInteger`] by another [`GaussianInteger`], taking the first by reference
108 /// and the second by value, and returns the remainder.
109 ///
110 /// The quotient (which is not returned) is the Gaussian integer nearest to the exact quotient,
111 /// with each part rounded to the nearest integer and ties rounded up, and the remainder is what
112 /// is left over. The quotient and remainder satisfy $x = qy + r$ and $N(r) \leq N(y) / 2$,
113 /// where $N$ is the norm. To get both at once, use
114 /// [`div_rem`](malachite_base::num::arithmetic::traits::DivRem::div_rem).
115 ///
116 /// $$
117 /// f(x, y) = x - qy, \quad \text{where } q = \left \lfloor \frac{x \bar{y}}{N(y)} +
118 /// \frac{1 + i}{2} \right \rfloor
119 /// $$
120 /// and the floor is taken on each part.
121 ///
122 /// # Worst-case complexity
123 /// $T(n) = O(n \log n \log\log n)$
124 ///
125 /// $M(n) = O(n \log n)$
126 ///
127 /// where $T$ is time, $M$ is additional memory, and $n$ is the maximum number of significant
128 /// bits of the real and imaginary parts of `self` and `other`.
129 ///
130 /// # Panics
131 /// Panics if `other` is zero.
132 ///
133 /// # Examples
134 /// ```
135 /// use malachite_nz::gaussian_integer::GaussianInteger;
136 /// use std::str::FromStr;
137 ///
138 /// // (2+i)(3) + (-1) = 5+3i
139 /// let x = GaussianInteger::from_str("5+3i").unwrap();
140 /// let y = GaussianInteger::from_str("2+i").unwrap();
141 /// assert_eq!((&x % y).to_string(), "-1");
142 /// ```
143 #[inline]
144 fn rem(self, other: GaussianInteger) -> GaussianInteger {
145 div_rem_ref_ref(self, &other).1
146 }
147}
148
149impl Rem<&GaussianInteger> for &GaussianInteger {
150 type Output = GaussianInteger;
151
152 /// Divides a [`GaussianInteger`] by another [`GaussianInteger`], taking both by reference, and
153 /// returns the remainder.
154 ///
155 /// The quotient (which is not returned) is the Gaussian integer nearest to the exact quotient,
156 /// with each part rounded to the nearest integer and ties rounded up, and the remainder is what
157 /// is left over. The quotient and remainder satisfy $x = qy + r$ and $N(r) \leq N(y) / 2$,
158 /// where $N$ is the norm. To get both at once, use
159 /// [`div_rem`](malachite_base::num::arithmetic::traits::DivRem::div_rem).
160 ///
161 /// $$
162 /// f(x, y) = x - qy, \quad \text{where } q = \left \lfloor \frac{x \bar{y}}{N(y)} +
163 /// \frac{1 + i}{2} \right \rfloor
164 /// $$
165 /// and the floor is taken on each part.
166 ///
167 /// # Worst-case complexity
168 /// $T(n) = O(n \log n \log\log n)$
169 ///
170 /// $M(n) = O(n \log n)$
171 ///
172 /// where $T$ is time, $M$ is additional memory, and $n$ is the maximum number of significant
173 /// bits of the real and imaginary parts of `self` and `other`.
174 ///
175 /// # Panics
176 /// Panics if `other` is zero.
177 ///
178 /// # Examples
179 /// ```
180 /// use malachite_nz::gaussian_integer::GaussianInteger;
181 /// use std::str::FromStr;
182 ///
183 /// // (2+i)(3) + (-1) = 5+3i
184 /// let x = GaussianInteger::from_str("5+3i").unwrap();
185 /// let y = GaussianInteger::from_str("2+i").unwrap();
186 /// assert_eq!((&x % &y).to_string(), "-1");
187 /// ```
188 #[inline]
189 fn rem(self, other: &GaussianInteger) -> GaussianInteger {
190 div_rem_ref_ref(self, other).1
191 }
192}
193
194impl RemAssign<Self> for GaussianInteger {
195 /// Divides a [`GaussianInteger`] by another [`GaussianInteger`] in place, taking the
196 /// [`GaussianInteger`] on the right-hand side by value and replacing the first
197 /// [`GaussianInteger`] with the remainder.
198 ///
199 /// The quotient (which is not returned) is the Gaussian integer nearest to the exact quotient,
200 /// with each part rounded to the nearest integer and ties rounded up, and the remainder is what
201 /// is left over. The quotient and remainder satisfy $x = qy + r$ and $N(r) \leq N(y) / 2$,
202 /// where $N$ is the norm. To get both at once, use
203 /// [`div_rem`](malachite_base::num::arithmetic::traits::DivRem::div_rem).
204 ///
205 /// $$
206 /// x \gets x - qy, \quad \text{where } q = \left \lfloor \frac{x \bar{y}}{N(y)} +
207 /// \frac{1 + i}{2} \right \rfloor
208 /// $$
209 /// and the floor is taken on each part.
210 ///
211 /// # Worst-case complexity
212 /// $T(n) = O(n \log n \log\log n)$
213 ///
214 /// $M(n) = O(n \log n)$
215 ///
216 /// where $T$ is time, $M$ is additional memory, and $n$ is the maximum number of significant
217 /// bits of the real and imaginary parts of `self` and `other`.
218 ///
219 /// # Panics
220 /// Panics if `other` is zero.
221 ///
222 /// # Examples
223 /// ```
224 /// use malachite_nz::gaussian_integer::GaussianInteger;
225 /// use std::str::FromStr;
226 ///
227 /// // (2+i)(3) + (-1) = 5+3i
228 /// let mut x = GaussianInteger::from_str("5+3i").unwrap();
229 /// x %= GaussianInteger::from_str("2+i").unwrap();
230 /// assert_eq!(x.to_string(), "-1");
231 /// ```
232 #[inline]
233 fn rem_assign(&mut self, other: Self) {
234 *self = div_rem_val_ref(take(self), &other).1;
235 }
236}
237
238impl RemAssign<&Self> for GaussianInteger {
239 /// Divides a [`GaussianInteger`] by another [`GaussianInteger`] in place, taking the
240 /// [`GaussianInteger`] on the right-hand side by reference and replacing the first
241 /// [`GaussianInteger`] with the remainder.
242 ///
243 /// The quotient (which is not returned) is the Gaussian integer nearest to the exact quotient,
244 /// with each part rounded to the nearest integer and ties rounded up, and the remainder is what
245 /// is left over. The quotient and remainder satisfy $x = qy + r$ and $N(r) \leq N(y) / 2$,
246 /// where $N$ is the norm. To get both at once, use
247 /// [`div_rem`](malachite_base::num::arithmetic::traits::DivRem::div_rem).
248 ///
249 /// $$
250 /// x \gets x - qy, \quad \text{where } q = \left \lfloor \frac{x \bar{y}}{N(y)} +
251 /// \frac{1 + i}{2} \right \rfloor
252 /// $$
253 /// and the floor is taken on each part.
254 ///
255 /// # Worst-case complexity
256 /// $T(n) = O(n \log n \log\log n)$
257 ///
258 /// $M(n) = O(n \log n)$
259 ///
260 /// where $T$ is time, $M$ is additional memory, and $n$ is the maximum number of significant
261 /// bits of the real and imaginary parts of `self` and `other`.
262 ///
263 /// # Panics
264 /// Panics if `other` is zero.
265 ///
266 /// # Examples
267 /// ```
268 /// use malachite_nz::gaussian_integer::GaussianInteger;
269 /// use std::str::FromStr;
270 ///
271 /// // (2+i)(3) + (-1) = 5+3i
272 /// let mut x = GaussianInteger::from_str("5+3i").unwrap();
273 /// x %= &GaussianInteger::from_str("2+i").unwrap();
274 /// assert_eq!(x.to_string(), "-1");
275 /// ```
276 #[inline]
277 fn rem_assign(&mut self, other: &Self) {
278 *self = div_rem_val_ref(take(self), other).1;
279 }
280}