github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/test/contracts/uniswap/v2/FixedPoint.sol (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 pragma solidity >=0.4.0; 3 4 import './FullMath.sol'; 5 import './Babylonian.sol'; 6 import './BitMath.sol'; 7 8 // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) 9 library FixedPoint { 10 // range: [0, 2**112 - 1] 11 // resolution: 1 / 2**112 12 struct uq112x112 { 13 uint224 _x; 14 } 15 16 // range: [0, 2**144 - 1] 17 // resolution: 1 / 2**112 18 struct uq144x112 { 19 uint256 _x; 20 } 21 22 uint8 public constant RESOLUTION = 112; 23 uint256 public constant Q112 = 0x10000000000000000000000000000; // 2**112 24 uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000; // 2**224 25 uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits) 26 27 // encode a uint112 as a UQ112x112 28 function encode(uint112 x) internal pure returns (uq112x112 memory) { 29 return uq112x112(uint224(x) << RESOLUTION); 30 } 31 32 // encodes a uint144 as a UQ144x112 33 function encode144(uint144 x) internal pure returns (uq144x112 memory) { 34 return uq144x112(uint256(x) << RESOLUTION); 35 } 36 37 // decode a UQ112x112 into a uint112 by truncating after the radix point 38 function decode(uq112x112 memory self) internal pure returns (uint112) { 39 return uint112(self._x >> RESOLUTION); 40 } 41 42 // decode a UQ144x112 into a uint144 by truncating after the radix point 43 function decode144(uq144x112 memory self) internal pure returns (uint144) { 44 return uint144(self._x >> RESOLUTION); 45 } 46 47 // multiply a UQ112x112 by a uint, returning a UQ144x112 48 // reverts on overflow 49 function mul(uq112x112 memory self, uint256 y) internal pure returns (uq144x112 memory) { 50 uint256 z = 0; 51 require(y == 0 || (z = self._x * y) / y == self._x, 'FixedPoint::mul: overflow'); 52 return uq144x112(z); 53 } 54 55 // multiply a UQ112x112 by an int and decode, returning an int 56 // reverts on overflow 57 function muli(uq112x112 memory self, int256 y) internal pure returns (int256) { 58 uint256 z = FullMath.mulDiv(self._x, uint256(y < 0 ? -y : y), Q112); 59 require(z < 2**255, 'FixedPoint::muli: overflow'); 60 return y < 0 ? -int256(z) : int256(z); 61 } 62 63 // multiply a UQ112x112 by a UQ112x112, returning a UQ112x112 64 // lossy 65 function muluq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) { 66 if (self._x == 0 || other._x == 0) { 67 return uq112x112(0); 68 } 69 uint112 upper_self = uint112(self._x >> RESOLUTION); // * 2^0 70 uint112 lower_self = uint112(self._x & LOWER_MASK); // * 2^-112 71 uint112 upper_other = uint112(other._x >> RESOLUTION); // * 2^0 72 uint112 lower_other = uint112(other._x & LOWER_MASK); // * 2^-112 73 74 // partial products 75 uint224 upper = uint224(upper_self) * upper_other; // * 2^0 76 uint224 lower = uint224(lower_self) * lower_other; // * 2^-224 77 uint224 uppers_lowero = uint224(upper_self) * lower_other; // * 2^-112 78 uint224 uppero_lowers = uint224(upper_other) * lower_self; // * 2^-112 79 80 // so the bit shift does not overflow 81 require(upper <= uint112(-1), 'FixedPoint::muluq: upper overflow'); 82 83 // this cannot exceed 256 bits, all values are 224 bits 84 uint256 sum = uint256(upper << RESOLUTION) + uppers_lowero + uppero_lowers + (lower >> RESOLUTION); 85 86 // so the cast does not overflow 87 require(sum <= uint224(-1), 'FixedPoint::muluq: sum overflow'); 88 89 return uq112x112(uint224(sum)); 90 } 91 92 // divide a UQ112x112 by a UQ112x112, returning a UQ112x112 93 function divuq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) { 94 require(other._x > 0, 'FixedPoint::divuq: division by zero'); 95 if (self._x == other._x) { 96 return uq112x112(uint224(Q112)); 97 } 98 if (self._x <= uint144(-1)) { 99 uint256 value = (uint256(self._x) << RESOLUTION) / other._x; 100 require(value <= uint224(-1), 'FixedPoint::divuq: overflow'); 101 return uq112x112(uint224(value)); 102 } 103 104 uint256 result = FullMath.mulDiv(Q112, self._x, other._x); 105 require(result <= uint224(-1), 'FixedPoint::divuq: overflow'); 106 return uq112x112(uint224(result)); 107 } 108 109 // returns a UQ112x112 which represents the ratio of the numerator to the denominator 110 // can be lossy 111 function fraction(uint256 numerator, uint256 denominator) internal pure returns (uq112x112 memory) { 112 require(denominator > 0, 'FixedPoint::fraction: division by zero'); 113 if (numerator == 0) return FixedPoint.uq112x112(0); 114 115 if (numerator <= uint144(-1)) { 116 uint256 result = (numerator << RESOLUTION) / denominator; 117 require(result <= uint224(-1), 'FixedPoint::fraction: overflow'); 118 return uq112x112(uint224(result)); 119 } else { 120 uint256 result = FullMath.mulDiv(numerator, Q112, denominator); 121 require(result <= uint224(-1), 'FixedPoint::fraction: overflow'); 122 return uq112x112(uint224(result)); 123 } 124 } 125 126 // take the reciprocal of a UQ112x112 127 // reverts on overflow 128 // lossy 129 function reciprocal(uq112x112 memory self) internal pure returns (uq112x112 memory) { 130 require(self._x != 0, 'FixedPoint::reciprocal: reciprocal of zero'); 131 require(self._x != 1, 'FixedPoint::reciprocal: overflow'); 132 return uq112x112(uint224(Q224 / self._x)); 133 } 134 135 // square root of a UQ112x112 136 // lossy between 0/1 and 40 bits 137 function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) { 138 if (self._x <= uint144(-1)) { 139 return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << 112))); 140 } 141 142 uint8 safeShiftBits = 255 - BitMath.mostSignificantBit(self._x); 143 safeShiftBits -= safeShiftBits % 2; 144 return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << safeShiftBits) << ((112 - safeShiftBits) / 2))); 145 } 146 }