1+ // SPDX-License-Identifier: MIT
2+ // OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)
3+ // Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/math/Math.sol
4+
5+
6+ pragma solidity ^ 0.8.0 ;
7+
8+ library Math {
9+
10+ /// @dev division or modulo by zero
11+ uint256 internal constant DIVISION_BY_ZERO = 0x12 ;
12+ /// @dev arithmetic underflow or overflow
13+ uint256 internal constant UNDER_OVERFLOW = 0x11 ;
14+
15+
16+ /**
17+ * @dev Return the 512-bit multiplication of two uint256.
18+ *
19+ * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
20+ */
21+ function mul512 (uint256 a , uint256 b ) internal pure returns (uint256 high , uint256 low ) {
22+ // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
23+ // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
24+ // variables such that product = high * 2²⁵⁶ + low.
25+ /// @solidity memory-safe-assembly
26+ assembly {
27+ let mm := mulmod (a, b, not (0 ))
28+ low := mul (a, b)
29+ high := sub (sub (mm, low), lt (mm, low))
30+ }
31+ }
32+
33+ /**
34+ * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
35+ *
36+ * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
37+ * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
38+ * one branch when needed, making this function more expensive.
39+ */
40+ function ternary (bool condition , uint256 a , uint256 b ) internal pure returns (uint256 ) {
41+ unchecked {
42+ // branchless ternary works because:
43+ // b ^ (a ^ b) == a
44+ // b ^ 0 == b
45+ return b ^ ((a ^ b) * toUint (condition));
46+ }
47+ }
48+
49+ /**
50+ * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
51+ */
52+ function toUint (bool b ) internal pure returns (uint256 u ) {
53+ /// @solidity memory-safe-assembly
54+ assembly {
55+ u := iszero (iszero (b))
56+ }
57+ }
58+
59+ /// @dev Reverts with a panic code. Recommended to use with
60+ /// the internal constants with predefined codes.
61+ function panic (uint256 code ) internal pure {
62+ /// @solidity memory-safe-assembly
63+ assembly {
64+ mstore (0x00 , 0x4e487b71 )
65+ mstore (0x20 , code)
66+ revert (0x1c , 0x24 )
67+ }
68+ }
69+
70+
71+ /**
72+ * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
73+ * denominator == 0.
74+ *
75+ * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
76+ * Uniswap Labs also under MIT license.
77+ */
78+ function mulDiv (uint256 x , uint256 y , uint256 denominator ) internal pure returns (uint256 result ) {
79+ unchecked {
80+ (uint256 high , uint256 low ) = mul512 (x, y);
81+
82+ // Handle non-overflow cases, 256 by 256 division.
83+ if (high == 0 ) {
84+ // Solidity will revert if denominator == 0, unlike the div opcode on its own.
85+ // The surrounding unchecked block does not change this fact.
86+ // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
87+ return low / denominator;
88+ }
89+
90+ // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
91+ if (denominator <= high) {
92+ panic (ternary (denominator == 0 , DIVISION_BY_ZERO, UNDER_OVERFLOW));
93+ }
94+
95+ ///////////////////////////////////////////////
96+ // 512 by 256 division.
97+ ///////////////////////////////////////////////
98+
99+ // Make division exact by subtracting the remainder from [high low].
100+ uint256 remainder;
101+ /// @solidity memory-safe-assembly
102+ assembly {
103+ // Compute remainder using mulmod.
104+ remainder := mulmod (x, y, denominator)
105+
106+ // Subtract 256 bit number from 512 bit number.
107+ high := sub (high, gt (remainder, low))
108+ low := sub (low, remainder)
109+ }
110+
111+ // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
112+ // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
113+
114+ uint256 twos = denominator & (0 - denominator);
115+ /// @solidity memory-safe-assembly
116+ assembly {
117+ // Divide denominator by twos.
118+ denominator := div (denominator, twos)
119+
120+ // Divide [high low] by twos.
121+ low := div (low, twos)
122+
123+ // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
124+ twos := add (div (sub (0 , twos), twos), 1 )
125+ }
126+
127+ // Shift in bits from high into low.
128+ low |= high * twos;
129+
130+ // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
131+ // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
132+ // four bits. That is, denominator * inv ≡ 1 mod 2⁴.
133+ uint256 inverse = (3 * denominator) ^ 2 ;
134+
135+ // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
136+ // works in modular arithmetic, doubling the correct bits in each step.
137+ inverse *= 2 - denominator * inverse; // inverse mod 2⁸
138+ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
139+ inverse *= 2 - denominator * inverse; // inverse mod 2³²
140+ inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
141+ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
142+ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
143+
144+ // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
145+ // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
146+ // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
147+ // is no longer required.
148+ result = low * inverse;
149+ return result;
150+ }
151+ }
152+
153+ // /**
154+ // * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
155+ // */
156+ // function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
157+ // return mulDiv(x, y, denominator) + toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
158+ // }
159+
160+ }
0 commit comments