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}