Update docs
This commit is contained in:
118
test/utils/math/Math.t.sol
Normal file
118
test/utils/math/Math.t.sol
Normal file
@ -0,0 +1,118 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
|
||||
import "../../../contracts/utils/math/Math.sol";
|
||||
import "../../../contracts/utils/math/SafeMath.sol";
|
||||
|
||||
contract MathTest is Test {
|
||||
// SQRT
|
||||
function testSqrt(uint256 input, uint8 r) public {
|
||||
Math.Rounding rounding = _asRounding(r);
|
||||
|
||||
uint256 result = Math.sqrt(input, rounding);
|
||||
|
||||
// square of result is bigger than input
|
||||
if (_squareBigger(result, input)) {
|
||||
assertTrue(rounding == Math.Rounding.Up);
|
||||
assertTrue(_squareSmaller(result - 1, input));
|
||||
}
|
||||
// square of result is smaller than input
|
||||
else if (_squareSmaller(result, input)) {
|
||||
assertFalse(rounding == Math.Rounding.Up);
|
||||
assertTrue(_squareBigger(result + 1, input));
|
||||
}
|
||||
}
|
||||
|
||||
function _squareBigger(uint256 value, uint256 ref) private pure returns (bool) {
|
||||
(bool noOverflow, uint256 square) = SafeMath.tryMul(value, value);
|
||||
return !noOverflow || square > ref;
|
||||
}
|
||||
|
||||
function _squareSmaller(uint256 value, uint256 ref) private pure returns (bool) {
|
||||
return value * value < ref;
|
||||
}
|
||||
|
||||
// LOG2
|
||||
function testLog2(uint256 input, uint8 r) public {
|
||||
Math.Rounding rounding = _asRounding(r);
|
||||
|
||||
uint256 result = Math.log2(input, rounding);
|
||||
|
||||
if (input == 0) {
|
||||
assertEq(result, 0);
|
||||
} else if (_powerOf2Bigger(result, input)) {
|
||||
assertTrue(rounding == Math.Rounding.Up);
|
||||
assertTrue(_powerOf2Smaller(result - 1, input));
|
||||
} else if (_powerOf2Smaller(result, input)) {
|
||||
assertFalse(rounding == Math.Rounding.Up);
|
||||
assertTrue(_powerOf2Bigger(result + 1, input));
|
||||
}
|
||||
}
|
||||
|
||||
function _powerOf2Bigger(uint256 value, uint256 ref) private pure returns (bool) {
|
||||
return value >= 256 || 2**value > ref; // 2**256 overflows uint256
|
||||
}
|
||||
|
||||
function _powerOf2Smaller(uint256 value, uint256 ref) private pure returns (bool) {
|
||||
return 2**value < ref;
|
||||
}
|
||||
|
||||
// LOG10
|
||||
function testLog10(uint256 input, uint8 r) public {
|
||||
Math.Rounding rounding = _asRounding(r);
|
||||
|
||||
uint256 result = Math.log10(input, rounding);
|
||||
|
||||
if (input == 0) {
|
||||
assertEq(result, 0);
|
||||
} else if (_powerOf10Bigger(result, input)) {
|
||||
assertTrue(rounding == Math.Rounding.Up);
|
||||
assertTrue(_powerOf10Smaller(result - 1, input));
|
||||
} else if (_powerOf10Smaller(result, input)) {
|
||||
assertFalse(rounding == Math.Rounding.Up);
|
||||
assertTrue(_powerOf10Bigger(result + 1, input));
|
||||
}
|
||||
}
|
||||
|
||||
function _powerOf10Bigger(uint256 value, uint256 ref) private pure returns (bool) {
|
||||
return value >= 78 || 10**value > ref; // 10**78 overflows uint256
|
||||
}
|
||||
|
||||
function _powerOf10Smaller(uint256 value, uint256 ref) private pure returns (bool) {
|
||||
return 10**value < ref;
|
||||
}
|
||||
|
||||
// LOG256
|
||||
function testLog256(uint256 input, uint8 r) public {
|
||||
Math.Rounding rounding = _asRounding(r);
|
||||
|
||||
uint256 result = Math.log256(input, rounding);
|
||||
|
||||
if (input == 0) {
|
||||
assertEq(result, 0);
|
||||
} else if (_powerOf256Bigger(result, input)) {
|
||||
assertTrue(rounding == Math.Rounding.Up);
|
||||
assertTrue(_powerOf256Smaller(result - 1, input));
|
||||
} else if (_powerOf256Smaller(result, input)) {
|
||||
assertFalse(rounding == Math.Rounding.Up);
|
||||
assertTrue(_powerOf256Bigger(result + 1, input));
|
||||
}
|
||||
}
|
||||
|
||||
function _powerOf256Bigger(uint256 value, uint256 ref) private pure returns (bool) {
|
||||
return value >= 32 || 256**value > ref; // 256**32 overflows uint256
|
||||
}
|
||||
|
||||
function _powerOf256Smaller(uint256 value, uint256 ref) private pure returns (bool) {
|
||||
return 256**value < ref;
|
||||
}
|
||||
|
||||
// Helpers
|
||||
function _asRounding(uint8 r) private returns (Math.Rounding) {
|
||||
vm.assume(r < uint8(type(Math.Rounding).max));
|
||||
return Math.Rounding(r);
|
||||
}
|
||||
}
|
||||
@ -185,35 +185,128 @@ contract('Math', function (accounts) {
|
||||
|
||||
describe('sqrt', function () {
|
||||
it('rounds down', async function () {
|
||||
expect(await this.math.sqrt(new BN('0'), Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.sqrt(new BN('1'), Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.sqrt(new BN('2'), Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.sqrt(new BN('3'), Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.sqrt(new BN('4'), Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.sqrt(new BN('144'), Rounding.Down)).to.be.bignumber.equal('12');
|
||||
expect(await this.math.sqrt(new BN('999999'), Rounding.Down)).to.be.bignumber.equal('999');
|
||||
expect(await this.math.sqrt(new BN('1000000'), Rounding.Down)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt(new BN('1000001'), Rounding.Down)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt(new BN('1002000'), Rounding.Down)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt(new BN('1002001'), Rounding.Down)).to.be.bignumber.equal('1001');
|
||||
expect(await this.math.sqrt('0', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.sqrt('1', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.sqrt('2', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.sqrt('3', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.sqrt('4', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.sqrt('144', Rounding.Down)).to.be.bignumber.equal('12');
|
||||
expect(await this.math.sqrt('999999', Rounding.Down)).to.be.bignumber.equal('999');
|
||||
expect(await this.math.sqrt('1000000', Rounding.Down)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt('1000001', Rounding.Down)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt('1002000', Rounding.Down)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt('1002001', Rounding.Down)).to.be.bignumber.equal('1001');
|
||||
expect(await this.math.sqrt(MAX_UINT256, Rounding.Down))
|
||||
.to.be.bignumber.equal('340282366920938463463374607431768211455');
|
||||
});
|
||||
|
||||
it('rounds up', async function () {
|
||||
expect(await this.math.sqrt(new BN('0'), Rounding.Up)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.sqrt(new BN('1'), Rounding.Up)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.sqrt(new BN('2'), Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.sqrt(new BN('3'), Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.sqrt(new BN('4'), Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.sqrt(new BN('144'), Rounding.Up)).to.be.bignumber.equal('12');
|
||||
expect(await this.math.sqrt(new BN('999999'), Rounding.Up)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt(new BN('1000000'), Rounding.Up)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt(new BN('1000001'), Rounding.Up)).to.be.bignumber.equal('1001');
|
||||
expect(await this.math.sqrt(new BN('1002000'), Rounding.Up)).to.be.bignumber.equal('1001');
|
||||
expect(await this.math.sqrt(new BN('1002001'), Rounding.Up)).to.be.bignumber.equal('1001');
|
||||
expect(await this.math.sqrt('0', Rounding.Up)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.sqrt('1', Rounding.Up)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.sqrt('2', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.sqrt('3', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.sqrt('4', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.sqrt('144', Rounding.Up)).to.be.bignumber.equal('12');
|
||||
expect(await this.math.sqrt('999999', Rounding.Up)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt('1000000', Rounding.Up)).to.be.bignumber.equal('1000');
|
||||
expect(await this.math.sqrt('1000001', Rounding.Up)).to.be.bignumber.equal('1001');
|
||||
expect(await this.math.sqrt('1002000', Rounding.Up)).to.be.bignumber.equal('1001');
|
||||
expect(await this.math.sqrt('1002001', Rounding.Up)).to.be.bignumber.equal('1001');
|
||||
expect(await this.math.sqrt(MAX_UINT256, Rounding.Up))
|
||||
.to.be.bignumber.equal('340282366920938463463374607431768211456');
|
||||
});
|
||||
});
|
||||
|
||||
describe('log', function () {
|
||||
describe('log2', function () {
|
||||
it('rounds down', async function () {
|
||||
expect(await this.math.log2('0', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log2('1', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log2('2', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log2('3', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log2('4', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log2('5', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log2('6', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log2('7', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log2('8', Rounding.Down)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log2('9', Rounding.Down)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log2(MAX_UINT256, Rounding.Down)).to.be.bignumber.equal('255');
|
||||
});
|
||||
|
||||
it('rounds up', async function () {
|
||||
expect(await this.math.log2('0', Rounding.Up)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log2('1', Rounding.Up)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log2('2', Rounding.Up)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log2('3', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log2('4', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log2('5', Rounding.Up)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log2('6', Rounding.Up)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log2('7', Rounding.Up)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log2('8', Rounding.Up)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log2(MAX_UINT256, Rounding.Up)).to.be.bignumber.equal('256');
|
||||
});
|
||||
});
|
||||
|
||||
describe('log10', function () {
|
||||
it('rounds down', async function () {
|
||||
expect(await this.math.log10('0', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log10('1', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log10('2', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log10('9', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log10('10', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log10('11', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log10('99', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log10('100', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log10('101', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log10('999', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log10('1000', Rounding.Down)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log10('1001', Rounding.Down)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log10(MAX_UINT256, Rounding.Down)).to.be.bignumber.equal('77');
|
||||
});
|
||||
|
||||
it('rounds up', async function () {
|
||||
expect(await this.math.log10('0', Rounding.Up)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log10('1', Rounding.Up)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log10('2', Rounding.Up)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log10('9', Rounding.Up)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log10('10', Rounding.Up)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log10('11', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log10('99', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log10('100', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log10('101', Rounding.Up)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log10('999', Rounding.Up)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log10('1000', Rounding.Up)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log10('1001', Rounding.Up)).to.be.bignumber.equal('4');
|
||||
expect(await this.math.log10(MAX_UINT256, Rounding.Up)).to.be.bignumber.equal('78');
|
||||
});
|
||||
});
|
||||
|
||||
describe('log256', function () {
|
||||
it('rounds down', async function () {
|
||||
expect(await this.math.log256('0', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log256('1', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log256('2', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log256('255', Rounding.Down)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log256('256', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log256('257', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log256('65535', Rounding.Down)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log256('65536', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log256('65537', Rounding.Down)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log256(MAX_UINT256, Rounding.Down)).to.be.bignumber.equal('31');
|
||||
});
|
||||
|
||||
it('rounds up', async function () {
|
||||
expect(await this.math.log256('0', Rounding.Up)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log256('1', Rounding.Up)).to.be.bignumber.equal('0');
|
||||
expect(await this.math.log256('2', Rounding.Up)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log256('255', Rounding.Up)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log256('256', Rounding.Up)).to.be.bignumber.equal('1');
|
||||
expect(await this.math.log256('257', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log256('65535', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log256('65536', Rounding.Up)).to.be.bignumber.equal('2');
|
||||
expect(await this.math.log256('65537', Rounding.Up)).to.be.bignumber.equal('3');
|
||||
expect(await this.math.log256(MAX_UINT256, Rounding.Up)).to.be.bignumber.equal('32');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user