add 512bits add and mult operations

pull/5035/merge^2
Hadrien Croubois 9 months ago
parent 52c36d412e
commit cc807105a4
No known key found for this signature in database
GPG Key ID: B53810561A746A06
  1. 39
      contracts/utils/math/Math.sol

@ -17,6 +17,35 @@ library Math {
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2² + low.
*/
function addFull(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
unchecked {
low = a + b;
high = SafeCast.toUint(low < a);
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2² + low.
*/
function mulFull(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// Compute the product mod 2² and mod 2² - 1, then use use the Chinese Remainder Theorem to reconstruct
// the 512 bit result.
unchecked {
low = a * b;
assembly {
let mm := mulmod(a, b, not(0))
high := sub(sub(mm, low), lt(mm, low))
}
}
}
/**
* @dev Returns the addition of two unsigned integers, with an success flag (no overflow).
*/
@ -143,15 +172,7 @@ library Math {
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2² and mod 2² - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2² + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
(uint256 prod1, uint256 prod0) = mulFull(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {

Loading…
Cancel
Save