@@ -121,9 +121,10 @@ library Math {
121121 }
122122
123123 /**
124- * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
124+ * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
125125 * denominator == 0.
126- * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
126+ *
127+ * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
127128 * Uniswap Labs also under MIT license.
128129 */
129130 function mulDiv (uint256 x , uint256 y , uint256 denominator ) internal pure returns (uint256 result ) {
@@ -208,7 +209,7 @@ library Math {
208209 }
209210
210211 /**
211- * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
212+ * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
212213 */
213214 function mulDiv (uint256 x , uint256 y , uint256 denominator , Rounding rounding ) internal pure returns (uint256 ) {
214215 uint256 result = mulDiv (x, y, denominator);
@@ -218,6 +219,62 @@ library Math {
218219 return result;
219220 }
220221
222+ /**
223+ * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
224+ *
225+ * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, expect 0.
226+ * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
227+ *
228+ * If the input value is not inversible, 0 is returned.
229+ */
230+ function invMod (uint256 a , uint256 n ) internal pure returns (uint256 ) {
231+ unchecked {
232+ if (n == 0 ) return 0 ;
233+
234+ // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
235+ // Used to compute integers x and y such that: ax + ny = gcd(a, n).
236+ // When the gcd is 1, then the inverse of a modulo n exists and it's x.
237+ // ax + ny = 1
238+ // ax = 1 + (-y)n
239+ // ax ≡ 1 (mod n) # x is the inverse of a modulo n
240+
241+ // If the remainder is 0 the gcd is n right away.
242+ uint256 remainder = a % n;
243+ uint256 gcd = n;
244+
245+ // Therefore the initial coefficients are:
246+ // ax + ny = gcd(a, n) = n
247+ // 0a + 1n = n
248+ int256 x = 0 ;
249+ int256 y = 1 ;
250+
251+ while (remainder != 0 ) {
252+ uint256 quotient = gcd / remainder;
253+
254+ (gcd, remainder) = (
255+ // The old remainder is the next gcd to try.
256+ remainder,
257+ // Compute the next remainder.
258+ // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
259+ // where gcd is at most n (capped to type(uint256).max)
260+ gcd - remainder * quotient
261+ );
262+
263+ (x, y) = (
264+ // Increment the coefficient of a.
265+ y,
266+ // Decrement the coefficient of n.
267+ // Can overflow, but the result is casted to uint256 so that the
268+ // next value of y is "wrapped around" to a value between 0 and n - 1.
269+ x - y * int256 (quotient)
270+ );
271+ }
272+
273+ if (gcd != 1 ) return 0 ; // No inverse exists.
274+ return x < 0 ? (n - uint256 (- x)) : uint256 (x); // Wrap the result if it's negative.
275+ }
276+ }
277+
221278 /**
222279 * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
223280 * towards zero.
@@ -258,7 +315,7 @@ library Math {
258315 }
259316
260317 /**
261- * @notice Calculates sqrt(a), following the selected rounding direction.
318+ * @dev Calculates sqrt(a), following the selected rounding direction.
262319 */
263320 function sqrt (uint256 a , Rounding rounding ) internal pure returns (uint256 ) {
264321 unchecked {
0 commit comments