"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.roundTo = exports.sum = exports.rad2deg = exports.deg2rad = exports.getFiniteScaleIndexForScale = exports.getClosestScaleIndex = exports.scaleRangeBetween = exports.areNumbersEqual = exports.restrictToRange = void 0;
var SHIM_EPSILON = Math.pow(2, -52);
function epsilon() {
    var num = Number;
    return num.EPSILON || SHIM_EPSILON;
}
/**
 * Restricts the given number to the given range
 *
 * @export
 * @param {number} val
 * @param {number} lower
 * @param {number} upper
 */
function restrictToRange(val, lower, upper) {
    return Math.min(Math.max(val, lower), upper);
}
exports.restrictToRange = restrictToRange;
/**
 * Indicates if the given numbers are equal
 *
 * @export
 * @param {number} a
 * @param {number} b
 * @returns {boolean}
 */
function areNumbersEqual(a, b) {
    return Math.abs(a - b) < epsilon();
}
exports.areNumbersEqual = areNumbersEqual;
/**
 * Indicates if the given scale is within the specified range
 *
 * @export
 * @param {number} scale
 * @param {number} minScale
 * @param {number} maxScale
 * @returns {boolean}
 */
function scaleRangeBetween(scale, minScale, maxScale) {
    //Note the '<'. This is the same range check used in MapGuide Server
    return scale >= minScale && scale < maxScale;
}
exports.scaleRangeBetween = scaleRangeBetween;
/**
 * Gets the closest scale index for the given scale and scale array pair
 *
 * @export
 * @param {[number, number]} scales
 * @param {number} scale
 * @returns {number}
 */
function getClosestScaleIndex(scales, scale) {
    var d1 = Math.abs(scales[0] - scale);
    var d2 = Math.abs(scales[1] - scale);
    if (d1 < d2)
        return 0;
    else
        return 1;
}
exports.getClosestScaleIndex = getClosestScaleIndex;
/**
 * Gets the applicable finite scale index for the given scale and finite scale array
 *
 * @export
 * @param {number[]} finiteScaleList
 * @param {number} scale
 * @returns {number}
 */
function getFiniteScaleIndexForScale(finiteScaleList, scale) {
    for (var i = 0; i < finiteScaleList.length; i++) {
        if (scale >= finiteScaleList[i]) { //Found the lower bound
            if ((i + 1) < finiteScaleList.length) { //There is a possible upper bound
                if (scale <= finiteScaleList[i + 1]) { //It is the upper bound
                    var test_1 = [finiteScaleList[i], finiteScaleList[i + 1]];
                    //Snap to the scale with lowest difference
                    var testIndex = getClosestScaleIndex(test_1, scale);
                    if (testIndex == 0) {
                        return i;
                    }
                    else {
                        return i + 1;
                    }
                }
            }
            else { //There is no upper bound (we're at the end), snap to it
                return i;
            }
        }
        else if (scale <= finiteScaleList[i]) {
            if (i > 0) {
                var test_2 = [finiteScaleList[i - 1], finiteScaleList[i]];
                var testIndex = getClosestScaleIndex(test_2, scale);
                if (testIndex == 0) {
                    return i - 1;
                }
                else {
                    return i;
                }
            }
            else {
                return i;
            }
        }
    }
    return 0;
}
exports.getFiniteScaleIndexForScale = getFiniteScaleIndexForScale;
/**
 * Converts the given angle in degrees to radians
 * @param deg The angle in degrees
 */
function deg2rad(deg) {
    return deg * (Math.PI / 180);
}
exports.deg2rad = deg2rad;
/**
 * Converts the given angle in radians to degrees
 * @param radians
 * @since 0.13
 */
function rad2deg(radians) {
    return radians * (180 / Math.PI);
}
exports.rad2deg = rad2deg;
/**
 * Computes the sum of the given array
 *
 * @since 0.11
 * @export
 * @template T
 * @param {T[]} array
 * @param {(item: T) => number} numSelector
 * @returns {number}
 */
function sum(array, numSelector) {
    var total = 0;
    for (var _i = 0, array_1 = array; _i < array_1.length; _i++) {
        var item = array_1[_i];
        total += numSelector(item);
    }
    return total;
}
exports.sum = sum;
/**
 * Rounds the given number to the specified number of decimals
 *
 * @since 0.11
 * @export
 * @param {number} num
 * @param {number} [decimals=2]
 * @returns {number}
 */
function roundTo(num, decimals) {
    if (decimals === void 0) { decimals = 2; }
    var a = Math.pow(10, decimals);
    return Math.round(num * a) / a;
}
exports.roundTo = roundTo;
//# sourceMappingURL=number.js.map