Skip to content

Commit

Permalink
✨ Coalesce (#1360)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized authored Feb 20, 2025
1 parent 9298d09 commit 6015421
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 0 deletions.
24 changes: 24 additions & 0 deletions docs/utils/fixedpointmathlib.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,30 @@ function ternary(bool condition, address x, address y)

Returns `condition ? x : y`, without branching.

### coalesce(uint256,uint256)

```solidity
function coalesce(uint256 x, uint256 y) internal pure returns (uint256 z)
```

Returns `x != 0 ? x : y`, without branching.

### coalesce(bytes32,bytes32)

```solidity
function coalesce(bytes32 x, bytes32 y) internal pure returns (bytes32 z)
```

Returns `x != bytes32(0) ? x : y`, without branching.

### coalesce(address,address)

```solidity
function coalesce(address x, address y) internal pure returns (address z)
```

Returns `x != address(0) ? x : y`, without branching.

### rpow(uint256,uint256,uint256)

```solidity
Expand Down
24 changes: 24 additions & 0 deletions src/utils/FixedPointMathLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,30 @@ library FixedPointMathLib {
}
}

/// @dev Returns `x != 0 ? x : y`, without branching.
function coalesce(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := or(x, mul(y, iszero(x)))
}
}

/// @dev Returns `x != bytes32(0) ? x : y`, without branching.
function coalesce(bytes32 x, bytes32 y) internal pure returns (bytes32 z) {
/// @solidity memory-safe-assembly
assembly {
z := or(x, mul(y, iszero(x)))
}
}

/// @dev Returns `x != address(0) ? x : y`, without branching.
function coalesce(address x, address y) internal pure returns (address z) {
/// @solidity memory-safe-assembly
assembly {
z := or(x, mul(y, iszero(shl(96, x))))
}
}

/// @dev Exponentiate `x` to `y` by squaring, denominated in base `b`.
/// Reverts if the computation overflows.
function rpow(uint256 x, uint256 y, uint256 b) internal pure returns (uint256 z) {
Expand Down
20 changes: 20 additions & 0 deletions test/FixedPointMathLib.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2195,10 +2195,30 @@ contract FixedPointMathLibTest is SoladyTest {
return a;
}

function testCoalesce(uint256 x, uint256 y) public {
assertEq(x == 0 ? y : x, FixedPointMathLib.coalesce(x, y));
}

function testCoalesce(address x, address y) public {
assertEq(x == address(0) ? y : x, FixedPointMathLib.coalesce(x, y));
}

function testCoalesce(bytes32 x, bytes32 y) public {
assertEq(x == bytes32(0) ? y : x, FixedPointMathLib.coalesce(x, y));
}

function testTernary(bool condition, uint256 x, uint256 y) public {
assertEq(condition ? x : y, FixedPointMathLib.ternary(condition, x, y));
}

function testTernary(bool condition, bytes32 x, bytes32 y) public {
assertEq(condition ? x : y, FixedPointMathLib.ternary(condition, x, y));
}

function testTernary(bool condition, address x, address y) public {
assertEq(condition ? x : y, FixedPointMathLib.ternary(condition, x, y));
}

function testIsEven(uint256 x) public {
assertEq(FixedPointMathLib.isEven(x), x % 2 == 0);
}
Expand Down

0 comments on commit 6015421

Please sign in to comment.