malachite_nz/integer/arithmetic/extended_gcd.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::integer::Integer;
10use crate::natural::Natural;
11use malachite_base::num::arithmetic::traits::{ExtendedGcd, NegAssign, UnsignedAbs};
12
13impl ExtendedGcd for Integer {
14 type Gcd = Natural;
15 type Cofactor = Self;
16
17 /// Computes the GCD (greatest common divisor) of two [`Integer`]s $a$ and $b$, and also the
18 /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. Both [`Integer`]s are
19 /// taken by value.
20 ///
21 /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full
22 /// specification is more detailed:
23 ///
24 /// - $f(0, 0) = (0, 0, 0)$.
25 /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$.
26 /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$.
27 /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$.
28 /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$.
29 /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, |b|)$,
30 /// where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq
31 /// \lfloor a/g \rfloor$.
32 ///
33 /// # Worst-case complexity
34 /// $T(n) = O(n (\log n)^2 \log\log n)$
35 ///
36 /// $M(n) = O(n \log n)$
37 ///
38 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
39 /// other.significant_bits())`.
40 ///
41 /// # Examples
42 /// ```
43 /// use malachite_base::num::arithmetic::traits::ExtendedGcd;
44 /// use malachite_base::strings::ToDebugString;
45 /// use malachite_nz::integer::Integer;
46 ///
47 /// assert_eq!(
48 /// Integer::from(3)
49 /// .extended_gcd(Integer::from(5))
50 /// .to_debug_string(),
51 /// "(1, 2, -1)"
52 /// );
53 /// assert_eq!(
54 /// Integer::from(240)
55 /// .extended_gcd(Integer::from(46))
56 /// .to_debug_string(),
57 /// "(2, -9, 47)"
58 /// );
59 /// assert_eq!(
60 /// Integer::from(-111)
61 /// .extended_gcd(Integer::from(300))
62 /// .to_debug_string(),
63 /// "(3, 27, 10)"
64 /// );
65 /// ```
66 fn extended_gcd(self, other: Self) -> (Natural, Self, Self) {
67 let a_sign = self.sign;
68 let b_sign = other.sign;
69 let (gcd, mut x, mut y) = self.unsigned_abs().extended_gcd(other.unsigned_abs());
70 if !a_sign {
71 x.neg_assign();
72 }
73 if !b_sign {
74 y.neg_assign();
75 }
76 (gcd, x, y)
77 }
78}
79
80impl ExtendedGcd<&Self> for Integer {
81 type Gcd = Natural;
82 type Cofactor = Self;
83
84 /// Computes the GCD (greatest common divisor) of two [`Integer`]s $a$ and $b$, and also the
85 /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. The first [`Integer`] is
86 /// taken by value and the second by reference.
87 ///
88 /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full
89 /// specification is more detailed:
90 ///
91 /// - $f(0, 0) = (0, 0, 0)$.
92 /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$.
93 /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$.
94 /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$.
95 /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$.
96 /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, |b|)$,
97 /// where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq
98 /// \lfloor a/g \rfloor$.
99 ///
100 /// # Worst-case complexity
101 /// $T(n) = O(n (\log n)^2 \log\log n)$
102 ///
103 /// $M(n) = O(n \log n)$
104 ///
105 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
106 /// other.significant_bits())`.
107 ///
108 /// # Examples
109 /// ```
110 /// use malachite_base::num::arithmetic::traits::ExtendedGcd;
111 /// use malachite_base::strings::ToDebugString;
112 /// use malachite_nz::integer::Integer;
113 ///
114 /// assert_eq!(
115 /// Integer::from(3)
116 /// .extended_gcd(&Integer::from(5))
117 /// .to_debug_string(),
118 /// "(1, 2, -1)"
119 /// );
120 /// assert_eq!(
121 /// Integer::from(240)
122 /// .extended_gcd(&Integer::from(46))
123 /// .to_debug_string(),
124 /// "(2, -9, 47)"
125 /// );
126 /// assert_eq!(
127 /// Integer::from(-111)
128 /// .extended_gcd(&Integer::from(300))
129 /// .to_debug_string(),
130 /// "(3, 27, 10)"
131 /// );
132 /// ```
133 fn extended_gcd(self, other: &Self) -> (Natural, Self, Self) {
134 let a_sign = self.sign;
135 let (gcd, mut x, mut y) = self.unsigned_abs().extended_gcd(other.unsigned_abs_ref());
136 if !a_sign {
137 x.neg_assign();
138 }
139 if !other.sign {
140 y.neg_assign();
141 }
142 (gcd, x, y)
143 }
144}
145
146impl ExtendedGcd<Integer> for &Integer {
147 type Gcd = Natural;
148 type Cofactor = Integer;
149
150 /// Computes the GCD (greatest common divisor) of two [`Integer`]s $a$ and $b$, and also the
151 /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. The first [`Integer`] is
152 /// taken by reference and the second by value.
153 ///
154 /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full
155 /// specification is more detailed:
156 ///
157 /// - $f(0, 0) = (0, 0, 0)$.
158 /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$.
159 /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$.
160 /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$.
161 /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$.
162 /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, |b|)$,
163 /// where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq
164 /// \lfloor a/g \rfloor$.
165 ///
166 /// # Worst-case complexity
167 /// $T(n) = O(n (\log n)^2 \log\log n)$
168 ///
169 /// $M(n) = O(n \log n)$
170 ///
171 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
172 /// other.significant_bits())`.
173 ///
174 /// # Examples
175 /// ```
176 /// use malachite_base::num::arithmetic::traits::ExtendedGcd;
177 /// use malachite_base::strings::ToDebugString;
178 /// use malachite_nz::integer::Integer;
179 ///
180 /// assert_eq!(
181 /// (&Integer::from(3))
182 /// .extended_gcd(Integer::from(5))
183 /// .to_debug_string(),
184 /// "(1, 2, -1)"
185 /// );
186 /// assert_eq!(
187 /// (&Integer::from(240))
188 /// .extended_gcd(Integer::from(46))
189 /// .to_debug_string(),
190 /// "(2, -9, 47)"
191 /// );
192 /// assert_eq!(
193 /// (&Integer::from(-111))
194 /// .extended_gcd(Integer::from(300))
195 /// .to_debug_string(),
196 /// "(3, 27, 10)"
197 /// );
198 /// ```
199 fn extended_gcd(self, other: Integer) -> (Natural, Integer, Integer) {
200 let b_sign = other.sign;
201 let (gcd, mut x, mut y) = self.unsigned_abs_ref().extended_gcd(other.unsigned_abs());
202 if !self.sign {
203 x.neg_assign();
204 }
205 if !b_sign {
206 y.neg_assign();
207 }
208 (gcd, x, y)
209 }
210}
211
212impl ExtendedGcd<&Integer> for &Integer {
213 type Gcd = Natural;
214 type Cofactor = Integer;
215
216 /// Computes the GCD (greatest common divisor) of two [`Integer`]s $a$ and $b$, and also the
217 /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. Both [`Integer`]s are
218 /// taken by reference.
219 ///
220 /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full
221 /// specification is more detailed:
222 ///
223 /// - $f(0, 0) = (0, 0, 0)$.
224 /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$.
225 /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$.
226 /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$.
227 /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$.
228 /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, |b|)$,
229 /// where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq
230 /// \lfloor a/g \rfloor$.
231 ///
232 /// # Worst-case complexity
233 /// $T(n) = O(n (\log n)^2 \log\log n)$
234 ///
235 /// $M(n) = O(n \log n)$
236 ///
237 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
238 /// other.significant_bits())`.
239 ///
240 /// # Examples
241 /// ```
242 /// use malachite_base::num::arithmetic::traits::ExtendedGcd;
243 /// use malachite_base::strings::ToDebugString;
244 /// use malachite_nz::integer::Integer;
245 ///
246 /// assert_eq!(
247 /// (&Integer::from(3))
248 /// .extended_gcd(&Integer::from(5))
249 /// .to_debug_string(),
250 /// "(1, 2, -1)"
251 /// );
252 /// assert_eq!(
253 /// (&Integer::from(240))
254 /// .extended_gcd(&Integer::from(46))
255 /// .to_debug_string(),
256 /// "(2, -9, 47)"
257 /// );
258 /// assert_eq!(
259 /// (&Integer::from(-111))
260 /// .extended_gcd(&Integer::from(300))
261 /// .to_debug_string(),
262 /// "(3, 27, 10)"
263 /// );
264 /// ```
265 fn extended_gcd(self, other: &Integer) -> (Natural, Integer, Integer) {
266 let (gcd, mut x, mut y) = self
267 .unsigned_abs_ref()
268 .extended_gcd(other.unsigned_abs_ref());
269 if !self.sign {
270 x.neg_assign();
271 }
272 if !other.sign {
273 y.neg_assign();
274 }
275 (gcd, x, y)
276 }
277}