-
Notifications
You must be signed in to change notification settings - Fork 2
2025 09 03 int #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2025 09 03 int #400
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,10 @@ import {LibOpDiv} from "src/lib/op/math/LibOpDiv.sol"; | |
| import {LibOperand} from "test/lib/operand/LibOperand.sol"; | ||
| import {StackItem} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol"; | ||
| import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; | ||
| import {LibDecimalFloatImplementation} from "rain.math.float/lib/implementation/LibDecimalFloatImplementation.sol"; | ||
| import { | ||
| LibDecimalFloatImplementation, | ||
| MulDivOverflow | ||
| } from "rain.math.float/lib/implementation/LibDecimalFloatImplementation.sol"; | ||
|
|
||
| contract LibOpDivTest is OpTest { | ||
| using LibDecimalFloat for Float; | ||
|
|
@@ -112,63 +115,91 @@ contract LibOpDivTest is OpTest { | |
| /// Tests two inputs. | ||
| /// Tests the happy path where we do not divide by zero or overflow. | ||
| function testOpDivEvalTwoInputsHappy() external view { | ||
| checkHappy("_: div(0 1);", Float.unwrap(LibDecimalFloat.packLossless(0, -1)), "0 1"); | ||
| checkHappy("_: div(1 1);", Float.unwrap(LibDecimalFloat.packLossless(1e38, -38)), "1 1"); | ||
| checkHappy("_: div(1 2);", Float.unwrap(LibDecimalFloat.packLossless(5e37, -38)), "1 2"); | ||
| checkHappy("_: div(2 1);", Float.unwrap(LibDecimalFloat.packLossless(2e38, -38)), "2 1"); | ||
| checkHappy("_: div(2 2);", Float.unwrap(LibDecimalFloat.packLossless(1e38, -38)), "2 2"); | ||
| checkHappy("_: div(2 0.1);", Float.unwrap(LibDecimalFloat.packLossless(2e38, -37)), "2 0.1"); | ||
| // https://github.com/rainlanguage/rain.math.float/issues/71 | ||
| // checkHappy("_: div(max-positive-value() 1);", Float.unwrap(LibDecimalFloat.packLossless(1, 1)), "max-positive-value() 1"); | ||
| checkHappy("_: div(0 1);", Float.unwrap(LibDecimalFloat.packLossless(0, 0)), "0 1"); | ||
| checkHappy("_: div(1 1);", Float.unwrap(LibDecimalFloat.packLossless(1e67, -67)), "1 1"); | ||
| checkHappy("_: div(1 2);", Float.unwrap(LibDecimalFloat.packLossless(0.5e67, -67)), "1 2"); | ||
| checkHappy("_: div(2 1);", Float.unwrap(LibDecimalFloat.packLossless(2e66, -66)), "2 1"); | ||
| checkHappy("_: div(2 2);", Float.unwrap(LibDecimalFloat.packLossless(1e67, -67)), "2 2"); | ||
| checkHappy("_: div(2 0.1);", Float.unwrap(LibDecimalFloat.packLossless(20e65, -65)), "2 0.1"); | ||
| checkHappy( | ||
| "_: div(max-positive-value() 1);", | ||
| Float.unwrap(LibDecimalFloat.FLOAT_MAX_POSITIVE_VALUE), | ||
| "max-positive-value() 1" | ||
| ); | ||
| } | ||
|
|
||
| /// Test the eval of `div` opcode parsed from a string. | ||
| /// Tests two inputs. | ||
| /// Tests the unhappy path where we divide by zero. | ||
| function testOpDivEvalTwoInputsUnhappy() external { | ||
| function testOpDivEvalTwoInputsUnhappyDivZero() external { | ||
| checkUnhappy("_: div(0 0);", stdError.divisionError); | ||
| checkUnhappy("_: div(1 0);", stdError.divisionError); | ||
| checkUnhappy("_: div(max-positive-value() 0);", stdError.divisionError); | ||
| checkUnhappy("_: div(1 0);", abi.encodeWithSelector(MulDivOverflow.selector, 1e76, 1e75, 0)); | ||
| checkUnhappy( | ||
| "_: div(max-positive-value() 0);", | ||
| abi.encodeWithSelector( | ||
| MulDivOverflow.selector, | ||
| 13479973333575319897333507543509815336818572211270286240551805124607000000000, | ||
| 1e75, | ||
| 0 | ||
| ) | ||
| ); | ||
| } | ||
|
thedavidmeister marked this conversation as resolved.
|
||
|
|
||
| /// Test the eval of `div` opcode parsed from a string. | ||
| /// Tests two inputs. | ||
| /// Tests the unhappy path where the final result overflows. | ||
| function testOpDivEvalTwoInputsUnhappyOverflow() external { | ||
| checkUnhappyOverflow("_: div(max-positive-value() 1e-18);", 134799733335753198973335075435098153360, 2147483694); | ||
| checkUnhappyOverflow( | ||
| "_: div(max-positive-value() 1e-18);", | ||
| 13479973333575319897333507543509815336818572211270286240551805124607, | ||
| 2147483665 | ||
| ); | ||
|
Comment on lines
+152
to
+156
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Replace magic numbers with named constants for overflow payloads. The coefficient and exponent sentinel literals hurt readability and are error-prone. Example (outside this hunk): uint256 constant COEFF_MAX = 13479973333575319897333507543509815336818572211270286240551805124607;
int256 constant EXP_OVERFLOW_SENTINEL = 2147483665;Then: checkUnhappyOverflow("_: div(max-positive-value() 1e-18);", COEFF_MAX, EXP_OVERFLOW_SENTINEL);🤖 Prompt for AI Agents |
||
| // checkUnhappy("_: div(1e52 1e-8);", abi.encodeWithSelector(PRBMath_MulDiv_Overflow.selector, 1e70, 1e18, 1e10)); | ||
| } | ||
|
|
||
| /// Test the eval of `div` opcode parsed from a string. | ||
| /// Tests three inputs. | ||
| /// Tests the happy path where we do not divide by zero or overflow. | ||
| function testOpDivEvalThreeInputsHappy() external view { | ||
| checkHappy("_: div(0 1 1);", Float.unwrap(LibDecimalFloat.packLossless(0, -1)), "0 1 1"); | ||
| checkHappy("_: div(1 1 1);", Float.unwrap(LibDecimalFloat.packLossless(1e38, -38)), "1 1 1"); | ||
| checkHappy("_: div(1 1 2);", Float.unwrap(LibDecimalFloat.packLossless(5e37, -38)), "1 1 2"); | ||
| checkHappy("_: div(1 2 1);", Float.unwrap(LibDecimalFloat.packLossless(5e38, -39)), "1 2 1"); | ||
| checkHappy("_: div(1 2 2);", Float.unwrap(LibDecimalFloat.packLossless(25e37, -39)), "1 2 2"); | ||
| checkHappy("_: div(1 2 0.1);", Float.unwrap(LibDecimalFloat.packLossless(5e38, -38)), "1 2 0.1"); | ||
| // https://github.com/rainlanguage/rain.math.float/issues/71 | ||
| // checkHappy("_: div(max-positive-value() 1 1);", type(uint256).max, "max-positive-value() 1 1"); | ||
| checkHappy("_: div(0 1 1);", Float.unwrap(LibDecimalFloat.packLossless(0, 0)), "0 1 1"); | ||
| checkHappy("_: div(1 1 1);", Float.unwrap(LibDecimalFloat.packLossless(1e67, -67)), "1 1 1"); | ||
| checkHappy("_: div(1 1 2);", Float.unwrap(LibDecimalFloat.packLossless(5e66, -67)), "1 1 2"); | ||
| checkHappy("_: div(1 2 1);", Float.unwrap(LibDecimalFloat.packLossless(5e66, -67)), "1 2 1"); | ||
| checkHappy("_: div(1 2 2);", Float.unwrap(LibDecimalFloat.packLossless(0.25e67, -67)), "1 2 2"); | ||
| checkHappy("_: div(1 2 0.1);", Float.unwrap(LibDecimalFloat.packLossless(5e66, -66)), "1 2 0.1"); | ||
| checkHappy( | ||
| "_: div(max-positive-value() 1 1);", | ||
| Float.unwrap(LibDecimalFloat.FLOAT_MAX_POSITIVE_VALUE), | ||
| "max-positive-value() 1 1" | ||
| ); | ||
| } | ||
|
|
||
| /// Test the eval of `div` opcode parsed from a string. | ||
| /// Tests three inputs. | ||
| /// Tests the unhappy path where we divide by zero. | ||
| function testOpDivEvalThreeInputsUnhappy() external { | ||
| function testOpDivEvalThreeInputsUnhappyExamples() external { | ||
| checkUnhappy("_: div(0 0 0);", stdError.divisionError); | ||
| checkUnhappy("_: div(1 0 0);", stdError.divisionError); | ||
| checkUnhappy("_: div(1 1 0);", stdError.divisionError); | ||
| checkUnhappy("_: div(max-positive-value() 0 0);", stdError.divisionError); | ||
| checkUnhappy("_: div(1 0 0);", abi.encodeWithSelector(MulDivOverflow.selector, 1e76, 1e75, 0)); | ||
| checkUnhappy("_: div(1 1 0);", abi.encodeWithSelector(MulDivOverflow.selector, 1e76, 1e75, 0)); | ||
| checkUnhappy( | ||
| "_: div(max-positive-value() 0 0);", | ||
| abi.encodeWithSelector( | ||
| MulDivOverflow.selector, | ||
| 13479973333575319897333507543509815336818572211270286240551805124607000000000, | ||
| 1e75, | ||
| 0 | ||
| ) | ||
| ); | ||
| } | ||
|
Comment on lines
+180
to
193
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) DRY the div-by-zero payload construction. Consider a small helper that builds the expected 🤖 Prompt for AI Agents |
||
|
|
||
| /// Test the eval of `div` opcode parsed from a string. | ||
| /// Tests three inputs. | ||
| /// Tests the unhappy path where the final result overflows. | ||
| function testOpDivEvalThreeInputsUnhappyOverflow() external { | ||
| checkUnhappyOverflow( | ||
| "_: div(max-positive-value() 1e-18 1e-18);", 134799733335753198973335075435098153360, 2147483694 | ||
| "_: div(max-positive-value() 1e-18 1e-18);", | ||
| 13479973333575319897333507543509815336818572211270286240551805124607, | ||
| 2147483665 | ||
| ); | ||
| // checkUnhappyOverflow("_: div(1e900000000 1 1e-900000000);", 1, -8000000000000000000000000000); | ||
| // checkUnhappy("_: div(1e52 1e-8 1);", abi.encodeWithSelector(PRBMath_MulDiv_Overflow.selector, 1e70, 1e18, 1e10)); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,26 +37,42 @@ contract LibOpExpTest is OpTest { | |
| } | ||
|
|
||
| /// Test the eval of `exp`. | ||
| function testOpExpEval() external view { | ||
| function testOpExpEvalExample() external view { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Broaden fuzz domain to include negative inputs for exp. Current bound excludes negatives; consider [-10000, 10000] to cover e^x for x < 0. Example (outside this hunk): signedCoefficientA = int224(bound(signedCoefficientA, -10000, 10000));🤖 Prompt for AI Agents |
||
| checkHappy("_: exp(0);", Float.unwrap(LibDecimalFloat.packLossless(1, 0)), "e^0"); | ||
| checkHappy( | ||
| "_: exp(1);", | ||
| Float.unwrap(LibDecimalFloat.packLossless(2.7182818284590452353602874713526624977e66, -66)), | ||
| Float.unwrap( | ||
| LibDecimalFloat.packLossless( | ||
| 2.718281828459045235360287471352662497757247093699959574966967627724e66, -66 | ||
| ) | ||
| ), | ||
| "e^1" | ||
| ); | ||
| checkHappy( | ||
| "_: exp(0.5);", | ||
| Float.unwrap(LibDecimalFloat.packLossless(1.64864091422952261768014373567633124885e66, -66)), | ||
| Float.unwrap( | ||
| LibDecimalFloat.packLossless( | ||
| 1.648640914229522617680143735676331248878623546849979787483483813862e66, -66 | ||
| ) | ||
| ), | ||
| "e^0.5" | ||
| ); | ||
| checkHappy( | ||
| "_: exp(2);", | ||
| Float.unwrap(LibDecimalFloat.packLossless(7.3901273138361809414411498854106499908e66, -66)), | ||
| Float.unwrap( | ||
| LibDecimalFloat.packLossless( | ||
| 7.390127313836180941441149885410649991028988374799838299867870510896e66, -66 | ||
| ) | ||
| ), | ||
| "e^2" | ||
| ); | ||
| checkHappy( | ||
| "_: exp(3);", | ||
| Float.unwrap(LibDecimalFloat.packLossless(20.088454853771357060808624140579874931e65, -65)), | ||
| Float.unwrap( | ||
| LibDecimalFloat.packLossless( | ||
| 20.08845485377135706080862414057987493271741281099878724900902883172e65, -65 | ||
| ) | ||
| ), | ||
| "e^3" | ||
| ); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -53,7 +53,7 @@ contract LibOpPowTest is OpTest { | |||||||||||||||||||||||||||||||||
| // 1 ^ 0 | ||||||||||||||||||||||||||||||||||
| checkHappy("_: power(1 0);", Float.unwrap(LibDecimalFloat.packLossless(1, 0)), "1 0"); | ||||||||||||||||||||||||||||||||||
| // 1 ^ 1 | ||||||||||||||||||||||||||||||||||
| checkHappy("_: power(1 1);", Float.unwrap(LibDecimalFloat.packLossless(1e3, -3)), "1 1"); | ||||||||||||||||||||||||||||||||||
| checkHappy("_: power(1 1);", Float.unwrap(LibDecimalFloat.packLossless(1, 0)), "1 1"); | ||||||||||||||||||||||||||||||||||
| // 1 ^ 2 | ||||||||||||||||||||||||||||||||||
| checkHappy("_: power(1 2);", Float.unwrap(LibDecimalFloat.packLossless(1e3, -3)), "1 2"); | ||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Consider canonicalizing other exact-1 cases 1^2 still expects 1e3,-3. If the pow path now normalizes exact integers, switch to packLossless(1, 0) for consistency (only if the reference fn returns canonical 1). Proposed diff: - checkHappy("_: power(1 2);", Float.unwrap(LibDecimalFloat.packLossless(1e3, -3)), "1 2");
+ checkHappy("_: power(1 2);", Float.unwrap(LibDecimalFloat.packLossless(1, 0)), "1 2");📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| // 2 ^ 2 | ||||||||||||||||||||||||||||||||||
|
|
@@ -70,9 +70,9 @@ contract LibOpPowTest is OpTest { | |||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| function testOpPowNegativeBaseError() external { | ||||||||||||||||||||||||||||||||||
| // Negative base with positive exponent. | ||||||||||||||||||||||||||||||||||
| checkUnhappy("_: power(-1 2);", abi.encodeWithSelector(Log10Negative.selector, -1e37, -37)); | ||||||||||||||||||||||||||||||||||
| checkUnhappy("_: power(-1 2);", abi.encodeWithSelector(Log10Negative.selector, -1, 0)); | ||||||||||||||||||||||||||||||||||
| // Negative base with negative exponent. | ||||||||||||||||||||||||||||||||||
| checkUnhappy("_: power(-1 -2);", abi.encodeWithSelector(Log10Negative.selector, -1e37, -37)); | ||||||||||||||||||||||||||||||||||
| checkUnhappy("_: power(-1 -2);", abi.encodeWithSelector(Log10Negative.selector, -1, 0)); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
Comment on lines
71
to
76
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Add fractional-negative-base unhappy example Add power(-4 0.5) unhappy to lock in the log-domain error behaviour for non-integer exponents with negative bases. Proposed snippet (within this test): + // Negative base with fractional exponent (domain error).
+ checkUnhappy("_: power(-4 0.5);", abi.encodeWithSelector(Log10Negative.selector, -4, 0));📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /// Test the eval of `power` for bad inputs. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,12 +36,14 @@ contract LibOpSqrtTest is OpTest { | |
| } | ||
|
|
||
| /// Test the eval of `sqrt`. | ||
| function testOpSqrtEval() external view { | ||
| function testOpSqrtEvalExamples() external view { | ||
| checkHappy("_: sqrt(0);", 0, "0"); | ||
| checkHappy("_: sqrt(1);", Float.unwrap(LibDecimalFloat.packLossless(1e3, -3)), "1"); | ||
| checkHappy( | ||
| "_: sqrt(0.5);", | ||
| Float.unwrap(LibDecimalFloat.packLossless(70671378091872791519434628975265017667, -38)), | ||
| Float.unwrap( | ||
| LibDecimalFloat.packLossless(7067137809187279151943462897526501766784452296819787985865724381625, -67) | ||
| ), | ||
|
Comment on lines
+44
to
+46
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Verify sqrt(0.5) canonical encoding The packed value for sqrt(0.5) changed to a very long mantissa with exponent -67. Please double-check this is the canonical packLossless encoding produced by the parser + evaluator for 0.5 to avoid future drift. Consider adding a brief comment noting how this constant was derived. 🤖 Prompt for AI Agents |
||
| "0.5" | ||
| ); | ||
| checkHappy("_: sqrt(2);", Float.unwrap(LibDecimalFloat.packLossless(1415, -3)), "2"); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.