"use strict";
/* eslint-disable no-bitwise */
/**
 * @fileoverview Utility functions for converting tick to sqrt and the opposite.
 */
var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mostSignificantBit = exports.getTickAtSqrtRatio = exports.getSqrtRatioAtTick = exports.POWERS_OF_2 = void 0;
var invariant_1 = __importDefault(require("invariant"));
var jsbi_1 = __importDefault(require("jsbi"));
var constants_1 = require("./constants");
exports.POWERS_OF_2 = [128, 64, 32, 16, 8, 4, 2, 1].map(function (pow) { return [
    pow,
    jsbi_1.default.exponentiate(constants_1.TWO, jsbi_1.default.BigInt(pow)),
]; });
/**
 * Multiplies and right shifts.
 *
 * @param {bigint} val The multiplier.
 * @param {string} mulBy Multiply by.
 * @return {bigint}
 */
function mulShift(val, mulBy) {
    return jsbi_1.default.signedRightShift(jsbi_1.default.multiply(val, jsbi_1.default.BigInt(mulBy)), jsbi_1.default.BigInt(128));
}
/**
 * Returns the sqrt ratio as a Q64.96 for the given tick. The sqrt ratio is
 * computed as sqrt(1.0001)^tick
 *
 * @param {string} tick the tick for which to compute the sqrt ratio.
 * @return {bigint} The SQRT value.
 */
var getSqrtRatioAtTick = function (tick) {
    (0, invariant_1.default)(tick >= constants_1.MIN_TICK && tick <= constants_1.MAX_TICK && Number.isInteger(tick), 'TICK');
    var absTick = tick < 0 ? tick * -1 : tick;
    var ratio = (absTick & 0x1) !== 0
        ? jsbi_1.default.BigInt('0xfffcb933bd6fad37aa2d162d1a594001')
        : jsbi_1.default.BigInt('0x100000000000000000000000000000000');
    if ((absTick & 0x2) !== 0) {
        ratio = mulShift(ratio, '0xfff97272373d413259a46990580e213a');
    }
    if ((absTick & 0x4) !== 0) {
        ratio = mulShift(ratio, '0xfff2e50f5f656932ef12357cf3c7fdcc');
    }
    if ((absTick & 0x8) !== 0) {
        ratio = mulShift(ratio, '0xffe5caca7e10e4e61c3624eaa0941cd0');
    }
    if ((absTick & 0x10) !== 0) {
        ratio = mulShift(ratio, '0xffcb9843d60f6159c9db58835c926644');
    }
    if ((absTick & 0x20) !== 0) {
        ratio = mulShift(ratio, '0xff973b41fa98c081472e6896dfb254c0');
    }
    if ((absTick & 0x40) !== 0) {
        ratio = mulShift(ratio, '0xff2ea16466c96a3843ec78b326b52861');
    }
    if ((absTick & 0x80) !== 0) {
        ratio = mulShift(ratio, '0xfe5dee046a99a2a811c461f1969c3053');
    }
    if ((absTick & 0x100) !== 0) {
        ratio = mulShift(ratio, '0xfcbe86c7900a88aedcffc83b479aa3a4');
    }
    if ((absTick & 0x200) !== 0) {
        ratio = mulShift(ratio, '0xf987a7253ac413176f2b074cf7815e54');
    }
    if ((absTick & 0x400) !== 0) {
        ratio = mulShift(ratio, '0xf3392b0822b70005940c7a398e4b70f3');
    }
    if ((absTick & 0x800) !== 0) {
        ratio = mulShift(ratio, '0xe7159475a2c29b7443b29c7fa6e889d9');
    }
    if ((absTick & 0x1000) !== 0) {
        ratio = mulShift(ratio, '0xd097f3bdfd2022b8845ad8f792aa5825');
    }
    if ((absTick & 0x2000) !== 0) {
        ratio = mulShift(ratio, '0xa9f746462d870fdf8a65dc1f90e061e5');
    }
    if ((absTick & 0x4000) !== 0) {
        ratio = mulShift(ratio, '0x70d869a156d2a1b890bb3df62baf32f7');
    }
    if ((absTick & 0x8000) !== 0) {
        ratio = mulShift(ratio, '0x31be135f97d08fd981231505542fcfa6');
    }
    if ((absTick & 0x10000) !== 0) {
        ratio = mulShift(ratio, '0x9aa508b5b7a84e1c677de54f3e99bc9');
    }
    if ((absTick & 0x20000) !== 0) {
        ratio = mulShift(ratio, '0x5d6af8dedb81196699c329225ee604');
    }
    if ((absTick & 0x40000) !== 0) {
        ratio = mulShift(ratio, '0x2216e584f5fa1ea926041bedfe98');
    }
    if ((absTick & 0x80000) !== 0) {
        ratio = mulShift(ratio, '0x48a170391f7dc42444e8fa2');
    }
    if (tick > 0) {
        ratio = jsbi_1.default.divide(constants_1.MaxUint256, ratio);
    }
    // back to Q96
    var result = jsbi_1.default.greaterThan(jsbi_1.default.remainder(ratio, constants_1.Q32), constants_1.ZERO)
        ? jsbi_1.default.add(jsbi_1.default.divide(ratio, constants_1.Q32), constants_1.ONE)
        : jsbi_1.default.divide(ratio, constants_1.Q32);
    return result;
};
exports.getSqrtRatioAtTick = getSqrtRatioAtTick;
/**
 * Returns the tick corresponding to a given sqrt ratio,
 * s.t. #getSqrtRatioAtTick(tick) <= sqrtRatioX96
 * and #getSqrtRatioAtTick(tick + 1) > sqrtRatioX96
 *
 * @param {string} sqrtRatioX96 the sqrt ratio as a Q64.96 for which to
 *    compute the tick.
 * @return {bigint} JSBI value of the tick.
 */
var getTickAtSqrtRatio = function (sqrtRatioX96) {
    var sqrtRatio = jsbi_1.default.BigInt(sqrtRatioX96);
    (0, invariant_1.default)(jsbi_1.default.greaterThanOrEqual(sqrtRatio, constants_1.MIN_SQRT_RATIO) &&
        jsbi_1.default.lessThan(sqrtRatio, constants_1.MAX_SQRT_RATIO), 'SQRT_RATIO');
    var sqrtRatioX128 = jsbi_1.default.leftShift(sqrtRatio, jsbi_1.default.BigInt(32));
    var msb = (0, exports.mostSignificantBit)(sqrtRatioX128);
    var r;
    if (jsbi_1.default.greaterThanOrEqual(jsbi_1.default.BigInt(msb), jsbi_1.default.BigInt(128))) {
        r = jsbi_1.default.signedRightShift(sqrtRatioX128, jsbi_1.default.BigInt(msb - 127));
    }
    else {
        r = jsbi_1.default.leftShift(sqrtRatioX128, jsbi_1.default.BigInt(127 - msb));
    }
    var log_2 = jsbi_1.default.leftShift(jsbi_1.default.subtract(jsbi_1.default.BigInt(msb), jsbi_1.default.BigInt(128)), jsbi_1.default.BigInt(64));
    for (var i = 0; i < 14; i += 1) {
        r = jsbi_1.default.signedRightShift(jsbi_1.default.multiply(r, r), jsbi_1.default.BigInt(127));
        var f = jsbi_1.default.signedRightShift(r, jsbi_1.default.BigInt(128));
        log_2 = jsbi_1.default.bitwiseOr(log_2, jsbi_1.default.leftShift(f, jsbi_1.default.BigInt(63 - i)));
        r = jsbi_1.default.signedRightShift(r, f);
    }
    var log_sqrt10001 = jsbi_1.default.multiply(log_2, jsbi_1.default.BigInt('255738958999603826347141'));
    var tickLow = jsbi_1.default.toNumber(jsbi_1.default.signedRightShift(jsbi_1.default.subtract(log_sqrt10001, jsbi_1.default.BigInt('3402992956809132418596140100660247210')), jsbi_1.default.BigInt(128)));
    var tickHigh = jsbi_1.default.toNumber(jsbi_1.default.signedRightShift(jsbi_1.default.add(log_sqrt10001, jsbi_1.default.BigInt('291339464771989622907027621153398088495')), jsbi_1.default.BigInt(128)));
    var result = tickLow;
    if (tickLow !== tickHigh &&
        jsbi_1.default.lessThanOrEqual((0, exports.getSqrtRatioAtTick)(tickHigh), sqrtRatioX96)) {
        result = tickHigh;
    }
    return result;
};
exports.getTickAtSqrtRatio = getTickAtSqrtRatio;
/**
 * Calculates the most significant bit.
 *
 * @param {bigint} x The value to calculate for.
 * @return {number} The most significant bit.
 */
var mostSignificantBit = function (x) {
    var e_1, _a;
    (0, invariant_1.default)(jsbi_1.default.greaterThan(x, constants_1.ZERO), 'ZERO');
    (0, invariant_1.default)(jsbi_1.default.lessThanOrEqual(x, constants_1.MaxUint256), 'MAX');
    var msb = 0;
    try {
        for (var POWERS_OF_2_1 = __values(exports.POWERS_OF_2), POWERS_OF_2_1_1 = POWERS_OF_2_1.next(); !POWERS_OF_2_1_1.done; POWERS_OF_2_1_1 = POWERS_OF_2_1.next()) {
            var _b = __read(POWERS_OF_2_1_1.value, 2), power = _b[0], min = _b[1];
            if (jsbi_1.default.greaterThanOrEqual(x, min)) {
                x = jsbi_1.default.signedRightShift(x, jsbi_1.default.BigInt(power));
                msb += power;
            }
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (POWERS_OF_2_1_1 && !POWERS_OF_2_1_1.done && (_a = POWERS_OF_2_1.return)) _a.call(POWERS_OF_2_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
    return msb;
};
exports.mostSignificantBit = mostSignificantBit;
//# sourceMappingURL=tickMath.js.map