pragma solidity >=0.4.0; // taken from https://medium.com/coinmonks/math-in-solidity-part-3-percents-and-proportions-4db014e080b1 // license is CC-BY-4.0 library FullMath { function fullMul(uint256 x, uint256 y) internal pure returns (uint256 l, uint256 h) { uint256 mm = mulmod(x, y, uint256(-1)); l = x * y; h = mm - l; if (mm < l) h -= 1; } function mulDiv( uint256 x, uint256 y, uint256 z ) internal pure returns (uint256) { (uint256 l, uint256 h) = fullMul(x, y); require(h < z); uint256 mm = mulmod(x, y, z); if (mm > l) h -= 1; l -= mm; uint256 pow2 = z & -z; z /= pow2; l /= pow2; l += h * ((-pow2) / pow2 + 1); uint256 r = 1; r *= 2 - z * r; r *= 2 - z * r; r *= 2 - z * r; r *= 2 - z * r; r *= 2 - z * r; r *= 2 - z * r; r *= 2 - z * r; r *= 2 - z * r; return l * r; } }