pragma solidity ^0.4.24;
import './SafeMath.sol';
/**
presented by: https://github.com/raineorshine/sol-decimal
A Solidity Decimal type.
Usage:
import "./Decimal.sol";
contract A {
using Decimal for Decimal.Data;
function foo() public constant returns(uint) {
Decimal.Data memory a = Decimal.fromUint(5);
Decimal.Data memory b = Decimal.Data({
num: 12,
den: 3
});
return a.add(b).toUint(); // 9
}
}
*/
library Decimal {
using SafeMath for uint256;
/** Creates a Decimal Data from a uint numerator and uint denominator by directly constructing Data. */
struct Data {
uint num; // numerator
uint den; // denomenator
}
// A decimal value can store multiples of 1/DECIMAL_DIVISOR
uint256 public constant DECIMAL_DIVISOR = 10 ** 10;
/** Creates a Decimal Data from a uint. */
function fromUint(uint256 num) internal pure returns (Data memory) {
return Data({
num : num,
den : 1
});
}
/** Creates a Decimal Data from a Decimal bytes. */
function fromDecimal(uint256 num) internal pure returns (Data memory) {
return Data({
num : num,
den : DECIMAL_DIVISOR
});
}
/** Converts a Decimal to a uint (effectively flooring the value). **/
function toUint(Data memory self) internal pure returns (uint256) {
require(self.den > 0, "invalid zero divide.");
return self.num.div(self.den);
}
/** Converts to decimal by increasing up 10 digitsnum. the decimal is fi168x10 **/
function toDecimal(Data memory self) internal pure returns (uint168) {
require(self.den > 0, "invalid zero divide.");
return uint168(self.num.mul(DECIMAL_DIVISOR).div(self.den));
}
/** Adds two Decimals without loss of precision. */
function add(Data memory a, Data memory b) internal pure returns (Data memory) {
return a.den == b.den ?
// if same denomenator, use b.num as-is
Data({
num : a.num.add(b.num),
den : a.den
}) :
// otherwise convert (b) to the same denominator as (a)
Data({
num : a.num.mul(b.den)
.add(b.num.mul(a.den)),
den : a.den * b.den
});
}
/** Subtracts two Decimals without loss of precision. */
function sub(Data memory a, Data memory b) internal pure returns (Data memory) {
return a.den == b.den ?
// if same denomenator, use b.num as-is
Data({
num : a.num.sub(b.num),
den : a.den
}) :
// otherwise convert (b) to the same denominator as (a)
Data({
num : a.num.mul(b.den)
.sub(b.num.mul(a.den)),
den : a.den * b.den
});
}
/** Multiplies two Decimals without loss of precision. */
function mul(Data memory a, Data memory b) internal pure returns (Data memory) {
return Data({
num : a.num.mul(b.num),
den : a.den.mul(b.den)
});
}
/** Divides two Decimals without loss of precision. */
function div(Data memory a, Data memory b) internal pure returns (Data memory) {
return Data({
num : a.num.mul(b.den),
den : b.num.mul(a.den)
});
}
/**
* @dev Compare a to b.
* @return 0 is a < b
* 1 is a = b
* 2 is a > b
*/
function comp(Data memory a, Data memory b) internal pure returns (uint8) {
uint a_num = a.num * b.den;
uint b_num = b.num * a.den;
if (a_num < b_num) {
return 0;
} else if (a_num == b_num) {
return 1;
} else {
return 2;
}
}
/**
* @dev Compare a to 0.
* @return 0 is a < 0
* 1 is a = 0
* 2 is a > 0
*/
function compZero(Data memory a) internal pure returns (uint8) {
if (a.num < 0) {
return 0;
} else if (a.num == 0) {
return 1;
} else {
return 2;
}
}
}