|
@@ -121,9 +121,10 @@ library Math {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
|
|
|
+ * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
|
|
|
* denominator == 0.
|
|
|
- * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
|
|
|
+ *
|
|
|
+ * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
|
|
|
* Uniswap Labs also under MIT license.
|
|
|
*/
|
|
|
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
|
|
@@ -208,7 +209,7 @@ library Math {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
|
|
|
+ * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
|
|
|
*/
|
|
|
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
|
|
|
uint256 result = mulDiv(x, y, denominator);
|
|
@@ -218,6 +219,62 @@ library Math {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
|
|
|
+ *
|
|
|
+ * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, expect 0.
|
|
|
+ * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
|
|
|
+ *
|
|
|
+ * If the input value is not inversible, 0 is returned.
|
|
|
+ */
|
|
|
+ function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
|
|
|
+ unchecked {
|
|
|
+ if (n == 0) return 0;
|
|
|
+
|
|
|
+ // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
|
|
|
+ // Used to compute integers x and y such that: ax + ny = gcd(a, n).
|
|
|
+ // When the gcd is 1, then the inverse of a modulo n exists and it's x.
|
|
|
+ // ax + ny = 1
|
|
|
+ // ax = 1 + (-y)n
|
|
|
+ // ax ≡ 1 (mod n) # x is the inverse of a modulo n
|
|
|
+
|
|
|
+ // If the remainder is 0 the gcd is n right away.
|
|
|
+ uint256 remainder = a % n;
|
|
|
+ uint256 gcd = n;
|
|
|
+
|
|
|
+ // Therefore the initial coefficients are:
|
|
|
+ // ax + ny = gcd(a, n) = n
|
|
|
+ // 0a + 1n = n
|
|
|
+ int256 x = 0;
|
|
|
+ int256 y = 1;
|
|
|
+
|
|
|
+ while (remainder != 0) {
|
|
|
+ uint256 quotient = gcd / remainder;
|
|
|
+
|
|
|
+ (gcd, remainder) = (
|
|
|
+ // The old remainder is the next gcd to try.
|
|
|
+ remainder,
|
|
|
+ // Compute the next remainder.
|
|
|
+ // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
|
|
|
+ // where gcd is at most n (capped to type(uint256).max)
|
|
|
+ gcd - remainder * quotient
|
|
|
+ );
|
|
|
+
|
|
|
+ (x, y) = (
|
|
|
+ // Increment the coefficient of a.
|
|
|
+ y,
|
|
|
+ // Decrement the coefficient of n.
|
|
|
+ // Can overflow, but the result is casted to uint256 so that the
|
|
|
+ // next value of y is "wrapped around" to a value between 0 and n - 1.
|
|
|
+ x - y * int256(quotient)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (gcd != 1) return 0; // No inverse exists.
|
|
|
+ return x < 0 ? (n - uint256(-x)) : uint256(x); // Wrap the result if it's negative.
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
|
|
|
* towards zero.
|
|
@@ -258,7 +315,7 @@ library Math {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @notice Calculates sqrt(a), following the selected rounding direction.
|
|
|
+ * @dev Calculates sqrt(a), following the selected rounding direction.
|
|
|
*/
|
|
|
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
|
|
|
unchecked {
|