Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@rainlanguage/float",
"description": "Rainlanguage rust Float library in JS/TS through wasm bindgen",
"version": "0.0.0-alpha.13",
"version": "0.0.0-alpha.14",
"license": "LicenseRef-DCL-1.0",
"author": "Rain Open Source Software Ltd",
"repository": {
Expand Down
89 changes: 65 additions & 24 deletions src/lib/implementation/LibDecimalFloatImplementation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,35 +106,76 @@ library LibDecimalFloatImplementation {
returns (int256, int256)
{
unchecked {
// Unchecked mul the coefficients and add the exponents.
int256 signedCoefficient = signedCoefficientA * signedCoefficientB;

// Need to return early if the result is zero to avoid divide by
// zero in the overflow check.
if (signedCoefficient == 0) {
return (NORMALIZED_ZERO_SIGNED_COEFFICIENT, NORMALIZED_ZERO_EXPONENT);
// mulDiv only works with unsigned integers, so get the aboslute
// values of the coefficients.
uint256 signedCoefficientAAbs;
if (signedCoefficientA < 0) {
if (signedCoefficientA == type(int256).min) {
signedCoefficientAAbs = uint256(type(int256).max) + 1;
} else {
signedCoefficientAAbs = uint256(-signedCoefficientA);
}
} else {
signedCoefficientAAbs = uint256(signedCoefficientA);
}
uint256 signedCoefficientBAbs;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
if (signedCoefficientB < 0) {
if (signedCoefficientB == type(int256).min) {
signedCoefficientBAbs = uint256(type(int256).max) + 1;
} else {
signedCoefficientBAbs = uint256(-signedCoefficientB);
}
} else {
signedCoefficientBAbs = uint256(signedCoefficientB);
}

int256 exponent = exponentA + exponentB;

// No jumps to see if we overflowed.
bool didOverflow;
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 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^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly ("memory-safe") {
didOverflow :=
or(
iszero(eq(sdiv(signedCoefficient, signedCoefficientA), signedCoefficientB)),
iszero(eq(sub(exponent, exponentA), exponentB))
)
let mm := mulmod(signedCoefficientA, signedCoefficientB, not(0))
prod0 := mul(signedCoefficientA, signedCoefficientB)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// If we did overflow, normalize and try again. Normalized values
// cannot overflow, so this will always succeed, provided the
// exponents are not out of bounds.
if (didOverflow) {
(signedCoefficientA, exponentA) = normalize(signedCoefficientA, exponentA);
(signedCoefficientB, exponentB) = normalize(signedCoefficientB, exponentB);
return mul(signedCoefficientA, exponentA, signedCoefficientB, exponentB);

// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
unchecked {
return (prod0 * denominator, 0);
}
}
Comment thread
thedavidmeister marked this conversation as resolved.
return (signedCoefficient, exponent);

// // Unchecked mul the coefficients and add the exponents.
// int256 signedCoefficient = signedCoefficientA * signedCoefficientB;

// // Need to return early if the result is zero to avoid divide by
// // zero in the overflow check.
// if (signedCoefficient == 0) {
// return (NORMALIZED_ZERO_SIGNED_COEFFICIENT, NORMALIZED_ZERO_EXPONENT);
// }

// int256 exponent = exponentA + exponentB;

// // No jumps to see if we overflowed.
// bool didOverflow;
// assembly ("memory-safe") {
// didOverflow :=
// or(
// iszero(eq(sdiv(signedCoefficient, signedCoefficientA), signedCoefficientB)),
// iszero(eq(sub(exponent, exponentA), exponentB))
// )
// }
// // If we did overflow, normalize and try again. Normalized values
// // cannot overflow, so this will always succeed, provided the
// // exponents are not out of bounds.
// if (didOverflow) {
// (signedCoefficientA, exponentA) = normalize(signedCoefficientA, exponentA);
// (signedCoefficientB, exponentB) = normalize(signedCoefficientB, exponentB);
// return mul(signedCoefficientA, exponentA, signedCoefficientB, exponentB);
// }
// return (signedCoefficient, exponent);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

Expand Down
Loading