Skip to content

Commit

Permalink
Merge 01e9a14 into 511accc
Browse files Browse the repository at this point in the history
  • Loading branch information
alcueca committed Jun 5, 2020
2 parents 511accc + 01e9a14 commit b91c418
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
66 changes: 66 additions & 0 deletions contracts/math/DecimalMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,70 @@ library DecimalMath {
{
return x.mul(int(unit(decimals))).div(y);
}

/// @dev Divides x between y, rounding to the closes representable number.
/// Assumes x and y are both fixed point with 18 digits.
function divdr(uint256 x, uint256 y) internal pure returns (uint256) {
return divdr(x, y, 18);
}

/// @dev Divides x between y, rounding to the closes representable number.
/// Assumes x and y are both fixed point with 18 digits.
function divdr(int256 x, int256 y) internal pure returns (int256) {
return divdr(x, y, 18);
}

/// @dev Divides x between y, rounding to the closest representable number.
/// Assumes x and y are both fixed point with `decimals` digits.
function divdr(uint256 x, uint256 y, uint8 decimals)
internal pure returns (uint256)
{
uint256 z = x.mul(unit(decimals + 1)).div(y);
if (z % 10 > 5) return z / 10 + 1;
else return z / 10;
}

/// @dev Divides x between y, rounding to the closest representable number.
/// Assumes x and y are both fixed point with `decimals` digits.
function divdr(int256 x, int256 y, uint8 decimals)
internal pure returns (int256)
{
int256 z = x.mul(int256(unit(decimals + 1))).div(y);
if (z % 10 > 5) return z / 10 + 1;
else if (z % 10 < -5) return z / 10 - 1;
else return z / 10;
}

/// @dev Divides x between y, rounding to the closes representable number.
/// Assumes x and y are both fixed point with 18 digits.
function divdrup(uint256 x, uint256 y) internal pure returns (uint256) {
return divdrup(x, y, 18);
}

/// @dev Divides x between y, rounding to the closes representable number.
/// Assumes x and y are both fixed point with 18 digits.
function divdrup(int256 x, int256 y) internal pure returns (int256) {
return divdrup(x, y, 18);
}

/// @dev Divides x between y, rounding to the closest representable number.
/// Assumes x and y are both fixed point with `decimals` digits.
function divdrup(uint256 x, uint256 y, uint8 decimals)
internal pure returns (uint256)
{
uint256 z = x.mul(unit(decimals + 1)).div(y);
if (z % 10 > 0) return z / 10 + 1;
else return z / 10;
}

/// @dev Divides x between y, rounding to the closest representable number.
/// Assumes x and y are both fixed point with `decimals` digits.
function divdrup(int256 x, int256 y, uint8 decimals)
internal pure returns (int256)
{
int256 z = x.mul(int256(unit(decimals + 1))).div(y);
if (z % 10 > 0) return z / 10 + 1;
else if (z % 10 < 0) return z / 10 - 1;
else return z / 10;
}
}
48 changes: 48 additions & 0 deletions contracts/test/math/DecimalMathMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,52 @@ contract DecimalMathMock {
{
return x.divd(y, decimals);
}

function divdr(uint256 x, uint256 y)
public virtual pure returns (uint256)
{
return x.divdr(y);
}

function divdrInt(int256 x, int256 y)
public virtual pure returns (int256)
{
return x.divdr(y);
}

function divdr2(uint256 x, uint256 y, uint8 decimals)
public virtual pure returns (uint256)
{
return x.divdr(y, decimals);
}

function divdr2Int(int256 x, int256 y, uint8 decimals)
public virtual pure returns (int256)
{
return x.divdr(y, decimals);
}

function divdrup(uint256 x, uint256 y)
public virtual pure returns (uint256)
{
return x.divdrup(y);
}

function divdrupInt(int256 x, int256 y)
public virtual pure returns (int256)
{
return x.divdrup(y);
}

function divdrup2(uint256 x, uint256 y, uint8 decimals)
public virtual pure returns (uint256)
{
return x.divdrup(y, decimals);
}

function divdrup2Int(int256 x, int256 y, uint8 decimals)
public virtual pure returns (int256)
{
return x.divdrup(y, decimals);
}
}
56 changes: 56 additions & 0 deletions test/math/DecimalMath.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ contract('DecimalMath', () => {
let decimal1_18: BN;
let decimal2_18: BN;
let decimal3_18: BN;
let decimal4_18: BN;
let decimal6_18: BN;
let decimal1_16: BN;
let decimal2_16: BN;
Expand All @@ -30,6 +31,7 @@ contract('DecimalMath', () => {
decimal1_18 = new BN(await tokenMath.unit(decimals18.toString()));
decimal2_18 = decimal1_18.mul(new BN('2'));
decimal3_18 = decimal1_18.mul(new BN('3'));
decimal4_18 = decimal1_18.mul(new BN('4'));
decimal6_18 = decimal1_18.mul(new BN('6'));
decimal1_16 = new BN(await tokenMath.unit(decimals16.toString()));
decimal2_16 = decimal1_16.mul(new BN('2'));
Expand Down Expand Up @@ -128,4 +130,58 @@ contract('DecimalMath', () => {
decimals16.toString(),
)).should.be.bignumber.equal(decimal2_16.mul(minus1));
});

/**
* @test {DecimalMath#divdr()}
*/
it('divides decimal values, rounding away from zero to the closest representable number.', async () => {
BN(await tokenMath.divdr(
decimal4_18.toString(),
decimal6_18.toString(),
)).should.be.bignumber.equal(new BN('666666666666666667'));
BN(await tokenMath.divdrInt(
decimal4_18.toString(),
decimal6_18.toString(),
)).should.be.bignumber.equal(new BN('666666666666666667'));
BN(await tokenMath.divdrInt(
decimal4_18.mul(minus1).toString(),
decimal6_18.toString(),
)).should.be.bignumber.equal((new BN('666666666666666667')).mul(minus1));
});

/**
* @test {DecimalMath#divdr()}
*/
it('divides decimal values, rounding towards zero to the closest representable number.', async () => {
BN(await tokenMath.divdr(
decimal2_18.toString(),
decimal6_18.toString(),
)).should.be.bignumber.equal(new BN('333333333333333333'));
BN(await tokenMath.divdrInt(
decimal2_18.toString(),
decimal6_18.toString(),
)).should.be.bignumber.equal(new BN('333333333333333333'));
BN(await tokenMath.divdrInt(
decimal2_18.mul(minus1).toString(),
decimal6_18.toString(),
)).should.be.bignumber.equal((new BN('333333333333333333')).mul(minus1));
});

/**
* @test {DecimalMath#divdr()}
*/
it('divides decimal values, rounding towards zero to the closest representable number.', async () => {
BN(await tokenMath.divdrup(
decimal2_18.toString(),
decimal6_18.toString(),
)).should.be.bignumber.equal(new BN('333333333333333334'));
BN(await tokenMath.divdrupInt(
decimal2_18.toString(),
decimal6_18.toString(),
)).should.be.bignumber.equal(new BN('333333333333333334'));
BN(await tokenMath.divdrupInt(
decimal2_18.mul(minus1).toString(),
decimal6_18.toString(),
)).should.be.bignumber.equal((new BN('333333333333333334')).mul(minus1));
});
});

0 comments on commit b91c418

Please sign in to comment.