* Divide this value by other one * @this {!UInt64} * @param {!Int64|!UInt64|number|string} other Other value * @returns {!UInt64} Division of two values
(other)
| 1603 | * @returns {!UInt64} Division of two values |
| 1604 | */ |
| 1605 | div (other) { |
| 1606 | if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) { |
| 1607 | other = UInt64.fromValue(other) |
| 1608 | } |
| 1609 | if (other.isZero) { |
| 1610 | throw new Error('Division by zero!') |
| 1611 | } |
| 1612 | |
| 1613 | if (this.isZero) { |
| 1614 | return UINT64_ZERO |
| 1615 | } |
| 1616 | |
| 1617 | let approx, rem, res |
| 1618 | |
| 1619 | // The algorithm below has not been made for unsigned longs. It's therefore required to take special care of |
| 1620 | // the MSB prior to running it. |
| 1621 | if (Int64.isInt64(other)) { |
| 1622 | other = other.toUnsigned() |
| 1623 | } |
| 1624 | if (other.gt(this)) { |
| 1625 | return UINT64_ZERO |
| 1626 | } |
| 1627 | // 15 >>> 1 = 7 ; with divisor = 8 ; true |
| 1628 | if (other.gt(this.shru(1))) { |
| 1629 | return UINT64_ONE |
| 1630 | } |
| 1631 | res = UINT64_ZERO |
| 1632 | |
| 1633 | // Repeat the following until the remainder is less than other: find a floating-point that approximates |
| 1634 | // remainder / other *from below*, add this into the result, and subtract it from the remainder. |
| 1635 | // It is critical that the approximate value is less than or equal to the real value so that the |
| 1636 | // remainder never becomes negative. |
| 1637 | rem = this |
| 1638 | while (rem.gte(other)) { |
| 1639 | // Approximate the result of division. This may be a little greater or smaller than the actual value |
| 1640 | approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())) |
| 1641 | |
| 1642 | // We will tweak the approximate result by changing it in the 48-th digit or the smallest non-fractional |
| 1643 | // digit, whichever is larger. |
| 1644 | let log2 = Math.ceil(Math.log(approx) / Math.LN2) |
| 1645 | let delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48) |
| 1646 | |
| 1647 | // Decrease the approximation until it is smaller than the remainder. |
| 1648 | // Note that if it is too large, the product overflows and is negative. |
| 1649 | let approxRes = Int64.fromNumber(approx) |
| 1650 | let approxRem = approxRes.mul(other) |
| 1651 | while (approxRem.isNegative || approxRem.gt(rem)) { |
| 1652 | approx -= delta |
| 1653 | approxRes = UInt64.fromNumber(approx) |
| 1654 | approxRem = approxRes.mul(other) |
| 1655 | } |
| 1656 | |
| 1657 | // We know the answer can't be zero... and actually, zero would cause infinite recursion since |
| 1658 | // we would make no progress. |
| 1659 | if (approxRes.isZero) { |
| 1660 | approxRes = UINT64_ONE |
| 1661 | } |
| 1662 |