Skip to main content

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}