-
Notifications
You must be signed in to change notification settings - Fork 2
exp op #393
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
exp op #393
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 |
|---|---|---|
| @@ -1,43 +1,49 @@ | ||
| // SPDX-License-Identifier: CAL | ||
| pragma solidity ^0.8.18; | ||
|
|
||
| // import {UD60x18, exp} from "prb-math/UD60x18.sol"; | ||
| // import {OperandV2} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol"; | ||
| // import {Pointer} from "rain.solmem/lib/LibPointer.sol"; | ||
| // import {InterpreterState} from "../../state/LibInterpreterState.sol"; | ||
| // import {IntegrityCheckState} from "../../integrity/LibIntegrityCheck.sol"; | ||
| import {OperandV2} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol"; | ||
| import {Pointer} from "rain.solmem/lib/LibPointer.sol"; | ||
| import {InterpreterState} from "../../state/LibInterpreterState.sol"; | ||
| import {IntegrityCheckState} from "../../integrity/LibIntegrityCheck.sol"; | ||
| import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; | ||
| import {StackItem} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol"; | ||
|
|
||
| // /// @title LibOpExp | ||
| // /// @notice Opcode for the natural exponential e^x as decimal 18 fixed point. | ||
| // library LibOpExp { | ||
| // function integrity(IntegrityCheckState memory, Operand) internal pure returns (uint256, uint256) { | ||
| // // There must be one inputs and one output. | ||
| // return (1, 1); | ||
| // } | ||
| /// @title LibOpExp | ||
| /// @notice Opcode for the natural exponential e^x as decimal floating point. | ||
| library LibOpExp { | ||
| using LibDecimalFloat for Float; | ||
|
|
||
| // /// exp | ||
| // /// 18 decimal fixed point natural exponent of a number. | ||
| // function run(InterpreterState memory, Operand, Pointer stackTop) internal pure returns (Pointer) { | ||
| // uint256 a; | ||
| // assembly ("memory-safe") { | ||
| // a := mload(stackTop) | ||
| // } | ||
| // a = UD60x18.unwrap(exp(UD60x18.wrap(a))); | ||
| function integrity(IntegrityCheckState memory, OperandV2) internal pure returns (uint256, uint256) { | ||
| // There must be one inputs and one output. | ||
| return (1, 1); | ||
| } | ||
|
|
||
| // assembly ("memory-safe") { | ||
| // mstore(stackTop, a) | ||
| // } | ||
| // return stackTop; | ||
| // } | ||
| /// exp | ||
| /// decimal floating point natural exponent of a number. | ||
| function run(InterpreterState memory, OperandV2, Pointer stackTop) internal view returns (Pointer) { | ||
| Float a; | ||
| assembly ("memory-safe") { | ||
| a := mload(stackTop) | ||
| } | ||
| a = LibDecimalFloat.FLOAT_E.pow(a, LibDecimalFloat.LOG_TABLES_ADDRESS); | ||
|
|
||
| // /// Gas intensive reference implementation of exp for testing. | ||
| // function referenceFn(InterpreterState memory, Operand, uint256[] memory inputs) | ||
| // internal | ||
| // pure | ||
| // returns (uint256[] memory) | ||
| // { | ||
| // uint256[] memory outputs = new uint256[](1); | ||
| // outputs[0] = UD60x18.unwrap(exp(UD60x18.wrap(inputs[0]))); | ||
| // return outputs; | ||
| // } | ||
| // } | ||
| assembly ("memory-safe") { | ||
| mstore(stackTop, a) | ||
| } | ||
| return stackTop; | ||
| } | ||
|
|
||
| /// Gas intensive reference implementation of exp for testing. | ||
| function referenceFn(InterpreterState memory, OperandV2, StackItem[] memory inputs) | ||
| internal | ||
| view | ||
| returns (StackItem[] memory) | ||
| { | ||
| Float a = Float.wrap(StackItem.unwrap(inputs[0])); | ||
| a = LibDecimalFloat.FLOAT_E.pow(a, LibDecimalFloat.LOG_TABLES_ADDRESS); | ||
|
|
||
| StackItem[] memory outputs = new StackItem[](1); | ||
| outputs[0] = StackItem.wrap(Float.unwrap(a)); | ||
| return outputs; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,59 +1,85 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // SPDX-License-Identifier: CAL | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pragma solidity =0.8.25; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // import {OpTest, IntegrityCheckState, Operand, InterpreterState, UnexpectedOperand} from "test/abstract/OpTest.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // import {LibOpExp} from "src/lib/op/math/LibOpExp.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // import {LibOperand} from "test/lib/operand/LibOperand.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // contract LibOpExpTest is OpTest { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // /// Directly test the integrity logic of LibOpExp. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // /// Inputs are always 1, outputs are always 1. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // function testOpExpIntegrity(IntegrityCheckState memory state, Operand operand) external pure { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // (uint256 calcInputs, uint256 calcOutputs) = LibOpExp.integrity(state, operand); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // assertEq(calcInputs, 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // assertEq(calcOutputs, 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // /// Directly test the runtime logic of LibOpExp. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // function testOpExpRun(uint256 a, uint16 operandData) public view { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // a = bound(a, 0, type(uint64).max - 1e18); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // InterpreterState memory state = opTestDefaultInterpreterState(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Operand operand = LibOperand.build(1, 1, operandData); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // uint256[] memory inputs = new uint256[](1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // inputs[0] = a; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // opReferenceCheck(state, operand, LibOpExp.referenceFn, LibOpExp.integrity, LibOpExp.run, inputs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // /// Test the eval of `exp`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // function testOpExpEval() external view { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkHappy("_: exp(0);", 1e18, "e^0"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkHappy("_: exp(1);", 2718281828459045234, "e^1"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkHappy("_: exp(0.5);", 1648721270700128145, "e^0.5"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkHappy("_: exp(2);", 7389056098930650223, "e^2"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkHappy("_: exp(3);", 20085536923187667724, "e^3"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // /// Test the eval of `exp` for bad inputs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // function testOpExpEvalZeroInputs() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkBadInputs("_: exp();", 0, 1, 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // function testOpExpEvalTwoInputs() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkBadInputs("_: exp(1 1);", 2, 1, 2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // function testOpExpZeroOutputs() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkBadOutputs(": exp(1);", 1, 1, 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // function testOpExpTwoOutputs() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkBadOutputs("_ _: exp(1);", 1, 1, 2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // /// Test that operand is disallowed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // function testOpExpEvalOperandDisallowed() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // checkUnhappyParse("_: exp<0>(1);", abi.encodeWithSelector(UnexpectedOperand.selector)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import {OpTest, IntegrityCheckState, OperandV2, InterpreterState, UnexpectedOperand} from "test/abstract/OpTest.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import {LibOpExp} from "src/lib/op/math/LibOpExp.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import {LibOperand} from "test/lib/operand/LibOperand.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import {StackItem} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contract LibOpExpTest is OpTest { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function beforeOpTestConstructor() internal virtual override { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vm.createSelectFork(vm.envString("ETH_RPC_URL")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Directly test the integrity logic of LibOpExp. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Inputs are always 1, outputs are always 1. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testOpExpIntegrity(IntegrityCheckState memory state, OperandV2 operand) external pure { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (uint256 calcInputs, uint256 calcOutputs) = LibOpExp.integrity(state, operand); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assertEq(calcInputs, 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assertEq(calcOutputs, 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Directly test the runtime logic of LibOpExp. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testOpExpRun(int224 signedCoefficientA, int32 exponentA, uint16 operandData) public view { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| signedCoefficientA = int224(bound(signedCoefficientA, 0, 10000)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exponentA = int32(bound(exponentA, -10, 5)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| InterpreterState memory state = opTestDefaultInterpreterState(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| OperandV2 operand = LibOperand.build(1, 1, operandData); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Float a = LibDecimalFloat.packLossless(signedCoefficientA, exponentA); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StackItem[] memory inputs = new StackItem[](1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputs[0] = StackItem.wrap(Float.unwrap(a)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| opReferenceCheck(state, operand, LibOpExp.referenceFn, LibOpExp.integrity, LibOpExp.run, inputs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Test the eval of `exp`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testOpExpEval() external view { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkHappy("_: exp(0);", Float.unwrap(LibDecimalFloat.packLossless(1, 0)), "e^0"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkHappy( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "_: exp(1);", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Float.unwrap(LibDecimalFloat.packLossless(271828182845904523536028747135266249770000, -41)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "e^1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkHappy( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "_: exp(0.5);", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Float.unwrap(LibDecimalFloat.packLossless(164864091422952261768014373567633124880000, -41)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "e^0.5" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkHappy( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "_: exp(2);", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Float.unwrap(LibDecimalFloat.packLossless(73901273138361809414411498854106499908000, -40)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "e^2" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkHappy( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "_: exp(3);", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Float.unwrap(LibDecimalFloat.packLossless(200884548537713570608086241405798749310000, -40)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "e^3" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+62
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 test cases for negative inputs The eval tests only cover positive inputs. Consider adding test cases for negative values to ensure the exponential function handles them correctly: checkHappy(
"_: exp(3);",
Float.unwrap(LibDecimalFloat.packLossless(200884548537713570608086241405798749310000, -40)),
"e^3"
);
+ checkHappy(
+ "_: exp(-1);",
+ Float.unwrap(LibDecimalFloat.packLossless(367897834377610754067267193921935356200000, -42)),
+ "e^-1"
+ );
+ checkHappy(
+ "_: exp(-2);",
+ Float.unwrap(LibDecimalFloat.packLossless(135263130223700958314976198650936531970000, -42)),
+ "e^-2"
+ );📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Test the eval of `exp` for bad inputs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testOpExpEvalZeroInputs() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkBadInputs("_: exp();", 0, 1, 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testOpExpEvalTwoInputs() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkBadInputs("_: exp(1 1);", 2, 1, 2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testOpExpZeroOutputs() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkBadOutputs(": exp(1);", 1, 1, 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testOpExpTwoOutputs() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkBadOutputs("_ _: exp(1);", 1, 1, 2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Test that operand is disallowed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testOpExpEvalOperandDisallowed() external { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkUnhappyParse("_: exp<0>(1);", abi.encodeWithSelector(UnexpectedOperand.selector)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,6 +24,7 @@ contract LibOpSqrtTest is OpTest { | |||||||||||||||||||
|
|
||||||||||||||||||||
| /// Directly test the runtime logic of LibOpSqrt. | ||||||||||||||||||||
| function testOpSqrtRun(Float a) public view { | ||||||||||||||||||||
| vm.assume(!a.eq(LibDecimalFloat.FLOAT_MIN_NEGATIVE_VALUE)); | ||||||||||||||||||||
|
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. 💡 Verification agent 🧩 Analysis chainDocument why The test excludes 🏁 Script executed: #!/bin/bash
# Check if FLOAT_MIN_NEGATIVE_VALUE is handled consistently across other math operations
ast-grep --pattern 'FLOAT_MIN_NEGATIVE_VALUE' Length of output: 45 🏁 Script executed: #!/bin/bash
# Search for all references to FLOAT_MIN_NEGATIVE_VALUE in the repo
rg -n "FLOAT_MIN_NEGATIVE_VALUE" .
# Locate its definition in the LibDecimalFloat contract
rg -n "constant FLOAT_MIN_NEGATIVE_VALUE" -t solLength of output: 496 🏁 Script executed: #!/bin/bash
# Locate the Solidity file defining LibDecimalFloat
rg -l "library LibDecimalFloat" --glob '*.sol'
# Search for FLOAT_MIN_NEGATIVE_VALUE definition in all .sol files
rg -n "FLOAT_MIN_NEGATIVE_VALUE" --glob '*.sol'Length of output: 473 🏁 Script executed: #!/bin/bash
# Display the sqrt test with context around the assume
sed -n '1,80p' test/src/lib/op/math/LibOpSqrt.t.sol
# Locate and display the implementation of LibOpSqrt
file=$(fd LibOpSqrt.sol --search-path src)
if [ -n "$file" ]; then
echo "Implementation file: $file"
sed -n '1,80p' "$file"
else
echo "LibOpSqrt.sol not found"
fiLength of output: 4913 Add a comment explaining why the smallest negative float is excluded The line in /// Directly test the runtime logic of LibOpSqrt.
function testOpSqrtRun(Float a) public view {
- vm.assume(!a.eq(LibDecimalFloat.FLOAT_MIN_NEGATIVE_VALUE));
+ // Exclude the minimum negative float because abs(min) cannot be represented
+ vm.assume(!a.eq(LibDecimalFloat.FLOAT_MIN_NEGATIVE_VALUE));
a = a.abs();
InterpreterState memory state = opTestDefaultInterpreterState();
…• File: test/src/lib/op/math/LibOpSqrt.t.sol 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
| a = a.abs(); | ||||||||||||||||||||
| InterpreterState memory state = opTestDefaultInterpreterState(); | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Consider expanding fuzz test bounds and adding negative input tests
The fuzz test bounds are quite restrictive:
Also consider adding explicit test cases for:
exp(-1),exp(-2))📝 Committable suggestion
🤖 Prompt for AI Agents