Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 src/generated/Rainterpreter.pointers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
pragma solidity =0.8.25;

/// @dev Hash of the known bytecode.
bytes32 constant BYTECODE_HASH = bytes32(0xef5d5c21b4a25cc7b3dfdd4402f2d8a35099c9d415c4b6a4f0f76ebfed67e0b0);
bytes32 constant BYTECODE_HASH = bytes32(0x1f82584ad80b630eb25769669c965fc8efff9d8f9cd3dcc6f9fc0ac842e81474);

/// @dev The function pointers known to the interpreter for dynamic dispatch.
/// By setting these as a constant they can be inlined into the interpreter
/// and loaded at eval time for very low gas (~100) due to the compiler
/// optimising it to a single `codecopy` to build the in memory bytes array.
bytes constant OPCODE_FUNCTION_POINTERS =
hex"07bd07ef0813099f0a680a7a0a8c0aa50ac90afd0b0e0b1f0bc10be00c9e0d4e0dd20f1410470c9e114011f21294130c131d132e132e133f1386140814211435144e1467149214ab14c414d71539158715d51623167116bf170d175b178c17da18281876195d";
hex"07c607f8081c09a80a710a830a950aae0ad20b060b170b280bca0be90ca70d570ddb0f1d10500ca7114911fb129d13151326133713371348138f1411142a143e14571470149b14b414cd14e01542159015de162c167a16c817161724177217a317f1183f188d1974";
6 changes: 3 additions & 3 deletions src/generated/RainterpreterExpressionDeployer.pointers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
pragma solidity =0.8.25;

/// @dev Hash of the known bytecode.
bytes32 constant BYTECODE_HASH = bytes32(0xce3a44f2ed702547f2da7cc4e7adfc9d9dd5a2bfbfd806b228db3cfcdd1da125);
bytes32 constant BYTECODE_HASH = bytes32(0xb76a360580b20009cee2999206d01cce8a7be9c16321becaa7a8897a4e8fc30c);

/// @dev The hash of the meta that describes the contract.
bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0xf8bdd3a04e26f925f45376a4f3cfe9455904c1abbbfbf60f84d982803beea817);
bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0xde93b39376f1e94f38fde797b17027f86a9a59b2540f89ec15cc09759f171eb8);

/// @dev The function pointers for the integrity check fns.
bytes constant INTEGRITY_FUNCTION_POINTERS =
hex"0e500ece0f3210ac10b610b610c010c910e4118a118a11e6125e126b10b610c0126b10b610c010b610b610b610c010ac10ac10ac10ac1275129a10b610b610b610b610c010b610b610ac12a412a412a412a412a412a412be12a410ac12a412be12be10c0129a";
hex"0e580ed60f3a10b410be10be10c810d110ec1192119211ee1266127310be10c8127310be10c810be10be10be10c810b410b410b410b4127d12a210be10be10be10be10c810be10be10b412ac12ac12ac12ac12ac12ac12c610c812ac10b412ac12c612c610c812a2";
8 changes: 4 additions & 4 deletions src/generated/RainterpreterParser.pointers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
pragma solidity =0.8.25;

/// @dev Hash of the known bytecode.
bytes32 constant BYTECODE_HASH = bytes32(0x802ffd0c76897b508453402052a3a1840b73d060ed67e227d1c874d3cff34ec4);
bytes32 constant BYTECODE_HASH = bytes32(0x680382e10b1fa1d3a16b62c994f80ced2eff3fbd3cb51ed90817bf25bb904f08);

/// @dev The parse meta that is used to lookup word definitions.
/// The structure of the parse meta is:
Expand All @@ -29,7 +29,7 @@ bytes32 constant BYTECODE_HASH = bytes32(0x802ffd0c76897b508453402052a3a1840b73d
/// bit count of the previous bloom filter. If we reach the end of the bloom
/// filters then we have a miss.
bytes constant PARSE_META =
hex"0178ac80600029b010810908a00a3448c001280030060100180000200cc2200408a00c95d8383148145c3234b3f32dd587e204afc8f01e95a26007b9a51f0d5e6f2803ce312215fae0a1271233de118cfd53051c784d25a55ade1681ac9622ac6dfc2ea4e5e91f5fc32a0e92b2401dbbd837100ef76b00cd8814205902e62a9714ec13313592290d473b21f880501427634f0f23b4970ac0e53d0b895f991ac908be0983724f12c080bc2f9d7b7d28757aea266f62e02b5c0ab5086d2a7b2390a6b319bcb24402af7d4506414b8117b04fb31cb2182f18ef532924c301e31b9314ad30fa5d8001336a592cab2461";
hex"0178ac80600029b010910908a00a3448c001280030060100180000200cc2200408a00c95d8383248145c3334b3f32ed587e204afc8f01e95a26007b9a51f0d5e6f2803ce312215fae0a1271233de118cfd53051c784d25a55ade1681ac9622ac6dfc2fa4e5e91f5fc32a0e92b2401dbbd837100ef76b00cd8814205902e62a9714ec13313592290d473b21f880501427634f0f23b4970ac0e53d0b895f991ac908be0983724f12c080bc309d7b7d28757aea2c3a7b86266f62e02b5c0ab5086d2a7b2390a6b319bcb24402af7d4506414b8117b04fb31cb2182f18ef532924c301e31b9314ad31fa5d8001336a592dab2461";

/// @dev The build depth of the parser meta.

Expand All @@ -39,11 +39,11 @@ uint8 constant PARSE_META_BUILD_DEPTH = 2;
/// These positional indexes all map to the same indexes looked up in the parse
/// meta.
bytes constant OPERAND_HANDLER_FUNCTION_POINTERS =
hex"1a331a331a331b081c1f1c1f1c1f1b081b081a331a331a331c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1c1f1a331c1f1c1f";
hex"1a3b1a3b1a3b1b101c271c271c271b101b101a3b1a3b1a3b1c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271c271a3b1c271c27";

/// @dev Every two bytes is a function pointer for a literal parser.
/// Literal dispatches are determined by the first byte(s) of the literal
/// rather than a full word lookup, and are done with simple conditional
/// jumps as the possibilities are limited compared to the number of words we
/// have.
bytes constant LITERAL_PARSER_FUNCTION_POINTERS = hex"157b17ad17f0188e";
bytes constant LITERAL_PARSER_FUNCTION_POINTERS = hex"158317b517f81896";
14 changes: 7 additions & 7 deletions src/lib/op/LibAllStandardOps.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ import {LibOpDiv} from "./math/LibOpDiv.sol";
// import {LibOpFrac} from "./math/LibOpFrac.sol";
// import {LibOpGm} from "./math/LibOpGm.sol";
// import {LibOpHeadroom} from "./math/LibOpHeadroom.sol";
// import {LibOpInv} from "./math/LibOpInv.sol";
import {LibOpInv} from "./math/LibOpInv.sol";
// import {LibOpLn} from "./math/LibOpLn.sol";
// import {LibOpLog10} from "./math/LibOpLog10.sol";
import {LibOpMax} from "./math/LibOpMax.sol";
Expand All @@ -108,7 +108,7 @@ import {LibParseLiteralHex} from "../parse/literal/LibParseLiteralHex.sol";
import {LibParseLiteralSubParseable} from "../parse/literal/LibParseLiteralSubParseable.sol";

/// @dev Number of ops currently provided by `AllStandardOps`.
uint256 constant ALL_STANDARD_OPS_LENGTH = 51;
uint256 constant ALL_STANDARD_OPS_LENGTH = 52;

/// @title LibAllStandardOps
/// @notice Every opcode available from the core repository laid out as a single
Expand Down Expand Up @@ -277,7 +277,7 @@ library LibAllStandardOps {
// "headroom",
// "Headroom of a number. I.e. the distance to the next whole number (1 - frac(x)). The headroom at any whole number is 1 (not 0)."
// ),
// AuthoringMetaV2("inv", "The inverse (1 / x) of a number. Errors if the number is zero."),
AuthoringMetaV2("inv", "The inverse (1 / x) of a number. Errors if the number is zero."),
// AuthoringMetaV2("ln", "Natural logarithm ln(x). Errors if the number is zero."),
// AuthoringMetaV2("log2", "Base 2 logarithm log2(x). Errors if the number is zero."),
// AuthoringMetaV2("log10", "Base 10 logarithm log10(x). Errors if the number is zero."),
Expand Down Expand Up @@ -492,8 +492,8 @@ library LibAllStandardOps {
// LibParseOperand.handleOperandDisallowed,
// // headroom
// LibParseOperand.handleOperandDisallowed,
// // inv
// LibParseOperand.handleOperandDisallowed,
// inv
LibParseOperand.handleOperandDisallowed,
// // ln
// LibParseOperand.handleOperandDisallowed,
// // log2
Expand Down Expand Up @@ -623,7 +623,7 @@ library LibAllStandardOps {
// LibOpFrac.integrity,
// LibOpGm.integrity,
// LibOpHeadroom.integrity,
// LibOpInv.integrity,
LibOpInv.integrity,
// LibOpLn.integrity,
// LibOpLog2.integrity,
// LibOpLog10.integrity,
Expand Down Expand Up @@ -738,7 +738,7 @@ library LibAllStandardOps {
// LibOpFrac.run,
// LibOpGm.run,
// LibOpHeadroom.run,
// LibOpInv.run,
LibOpInv.run,
// LibOpLn.run,
// LibOpLog2.run,
// LibOpLog10.run,
Expand Down
73 changes: 37 additions & 36 deletions src/lib/op/math/LibOpInv.sol
Original file line number Diff line number Diff line change
@@ -1,43 +1,44 @@
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

// import {UD60x18, inv} 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 {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol";
import {StackItem} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol";

// /// @title LibOpInv
// /// @notice Opcode for the inverse 1 / x of an decimal 18 fixed point number.
// library LibOpInv {
// function integrity(IntegrityCheckState memory, Operand) internal pure returns (uint256, uint256) {
// // There must be one inputs and one output.
// return (1, 1);
// }
/// @title LibOpInv
/// @notice Opcode for the inverse 1 / x of a floating point number.
library LibOpInv {
function integrity(IntegrityCheckState memory, OperandV2) internal pure returns (uint256, uint256) {
// There must be one inputs and one output.
return (1, 1);
}

// /// inv
// /// 18 decimal fixed point inverse 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(inv(UD60x18.wrap(a)));
/// inv
/// floating point inverse of a number.
function run(InterpreterState memory, OperandV2, Pointer stackTop) internal pure returns (Pointer) {
Float a;
assembly ("memory-safe") {
a := mload(stackTop)
}
a = LibDecimalFloat.inv(a);

// assembly ("memory-safe") {
// mstore(stackTop, a)
// }
// return stackTop;
// }
assembly ("memory-safe") {
mstore(stackTop, a)
}
return stackTop;
}

// /// Gas intensive reference implementation of inv 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(inv(UD60x18.wrap(inputs[0])));
// return outputs;
// }
// }
/// Gas intensive reference implementation of inv for testing.
function referenceFn(InterpreterState memory, OperandV2, StackItem[] memory inputs)
internal
pure
returns (StackItem[] memory)
{
StackItem[] memory outputs = new StackItem[](1);
outputs[0] = StackItem.wrap(Float.unwrap((LibDecimalFloat.inv(Float.wrap(StackItem.unwrap(inputs[0]))))));
return outputs;
}
}
120 changes: 64 additions & 56 deletions test/src/lib/op/math/LibOpInv.t.sol
Original file line number Diff line number Diff line change
@@ -1,59 +1,67 @@
// SPDX-License-Identifier: CAL
pragma solidity =0.8.25;

// import {OpTest, IntegrityCheckState, Operand, InterpreterState, UnexpectedOperand} from "test/abstract/OpTest.sol";
// import {LibOpInv} from "src/lib/op/math/LibOpInv.sol";
// import {LibOperand} from "test/lib/operand/LibOperand.sol";

// contract LibOpInvTest is OpTest {
// /// Directly test the integrity logic of LibOpInv.
// /// Inputs are always 1, outputs are always 1.
// function testOpInvIntegrity(IntegrityCheckState memory state, Operand operand) external pure {
// (uint256 calcInputs, uint256 calcOutputs) = LibOpInv.integrity(state, operand);
// assertEq(calcInputs, 1);
// assertEq(calcOutputs, 1);
// }

// /// Directly test the runtime logic of LibOpInv.
// function testOpInvRun(uint256 a, uint16 operandData) public view {
// // 0 is division by 0.
// a = bound(a, 1, 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, LibOpInv.referenceFn, LibOpInv.integrity, LibOpInv.run, inputs);
// }

// /// Test the eval of `inv`.
// function testOpInvEval() external view {
// checkHappy("_: inv(1);", 1e18, "1");
// checkHappy("_: inv(0.5);", 2e18, "0.5");
// checkHappy("_: inv(2);", 0.5e18, "2");
// checkHappy("_: inv(3);", 333333333333333333, "3");
// }

// /// Test the eval of `inv` for bad inputs.
// function testOpInvZeroInputs() external {
// checkBadInputs("_: inv();", 0, 1, 0);
// }

// function testOpInvTwoInputs() external {
// checkBadInputs("_: inv(1 1);", 2, 1, 2);
// }

// function testOpInvZeroOutputs() external {
// checkBadOutputs(": inv(1);", 1, 1, 0);
// }

// function testOpInvTwoOutputs() external {
// checkBadOutputs("_ _: inv(1);", 1, 1, 2);
// }

// /// Test that operand is disallowed.
// function testOpExpEvalOperandDisallowed() external {
// checkUnhappyParse("_: inv<0>(1);", abi.encodeWithSelector(UnexpectedOperand.selector));
// }
// }
import {OpTest, IntegrityCheckState, OperandV2, InterpreterState, UnexpectedOperand} from "test/abstract/OpTest.sol";
import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol";
import {LibOpInv} from "src/lib/op/math/LibOpInv.sol";
import {LibOperand} from "test/lib/operand/LibOperand.sol";
import {StackItem} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol";

contract LibOpInvTest is OpTest {
/// Directly test the integrity logic of LibOpInv.
/// Inputs are always 1, outputs are always 1.
function testOpInvIntegrity(IntegrityCheckState memory state, OperandV2 operand) external pure {
(uint256 calcInputs, uint256 calcOutputs) = LibOpInv.integrity(state, operand);
assertEq(calcInputs, 1);
assertEq(calcOutputs, 1);
}

/// Directly test the runtime logic of LibOpInv.
function testOpInvRun(int224 signedCoefficient, int32 exponent, uint16 operandData) public view {
exponent = int32(bound(exponent, type(int16).min, type(int16).max));
Float a = LibDecimalFloat.packLossless(signedCoefficient, exponent);
// 0 is division by 0.
vm.assume(!LibDecimalFloat.isZero(a));
InterpreterState memory state = opTestDefaultInterpreterState();

OperandV2 operand = LibOperand.build(1, 1, operandData);
StackItem[] memory inputs = new StackItem[](1);
inputs[0] = StackItem.wrap(Float.unwrap(a));

opReferenceCheck(state, operand, LibOpInv.referenceFn, LibOpInv.integrity, LibOpInv.run, inputs);
}

/// Test the eval of `inv`.
function testOpInvEval() external view {
checkHappy("_: inv(1);", Float.unwrap(LibDecimalFloat.packLossless(1e38, -38)), "1");
checkHappy("_: inv(0.5);", Float.unwrap(LibDecimalFloat.packLossless(2e37, -37)), "0.5");
checkHappy("_: inv(2);", Float.unwrap(LibDecimalFloat.packLossless(0.5e38, -38)), "2");
checkHappy(
"_: inv(3);",
Float.unwrap(LibDecimalFloat.packLossless(0.33333333333333333333333333333333333333e38, -38)),
"3"
);
}

/// Test the eval of `inv` for bad inputs.
function testOpInvZeroInputs() external {
checkBadInputs("_: inv();", 0, 1, 0);
}

function testOpInvTwoInputs() external {
checkBadInputs("_: inv(1 1);", 2, 1, 2);
}

function testOpInvZeroOutputs() external {
checkBadOutputs(": inv(1);", 1, 1, 0);
}

function testOpInvTwoOutputs() external {
checkBadOutputs("_ _: inv(1);", 1, 1, 2);
}

/// Test that operand is disallowed.
function testOpExpEvalOperandDisallowed() external {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Fix function name to match the operation being tested.

The function name suggests it's testing exponential operation, but it's actually testing the inverse operation's operand validation.

-    function testOpExpEvalOperandDisallowed() external {
+    function testOpInvEvalOperandDisallowed() external {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function testOpExpEvalOperandDisallowed() external {
function testOpInvEvalOperandDisallowed() external {
🤖 Prompt for AI Agents
In test/src/lib/op/math/LibOpInv.t.sol at line 62, the function name
testOpExpEvalOperandDisallowed does not match the operation being tested, which
is the inverse operation's operand validation. Rename the function to reflect
that it tests the inverse operation, such as testOpInvEvalOperandDisallowed, to
improve clarity and correctness.

checkUnhappyParse("_: inv<0>(1);", abi.encodeWithSelector(UnexpectedOperand.selector));
}
}