malachite_nz/natural/arithmetic/mod_inverse.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::natural::InnerNatural::Small;
10use crate::natural::Natural;
11use crate::natural::arithmetic::gcd::extended_gcd::limbs_extended_gcd;
12use crate::natural::arithmetic::sub::limbs_sub_same_length_in_place_right;
13use malachite_base::num::arithmetic::traits::ModInverse;
14use malachite_base::num::basic::traits::One;
15
16fn mod_inverse_helper(x: Natural, m: Natural) -> Option<Natural> {
17 let mut xs = x.into_limbs_asc();
18 let mut ys = m.to_limbs_asc();
19 let len = ys.len();
20 xs.resize(len, 0);
21 let mut gs = vec![0; len];
22 let mut ss = vec![0; len + 1];
23 let (g_len, ss_sign) = limbs_extended_gcd(&mut gs, &mut ss, &mut xs, &mut ys);
24 gs.truncate(g_len);
25 if Natural::from_owned_limbs_asc(gs) != 1u32 {
26 return None;
27 }
28 if !ss_sign {
29 assert_eq!(ss.pop(), Some(0));
30 limbs_sub_same_length_in_place_right(&m.into_limbs_asc(), &mut ss);
31 }
32 Some(Natural::from_owned_limbs_asc(ss))
33}
34
35impl ModInverse for Natural {
36 type Output = Self;
37
38 /// Computes the multiplicative inverse of a [`Natural`] modulo another [`Natural`] $m$. The
39 /// input must be already reduced modulo $m$. Both [`Natural`]s are taken by value.
40 ///
41 /// Returns `None` if $x$ and $m$ are not coprime.
42 ///
43 /// $f(x, m) = y$, where $x, y < m$, $\gcd(x, y) = 1$, and $xy \equiv 1 \mod m$.
44 ///
45 /// # Worst-case complexity
46 /// $T(n) = O(n (\log n)^2 \log\log n)$
47 ///
48 /// $M(n) = O(n \log n)$
49 ///
50 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
51 /// m.significant_bits())`.
52 ///
53 /// # Panics
54 /// Panics if `self` is 0 or if `self` is greater than or equal to `m`.
55 ///
56 /// # Examples
57 /// ```
58 /// use malachite_base::num::arithmetic::traits::ModInverse;
59 /// use malachite_nz::natural::Natural;
60 ///
61 /// assert_eq!(
62 /// Natural::from(3u32).mod_inverse(Natural::from(10u32)),
63 /// Some(Natural::from(7u32))
64 /// );
65 /// assert_eq!(Natural::from(4u32).mod_inverse(Natural::from(10u32)), None);
66 /// ```
67 fn mod_inverse(self, m: Self) -> Option<Self> {
68 assert_ne!(self, 0u32);
69 assert!(self < m, "self must be reduced mod m, but {self} >= {m}");
70 match (self, m) {
71 (x @ Self::ONE, _) => Some(x),
72 (Self(Small(x)), Self(Small(y))) => x.mod_inverse(y).map(Self::from),
73 (a, b) => mod_inverse_helper(a, b),
74 }
75 }
76}
77
78impl<'a> ModInverse<&'a Self> for Natural {
79 type Output = Self;
80
81 /// Computes the multiplicative inverse of a [`Natural`] modulo another [`Natural`] $m$. The
82 /// input must be already reduced modulo $m$. The first [`Natural`] is taken by value and the
83 /// second by reference.
84 ///
85 /// Returns `None` if $x$ and $m$ are not coprime.
86 ///
87 /// $f(x, m) = y$, where $x, y < m$, $\gcd(x, y) = 1$, and $xy \equiv 1 \mod m$.
88 ///
89 /// # Worst-case complexity
90 /// $T(n) = O(n (\log n)^2 \log\log n)$
91 ///
92 /// $M(n) = O(n \log n)$
93 ///
94 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
95 /// m.significant_bits())`.
96 ///
97 /// # Panics
98 /// Panics if `self` is 0 or if `self` is greater than or equal to `m`.
99 ///
100 /// # Examples
101 /// ```
102 /// use malachite_base::num::arithmetic::traits::ModInverse;
103 /// use malachite_nz::natural::Natural;
104 ///
105 /// assert_eq!(
106 /// Natural::from(3u32).mod_inverse(&Natural::from(10u32)),
107 /// Some(Natural::from(7u32))
108 /// );
109 /// assert_eq!(Natural::from(4u32).mod_inverse(&Natural::from(10u32)), None);
110 /// ```
111 fn mod_inverse(self, m: &'a Self) -> Option<Self> {
112 assert_ne!(self, 0u32);
113 assert!(self < *m, "self must be reduced mod m, but {self} >= {m}");
114 match (self, m) {
115 (x @ Self::ONE, _) => Some(x),
116 (Self(Small(x)), Self(Small(y))) => x.mod_inverse(*y).map(Self::from),
117 (a, b) => mod_inverse_helper(a, b.clone()),
118 }
119 }
120}
121
122impl ModInverse<Natural> for &Natural {
123 type Output = Natural;
124
125 /// Computes the multiplicative inverse of a [`Natural`] modulo another [`Natural`] $m$. The
126 /// input must be already reduced modulo $m$. The first [`Natural`]s is taken by reference and
127 /// the second by value.
128 ///
129 /// Returns `None` if $x$ and $m$ are not coprime.
130 ///
131 /// $f(x, m) = y$, where $x, y < m$, $\gcd(x, y) = 1$, and $xy \equiv 1 \mod m$.
132 ///
133 /// # Worst-case complexity
134 /// $T(n) = O(n (\log n)^2 \log\log n)$
135 ///
136 /// $M(n) = O(n \log n)$
137 ///
138 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
139 /// m.significant_bits())`.
140 ///
141 /// # Panics
142 /// Panics if `self` is 0 or if `self` is greater than or equal to `m`.
143 ///
144 /// # Examples
145 /// ```
146 /// use malachite_base::num::arithmetic::traits::ModInverse;
147 /// use malachite_nz::natural::Natural;
148 ///
149 /// assert_eq!(
150 /// (&Natural::from(3u32)).mod_inverse(Natural::from(10u32)),
151 /// Some(Natural::from(7u32))
152 /// );
153 /// assert_eq!(
154 /// (&Natural::from(4u32)).mod_inverse(Natural::from(10u32)),
155 /// None
156 /// );
157 /// ```
158 fn mod_inverse(self, m: Natural) -> Option<Natural> {
159 assert_ne!(*self, 0u32);
160 assert!(*self < m, "self must be reduced mod m, but {self} >= {m}");
161 match (self, m) {
162 (&Natural::ONE, _) => Some(Natural::ONE),
163 (Natural(Small(x)), Natural(Small(y))) => x.mod_inverse(y).map(Natural::from),
164 (a, b) => mod_inverse_helper(a.clone(), b),
165 }
166 }
167}
168
169impl ModInverse<&Natural> for &Natural {
170 type Output = Natural;
171
172 /// Computes the multiplicative inverse of a [`Natural`] modulo another [`Natural`] $m$. The
173 /// input must be already reduced modulo $m$. Both [`Natural`]s are taken by reference.
174 ///
175 /// Returns `None` if $x$ and $m$ are not coprime.
176 ///
177 /// $f(x, m) = y$, where $x, y < m$, $\gcd(x, y) = 1$, and $xy \equiv 1 \mod m$.
178 ///
179 /// # Worst-case complexity
180 /// $T(n) = O(n (\log n)^2 \log\log n)$
181 ///
182 /// $M(n) = O(n \log n)$
183 ///
184 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
185 /// m.significant_bits())`.
186 ///
187 /// # Panics
188 /// Panics if `self` is 0 or if `self` is greater than or equal to `m`.
189 ///
190 /// # Examples
191 /// ```
192 /// use malachite_base::num::arithmetic::traits::ModInverse;
193 /// use malachite_nz::natural::Natural;
194 ///
195 /// assert_eq!(
196 /// (&Natural::from(3u32)).mod_inverse(&Natural::from(10u32)),
197 /// Some(Natural::from(7u32))
198 /// );
199 /// assert_eq!(
200 /// (&Natural::from(4u32)).mod_inverse(&Natural::from(10u32)),
201 /// None
202 /// );
203 /// ```
204 fn mod_inverse(self, m: &Natural) -> Option<Natural> {
205 assert_ne!(*self, 0u32);
206 assert!(self < m, "self must be reduced mod m, but {self} >= {m}");
207 match (self, m) {
208 (&Natural::ONE, _) => Some(Natural::ONE),
209 (Natural(Small(x)), Natural(Small(y))) => x.mod_inverse(*y).map(Natural::from),
210 (a, b) => mod_inverse_helper(a.clone(), b.clone()),
211 }
212 }
213}