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  }