In Solidity: 2*2/3 = 1 (rounding down)
MulDivUp: 2*2/3 = 2 (rounding up)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
contract Test {
// solmate
// <https://github.com/transmissions11/solmate/blob/12421e3edee21cfb99bf5a6edd6169e6497511de/src/mixins/ERC4626.sol#L133>
function mulDivUp(
uint256 x,
uint256 y,
uint256 denominator
) public pure returns (uint256 z) {
assembly {
// Store x * y in z for now.
z := mul(x, y)
// Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
revert(0, 0)
}
// First, divide z - 1 by the denominator and add 1.
// We allow z - 1 to underflow if z is 0, because we multiply the
// end result by 0 if z is zero, ensuring we return 0 if z is zero.
z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))
}
}
// solidstate
// <https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/token/ERC4626/base/ERC4626BaseInternal.sol>
function _previewWithdraw(uint256 x,uint256 y,uint256 z)
public
pure
returns (uint256 shareAmount)
{
shareAmount = (x * y + z - 1) / z;
}
}