spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← All files
name: dist/Formulas/Math.js
-rw-r--r--
55974
   1"use strict";
   2exports.__esModule = true;
   3var ArgsChecker_1 = require("../Utilities/ArgsChecker");
   4var TypeConverter_1 = require("../Utilities/TypeConverter");
   5var Filter_1 = require("../Utilities/Filter");
   6var Serializer_1 = require("../Utilities/Serializer");
   7var CriteriaFunctionFactory_1 = require("../Utilities/CriteriaFunctionFactory");
   8var Errors_1 = require("../Errors");
   9var MathHelpers_1 = require("../Utilities/MathHelpers");
  10var Statistical_1 = require("./Statistical");
  11/**
  12 * Returns the greatest common divisor of one or more integers.
  13 * @param values - The values or ranges whose factors to consider in a calculation to find the greatest common divisor.
  14 * @returns {number} greatest common divisor.
  15 * @constructor
  16 */
  17var GCD = function () {
  18    var values = [];
  19    for (var _i = 0; _i < arguments.length; _i++) {
  20        values[_i] = arguments[_i];
  21    }
  22    ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "ABS");
  23    // Credits: Andrew Pociu
  24    for (var r, a, i = values.length - 1, result = values[i]; i;) {
  25        for (a = values[--i]; (r = a % result); a = result, result = r) {
  26            //empty
  27        }
  28    }
  29    return result;
  30};
  31exports.GCD = GCD;
  32/**
  33 * Returns the least common multiple of one or more integers.
  34 * @param values - The values or range whose factors to consider in a calculation to find the least common multiple.
  35 * @returns {number}
  36 * @constructor
  37 */
  38var LCM = function () {
  39    var values = [];
  40    for (var _i = 0; _i < arguments.length; _i++) {
  41        values[_i] = arguments[_i];
  42    }
  43    ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "LCM");
  44    // Credits: Jonas Raoni Soares Silva
  45    var o = Filter_1.Filter.flatten(values);
  46    for (var i, j, n, d, r = 1; (n = o.pop()) !== undefined;) {
  47        while (n > 1) {
  48            if (n % 2) {
  49                for (i = 3, j = Math.floor(Math.sqrt(n)); i <= j && n % i; i += 2) { }
  50                d = (i <= j) ? i : n;
  51            }
  52            else {
  53                d = 2;
  54            }
  55            for (n /= d, r *= d, i = o.length; i; (o[--i] % d) === 0 && (o[i] /= d) === 1 && o.splice(i, 1)) { }
  56        }
  57    }
  58    return r;
  59};
  60exports.LCM = LCM;
  61/**
  62 * Returns the the logarithm of a specified Gamma function, base e (Euler's number).
  63 * @param value - The input number. The natural logarithm of Gamma (value) will be returned. Must be positive.
  64 * @returns {number}
  65 * @constructor
  66 */
  67var GAMMALN = function (value) {
  68    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "GAMMALN");
  69    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
  70    if (x <= 0) {
  71        throw new Errors_1.NumError("Function GAMMALN parameter 1 value is " + x + ". It should be greater than 0.");
  72    }
  73    return MathHelpers_1.gammaln(x);
  74};
  75exports.GAMMALN = GAMMALN;
  76/**
  77 * Returns the absolute value of a number.
  78 * @param value to get the absolute value of.
  79 * @returns {number} absolute value
  80 * @constructor
  81 */
  82var ABS = function (value) {
  83    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ABS");
  84    var v = TypeConverter_1.TypeConverter.valueToNumber(value);
  85    return Math.abs(v);
  86};
  87exports.ABS = ABS;
  88/**
  89 * Returns the inverse cosine of a value, in radians.
  90 * @param value The value for which to calculate the inverse cosine. Must be between -1 and 1, inclusive.
  91 * @returns {number} inverse cosine of value
  92 * @constructor
  93 */
  94var ACOS = function (value) {
  95    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ACOS");
  96    value = TypeConverter_1.TypeConverter.valueToNumber(value);
  97    if (value === -1) {
  98        return Math.PI;
  99    }
 100    else if (value > 1 || value < -1) {
 101        throw new Errors_1.NumError("Function ACOS parameter 1 value is " + value + ". Valid values are between -1 and 1 inclusive.");
 102    }
 103    return Math.acos(value);
 104};
 105exports.ACOS = ACOS;
 106/**
 107 * Returns the inverse hyperbolic cosine of a number.
 108 * @param value The value for which to calculate the inverse hyperbolic cosine. Must be greater than or equal to 1.
 109 * @returns {number} to find the inverse hyperbolic cosine for.
 110 * @constructor
 111 */
 112var ACOSH = function (value) {
 113    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ACOSH");
 114    value = TypeConverter_1.TypeConverter.valueToNumber(value);
 115    if (value < 1) {
 116        throw new Errors_1.NumError("Function ACOSH parameter 1 value is " + value + ". It should be greater than or equal to 1.");
 117    }
 118    return Math.log(value + Math.sqrt(value * value - 1));
 119};
 120exports.ACOSH = ACOSH;
 121/**
 122 * Calculate the hyperbolic arc-cotangent of a value
 123 * @param value number not between -1 and 1 inclusively.
 124 * @returns {number} hyperbolic arc-cotangent
 125 * @constructor
 126 */
 127var ACOTH = function (value) {
 128    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ACOTH");
 129    value = TypeConverter_1.TypeConverter.valueToNumber(value);
 130    if (value <= 1 && value >= -1) {
 131        throw new Errors_1.NumError("Function ACOTH parameter 1 value is " + value + ". Valid values cannot be between -1 and 1 inclusive.");
 132    }
 133    return 0.5 * Math.log((value + 1) / (value - 1));
 134};
 135exports.ACOTH = ACOTH;
 136/**
 137 * Returns the inverse sine of a value, in radians.
 138 * @param value The value for which to calculate the inverse sine. Must be between -1 and 1, inclusive.
 139 * @returns {number} inverse sine of input value
 140 * @constructor
 141 */
 142var ASIN = function (value) {
 143    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ASIN");
 144    value = TypeConverter_1.TypeConverter.valueToNumber(value);
 145    if (value === -1) {
 146        return Math.PI;
 147    }
 148    else if (value > 1 || value < -1) {
 149        throw new Errors_1.NumError("Function ASIN parameter 1 value is " + value + ". Valid values are between -1 and 1 inclusive.");
 150    }
 151    return Math.asin(value);
 152};
 153exports.ASIN = ASIN;
 154/**
 155 * Returns the inverse hyperbolic sine of a number.
 156 * @param value The value for which to calculate the inverse hyperbolic sine.
 157 * @returns {number} inverse hyperbolic sine of input
 158 * @constructor
 159 */
 160var ASINH = function (value) {
 161    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ASINH");
 162    value = TypeConverter_1.TypeConverter.valueToNumber(value);
 163    return Math.log(value + Math.sqrt(value * value + 1));
 164};
 165exports.ASINH = ASINH;
 166/**
 167 * Returns the inverse tangent of a value, in radians.
 168 * @param value The value for which to calculate the inverse tangent.
 169 * @returns {number} inverse tangent of input value
 170 * @constructor
 171 */
 172var ATAN = function (value) {
 173    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ATAN");
 174    value = TypeConverter_1.TypeConverter.valueToNumber(value);
 175    if (value === -1) {
 176        return Math.PI;
 177    }
 178    else if (value > 1 || value < -1) {
 179        throw new Errors_1.NumError("Function ATAN parameter 1 value is " + value + ". Valid values are between -1 and 1 inclusive.");
 180    }
 181    return Math.atan(value);
 182};
 183exports.ATAN = ATAN;
 184/**
 185 * Returns the angle between the x-axis and a line segment from the origin (0,0) to specified coordinate pair (x,y), in radians.
 186 * @param x The x coordinate of the endpoint of the line segment for which to calculate the angle from the x-axis.
 187 * @param y The y coordinate of the endpoint of the line segment for which to calculate the angle from the x-axis.
 188 * @returns {number} angle in radians
 189 * @constructor
 190 */
 191var ATAN2 = function (x, y) {
 192    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "ATAN2");
 193    x = TypeConverter_1.TypeConverter.valueToNumber(x);
 194    y = TypeConverter_1.TypeConverter.valueToNumber(y);
 195    if (x === 0 && y === 0) {
 196        throw new Errors_1.DivZeroError("Evaluation of function ATAN2 caused a divide by zero error.");
 197    }
 198    return Math.atan2(y, x);
 199};
 200exports.ATAN2 = ATAN2;
 201/**
 202 * Returns the inverse hyperbolic tangent of a number.
 203 * @param value The value for which to calculate the inverse hyperbolic tangent. Must be between -1 and 1, exclusive.
 204 * @returns {number} inverse hyperbolic tangent of input
 205 * @constructor
 206 */
 207var ATANH = function (value) {
 208    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ATANH");
 209    value = TypeConverter_1.TypeConverter.valueToNumber(value);
 210    if (value >= 1 || value <= -1) {
 211        throw new Errors_1.NumError("Function ATANH parameter 1 value is " + value + ". Valid values are between -1 and 1 exclusive.");
 212    }
 213    if (Math.abs(value) < 1) {
 214    }
 215    return Math["atanh"](value);
 216};
 217exports.ATANH = ATANH;
 218/**
 219 * Rounds a number up to the nearest even integer.
 220 * @param value The value to round to the next greatest even number.
 221 * @returns {number} next greatest even number
 222 * @constructor
 223 */
 224var EVEN = function (value) {
 225    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "EVEN");
 226    var X = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 227    return X % 2 === 1 ? X + 1 : X;
 228};
 229exports.EVEN = EVEN;
 230/**
 231 * Returns the result of the modulo operator, the remainder after a division operation.
 232 * @param dividend The number to be divided to find the remainder.
 233 * @param divisor The number to divide by.
 234 * @returns {number}
 235 * @constructor
 236 */
 237var MOD = function (dividend, divisor) {
 238    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "MOD");
 239    var oneN = TypeConverter_1.TypeConverter.valueToNumber(dividend);
 240    var twoN = TypeConverter_1.TypeConverter.valueToNumber(divisor);
 241    if (twoN === 0) {
 242        throw new Errors_1.DivZeroError("Function MOD parameter 2 cannot be zero.");
 243    }
 244    return oneN % twoN;
 245};
 246exports.MOD = MOD;
 247/**
 248 * Rounds a number up to the nearest odd integer.
 249 * @param value The value to round to the next greatest odd number.
 250 * @returns {number} value to round up to next greatest odd number.
 251 * @constructor
 252 */
 253var ODD = function (value) {
 254    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ODD");
 255    var X = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 256    return X % 2 === 1 ? X : X + 1;
 257};
 258exports.ODD = ODD;
 259/**
 260 * Returns a number raised to a power.
 261 * @param base - The number to raise to the exponent power.
 262 * @param exponent - The exponent to raise base to.
 263 * @returns {number} resulting number
 264 * @constructor
 265 */
 266var POWER = function (base, exponent) {
 267    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "POWER");
 268    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(base);
 269    var p = TypeConverter_1.TypeConverter.firstValueAsNumber(exponent);
 270    return Math.pow(n, p);
 271};
 272exports.POWER = POWER;
 273/**
 274 * Returns the sum of a series of numbers and/or cells.
 275 * @param values The first number or range to add together.
 276 * @returns {number} The sum of the series
 277 * @constructor
 278 */
 279var SUM = function () {
 280    var values = [];
 281    for (var _i = 0; _i < arguments.length; _i++) {
 282        values[_i] = arguments[_i];
 283    }
 284    ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "SUM");
 285    var result = 0;
 286    for (var i = 0; i < values.length; i++) {
 287        if (values[i] instanceof Array) {
 288            result = result + SUM.apply(this, values[i]);
 289        }
 290        else {
 291            if (values[i] === "") {
 292                throw new Errors_1.ValueError("Function SUM parameter " + i + " expects number values. But '" + values[i] + "' is a text and cannot be coerced to a number.");
 293            }
 294            result = result + TypeConverter_1.TypeConverter.valueToNumber(values[i]);
 295        }
 296    }
 297    return result;
 298};
 299exports.SUM = SUM;
 300/**
 301 * Returns the positive square root of a positive number.
 302 * @param value - The number for which to calculate the positive square root.
 303 * @returns {number} square root
 304 * @constructor
 305 */
 306var SQRT = function (value) {
 307    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "SQRT");
 308    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 309    if (x < 0) {
 310        throw new Errors_1.ValueError("Function SQRT parameter 1 value is " + x + ". It should be greater than or equal to 0.");
 311    }
 312    return Math.sqrt(x);
 313};
 314exports.SQRT = SQRT;
 315/**
 316 * Returns the positive square root of the product of Pi and the given positive number.
 317 * @param value - The number which will be multiplied by Pi and have the product's square root returned
 318 * @returns {number} the positive square root of the product of Pi and the given positive number.
 319 * @constructor
 320 */
 321var SQRTPI = function (value) {
 322    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "SQRTPI");
 323    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 324    if (n < 0) {
 325        throw new Errors_1.NumError("Function SQRTPI parameter 1 value is " + n + ". It should be greater than or equal to 0.");
 326    }
 327    return Math.sqrt(n * Math.PI);
 328};
 329exports.SQRTPI = SQRTPI;
 330/**
 331 * Returns the cosine of an angle provided in radians.
 332 * @param value - The angle to find the cosine of, in radians.
 333 * @returns {number} cosine of angle
 334 * @constructor
 335 */
 336var COS = function (value) {
 337    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "COS");
 338    var r = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 339    return Math.cos(r);
 340};
 341exports.COS = COS;
 342/**
 343 * Returns the hyperbolic cosine of any real number.
 344 * @param value - Any real value to calculate the hyperbolic cosine of.
 345 * @returns {number} the hyperbolic cosine of the input
 346 * @constructor
 347 */
 348var COSH = function (value) {
 349    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "COSH");
 350    var r = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 351    return Math["cosh"](r);
 352};
 353exports.COSH = COSH;
 354/**
 355 * Returns the cotangent of any real number. Defined as cot(x) = 1 / tan(x).
 356 * @param value - number to calculate the cotangent for
 357 * @returns {number} cotangent
 358 * @constructor
 359 */
 360var COT = function (value) {
 361    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "COT");
 362    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 363    if (x === 0) {
 364        throw new Errors_1.DivZeroError("Evaluation of function COT caused a divide by zero error.");
 365    }
 366    return 1 / Math.tan(x);
 367};
 368exports.COT = COT;
 369/**
 370 * Return the hyperbolic cotangent of a value, defined as coth(x) = 1 / tanh(x).
 371 * @param value - value to calculate the hyperbolic cotangent value of
 372 * @returns {number} hyperbolic cotangent
 373 * @constructor
 374 */
 375var COTH = function (value) {
 376    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "COTH");
 377    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 378    if (x === 0) {
 379        throw new Errors_1.DivZeroError("Evaluation of function COTH caused a divide by zero error.");
 380    }
 381    return 1 / Math["tanh"](x);
 382};
 383exports.COTH = COTH;
 384/**
 385 * Rounds a number down to the nearest integer that is less than or equal to it.
 386 * @param value -  The value to round down to the nearest integer.
 387 * @returns {number} Rounded number
 388 * @constructor
 389 */
 390var INT = function (value) {
 391    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "INT");
 392    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 393    return Math.floor(x);
 394};
 395exports.INT = INT;
 396/**
 397 * Checks whether the provided value is even.
 398 * @param value - The value to be verified as even.
 399 * @returns {boolean} whether this value is even or not
 400 * @constructor
 401 */
 402var ISEVEN = function (value) {
 403    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ISEVEN");
 404    if (value === "") {
 405        throw new Errors_1.ValueError("Function ISEVEN parameter 1 expects boolean values. But '" + value + "' is a text and cannot be coerced to a boolean.");
 406    }
 407    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 408    return Math.floor(x) % 2 === 0;
 409};
 410exports.ISEVEN = ISEVEN;
 411/**
 412 * Checks whether the provided value is odd.
 413 * @param value - The value to be verified as odd.
 414 * @returns {boolean} whether this value is odd or not
 415 * @constructor
 416 */
 417var ISODD = function (value) {
 418    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ISODD");
 419    if (value === "") {
 420        throw new Errors_1.ValueError("Function ISODD parameter 1 expects boolean values. But '" + value + "' is a text and cannot be coerced to a boolean.");
 421    }
 422    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 423    return Math.floor(x) % 2 === 1;
 424};
 425exports.ISODD = ISODD;
 426/**
 427 * Returns the sine of an angle provided in radians.
 428 * @param value - The angle to find the sine of, in radians.
 429 * @returns {number} Sine of angle.
 430 * @constructor
 431 */
 432var SIN = function (value) {
 433    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "SIN");
 434    var rad = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 435    return rad === Math.PI ? 0 : Math.sin(rad);
 436};
 437exports.SIN = SIN;
 438/**
 439 * Returns the hyperbolic sine of any real number.
 440 * @param value - real number to find the hyperbolic sine of
 441 * @returns {number} hyperbolic sine
 442 * @constructor
 443 */
 444var SINH = function (value) {
 445    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "SINH");
 446    var rad = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 447    return Math["sinh"](rad);
 448};
 449exports.SINH = SINH;
 450/**
 451 * The value Pi.
 452 * @returns {number} Pi.
 453 * @constructor
 454 */
 455var PI = function () {
 456    ArgsChecker_1.ArgsChecker.checkLength(arguments, 0, "SINH");
 457    return Math.PI;
 458};
 459exports.PI = PI;
 460/**
 461 * Returns the the logarithm of a number, base 10.
 462 * @param value - The value for which to calculate the logarithm, base 10.
 463 * @returns {number} logarithm of the number, in base 10.
 464 * @constructor
 465 */
 466var LOG10 = function (value) {
 467    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "LOG10");
 468    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 469    if (n < 1) {
 470        throw new Errors_1.NumError("Function LOG10 parameter 1 value is " + n + ". It should be greater than 0.");
 471    }
 472    var ln = Math.log(n);
 473    var lb = Math.log(10);
 474    return ln / lb;
 475};
 476exports.LOG10 = LOG10;
 477/**
 478 * Returns the the logarithm of a number given a base.
 479 * @param value - The value for which to calculate the logarithm given base.
 480 * @param base - The base to use for calculation of the logarithm. Defaults to 10.
 481 * @returns {number}
 482 * @constructor
 483 */
 484var LOG = function (value, base) {
 485    ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 2, "LOG");
 486    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 487    var b = TypeConverter_1.TypeConverter.firstValueAsNumber(base);
 488    if (b < 1) {
 489        throw new Errors_1.NumError("Function LOG parameter 2 value is " + b + ". It should be greater than 0.");
 490    }
 491    if (b < 2) {
 492        throw new Errors_1.DivZeroError("Evaluation of function LOG caused a divide by zero error.");
 493    }
 494    var ln = Math.log(n);
 495    var lb = Math.log(b);
 496    if (lb === 0) {
 497        throw new Errors_1.DivZeroError("Evaluation of function LOG caused a divide by zero error.");
 498    }
 499    return ln / lb;
 500};
 501exports.LOG = LOG;
 502/**
 503 * Returns the logarithm of a number, base e (Euler's number).
 504 * @param value - The value for which to calculate the logarithm, base e.
 505 * @returns {number} logarithm calculated
 506 * @constructor
 507 */
 508var LN = function (value) {
 509    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "LN");
 510    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 511    if (n < 1) {
 512        throw new Errors_1.NumError("Function LN parameter 1 value is " + n + ". It should be greater than 0.");
 513    }
 514    return Math.log(n);
 515};
 516exports.LN = LN;
 517/**
 518 * Returns the tangent of an angle provided in radians.
 519 * @param value - The angle to find the tangent of, in radians.
 520 * @returns {number} tangent in radians
 521 * @constructor
 522 */
 523var TAN = function (value) {
 524    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "TAN");
 525    var rad = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 526    return rad === Math.PI ? 0 : Math.tan(rad);
 527};
 528exports.TAN = TAN;
 529/**
 530 * Returns the hyperbolic tangent of any real number.
 531 * @param value - Any real value to calculate the hyperbolic tangent of.
 532 * @returns {number} hyperbolic tangent
 533 * @constructor
 534 */
 535var TANH = function (value) {
 536    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "TANH");
 537    var rad = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 538    return Math["tanh"](rad);
 539};
 540exports.TANH = TANH;
 541/**
 542 * Rounds a number up to the nearest integer multiple of specified significance.
 543 * @param value The value to round up to the nearest integer multiple of factor.
 544 * @param factor - [ OPTIONAL ] The number to whose multiples value will be rounded.
 545 * @returns {number}
 546 * @constructor
 547 */
 548var CEILING = function (value, factor) {
 549    ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 1, 2, "CEILING");
 550    var num = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 551    if (factor === undefined) {
 552        return Math.ceil(num);
 553    }
 554    var significance = TypeConverter_1.TypeConverter.firstValueAsNumber(factor);
 555    if (significance === 0) {
 556        throw new Errors_1.DivZeroError("Function CEILING parameter 2 cannot be zero.");
 557    }
 558    var precision = -Math.floor(Math.log(significance) / Math.log(10));
 559    if (num >= 0) {
 560        return ROUND(Math.ceil(num / significance) * significance, precision);
 561    }
 562    else {
 563        return -ROUND(Math.floor(Math.abs(num) / significance) * significance, precision);
 564    }
 565};
 566exports.CEILING = CEILING;
 567/**
 568 * Rounds a number down to the nearest integer multiple of specified significance.
 569 * @param value - The value to round down to the nearest integer multiple of factor.
 570 * @param factor - The number to whose multiples value will be rounded.
 571 * @returns {number}
 572 * @constructor
 573 */
 574var FLOOR = function (value, factor) {
 575    ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 1, 2, "FLOOR");
 576    var num = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 577    if (factor === undefined) {
 578        return Math.floor(num);
 579    }
 580    var significance = TypeConverter_1.TypeConverter.firstValueAsNumber(factor);
 581    if (significance === 0) {
 582        throw new Errors_1.DivZeroError("Function FLOOR parameter 2 cannot be zero.");
 583    }
 584    significance = significance ? Math.abs(significance) : 1;
 585    var precision = -Math.floor(Math.log(significance) / Math.log(10));
 586    if (num >= 0) {
 587        return ROUND(Math.floor(num / significance) * significance, precision);
 588    }
 589    return -ROUND(Math.floor(Math.abs(num) / significance) * significance, precision);
 590};
 591exports.FLOOR = FLOOR;
 592/**
 593 * Returns one value if a logical expression is TRUE and another if it is FALSE.
 594 * @param logicalExpression - An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE.
 595 * @param valueIfTrue - The value the function returns if logical_expression is TRUE
 596 * @param valueIfFalse - The value the function returns if logical_expression is FALSE.
 597 * @returns one value if a logical expression is TRUE and another if it is FALSE.
 598 * @constructor
 599 */
 600var IF = function (logicalExpression, valueIfTrue, valueIfFalse) {
 601    ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "IF");
 602    if (logicalExpression instanceof Array) {
 603        if (logicalExpression.length === 0) {
 604            throw new Errors_1.RefError("Reference does not exist.");
 605        }
 606        return IF(logicalExpression[0], valueIfTrue, valueIfFalse);
 607    }
 608    else if (logicalExpression === "") {
 609        return valueIfFalse;
 610    }
 611    return (TypeConverter_1.TypeConverter.valueToBoolean(logicalExpression)) ? valueIfTrue : valueIfFalse;
 612};
 613exports.IF = IF;
 614/**
 615 * Returns a conditional count across a range.
 616 * @param range - The range that is tested against criterion., value[1];
 617 * @param criteria - The pattern or test to apply to range. If the range to check against contains text,
 618 * this must be a string. It can be a comparison based string (e.g. "=1", "<1", ">=1") or it can be a wild-card string,
 619 * in which * matches any number of characters, and ? matches the next character. Both ? and * can be escaped by placing
 620 * a ~ in front of them. If it is neither, it will compared with values in the range using equality comparison.
 621 * @returns {number}
 622 * @constructor
 623 */
 624var COUNTIF = function (range, criteria) {
 625    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "COUNTIF");
 626    if (!(range instanceof Array)) {
 627        range = [range];
 628    }
 629    var criteriaEvaluation = CriteriaFunctionFactory_1.CriteriaFunctionFactory.createCriteriaFunction(criteria);
 630    var count = 0;
 631    for (var i = 0; i < range.length; i++) {
 632        var x = range[i];
 633        if (x instanceof Array) {
 634            count = count + COUNTIF.apply(this, [x, criteria]);
 635        }
 636        else if (criteriaEvaluation(x)) {
 637            count++;
 638        }
 639    }
 640    return count;
 641};
 642exports.COUNTIF = COUNTIF;
 643/**
 644 * Returns the count of a range depending on multiple criteria.
 645 * @param values[0] criteria_range1 - The range to check against criterion1.
 646 * @param values[1] criterion1 - The pattern or test to apply to criteria_range1.
 647 * @param values[2...N] Repeated sets of ranges and criterion to check.
 648 * @returns {number} count
 649 * @constructor
 650 */
 651var COUNTIFS = function () {
 652    var values = [];
 653    for (var _i = 0; _i < arguments.length; _i++) {
 654        values[_i] = arguments[_i];
 655    }
 656    ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 2, "COUNTIFS");
 657    var criteriaEvaluationFunctions = values.map(function (criteria, index) {
 658        if (index % 2 === 1) {
 659            return CriteriaFunctionFactory_1.CriteriaFunctionFactory.createCriteriaFunction(criteria);
 660        }
 661        else {
 662            return function () { return false; };
 663        }
 664    });
 665    var filteredValues = [];
 666    // Flatten arrays/ranges
 667    for (var x = 0; x < values.length; x++) {
 668        // If this is an array/range parameter
 669        if (x % 2 === 0) {
 670            filteredValues.push(Filter_1.Filter.flatten(values[x]));
 671        }
 672        else {
 673            filteredValues.push(values[x]);
 674        }
 675    }
 676    var count = 0;
 677    // For every value in the range
 678    for (var i = 0; i < filteredValues[0].length; i++) {
 679        // Check for criteria eval for other ranges and other criteria pairs.
 680        var otherCriteriaEvaluationSuccessfulSoFar = true;
 681        for (var x = 0; x < filteredValues.length; x += 2) {
 682            if (filteredValues[x].length < filteredValues[0].length) {
 683                throw new Errors_1.ValueError("Array arguments to COUNTIFS are of different size.");
 684            }
 685            var criteriaEvaluation = criteriaEvaluationFunctions[x + 1];
 686            if (otherCriteriaEvaluationSuccessfulSoFar) {
 687                if (!criteriaEvaluation(filteredValues[x][i])) { // evaluate THIS value with x+1 index, which is criteria.
 688                    otherCriteriaEvaluationSuccessfulSoFar = false;
 689                }
 690            }
 691        }
 692        if (otherCriteriaEvaluationSuccessfulSoFar) {
 693            count++;
 694        }
 695    }
 696    return count;
 697};
 698exports.COUNTIFS = COUNTIFS;
 699/**
 700 * Rounds a number to a certain number of decimal places according to standard rules.
 701 * @param value - The value to round to places number of places.
 702 * @param places - The number of decimal places to which to round.
 703 * @returns {number}
 704 * @constructor
 705 */
 706var ROUND = function (value, places) {
 707    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "ROUND");
 708    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 709    var d = TypeConverter_1.TypeConverter.firstValueAsNumber(places);
 710    return Math.round(n * Math.pow(10, d)) / Math.pow(10, d);
 711};
 712exports.ROUND = ROUND;
 713/**
 714 * Rounds a number to a certain number of decimal places, always rounding down to the next valid increment.
 715 * @param value - The value to round to places number of places, always rounding down.
 716 * @param places - (optional) The number of decimal places to which to round.
 717 * @returns {number}
 718 * @constructor
 719 */
 720var ROUNDDOWN = function (value, places) {
 721    ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 1, 2, "ROUNDDOWN");
 722    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 723    if (places === undefined) {
 724        return Math.floor(n);
 725    }
 726    var d = TypeConverter_1.TypeConverter.firstValueAsNumber(places);
 727    return Math.floor(n * Math.pow(10, d)) / Math.pow(10, d);
 728};
 729exports.ROUNDDOWN = ROUNDDOWN;
 730/**
 731 * Rounds a number to a certain number of decimal places, always rounding up to the next valid increment.
 732 * @param value - The value to round to places number of places, always rounding up.
 733 * @param places - (optional) The number of decimal places to which to round.
 734 * @returns {number}
 735 * @constructor
 736 */
 737var ROUNDUP = function (value, places) {
 738    ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 1, 2, "ROUNDUP");
 739    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 740    if (places === undefined) {
 741        return Math.ceil(n);
 742    }
 743    var d = TypeConverter_1.TypeConverter.firstValueAsNumber(places);
 744    return Math.ceil(n * Math.pow(10, d)) / Math.pow(10, d);
 745};
 746exports.ROUNDUP = ROUNDUP;
 747/**
 748 * Returns a conditional sum across a range.
 749 * @param range -  The range which is tested against criterion.
 750 * @param criteria - The pattern or test to apply to range. If the range to check against contains text, this must be a
 751 * string. It can be a comparison based string (e.g. "=1", "<1", ">=1") or it can be a wild-card string, in which *
 752 * matches any number of characters, and ? matches the next character. Both ? and * can be escaped by placing a ~ in
 753 * front of them.
 754 * @param sumRange - (optional) The range to be summed, if different from range.
 755 * @returns {number}
 756 * @constructor
 757 */
 758var SUMIF = function (range, criteria, sumRange) {
 759    ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 2, 3, "SUMIF");
 760    var criteriaEvaluation = CriteriaFunctionFactory_1.CriteriaFunctionFactory.createCriteriaFunction(criteria);
 761    var sum = 0;
 762    for (var i = 0; i < range.length; i++) {
 763        var x = range[i];
 764        if (x instanceof Array) {
 765            sum += SUMIF.apply(this, [x, criteria]);
 766        }
 767        else {
 768            if (sumRange && i > sumRange.length - 1) {
 769                continue;
 770            }
 771            if (arguments.length === 2 && TypeConverter_1.TypeConverter.canCoerceToNumber(x) && criteriaEvaluation(x)) {
 772                sum = sum + TypeConverter_1.TypeConverter.valueToNumber(x);
 773            }
 774            else if (arguments.length === 3 && TypeConverter_1.TypeConverter.canCoerceToNumber(sumRange[i]) && criteriaEvaluation(x)) {
 775                sum = sum + TypeConverter_1.TypeConverter.valueToNumber(sumRange[i]);
 776            }
 777        }
 778    }
 779    return sum;
 780};
 781exports.SUMIF = SUMIF;
 782/**
 783 * Returns the sum of the squares of a series of numbers and/or cells.
 784 * @param values  The values or range(s) whose squares to add together.
 785 * @returns {number} the sum of the squares if the input.
 786 * @constructor
 787 */
 788var SUMSQ = function () {
 789    var values = [];
 790    for (var _i = 0; _i < arguments.length; _i++) {
 791        values[_i] = arguments[_i];
 792    }
 793    ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "SUMSQ");
 794    var result = 0;
 795    for (var i = 0; i < values.length; i++) {
 796        if (values[i] instanceof Array) {
 797            if (values[i].length === 0) {
 798                throw new Errors_1.RefError("Reference does not exist.");
 799            }
 800            result = result + SUMSQ.apply(this, Filter_1.Filter.filterOutNonNumberValues(values[i]));
 801        }
 802        else {
 803            var n = TypeConverter_1.TypeConverter.valueToNumber(values[i]);
 804            result = result + (n * n);
 805        }
 806    }
 807    return result;
 808};
 809exports.SUMSQ = SUMSQ;
 810/**
 811 * Returns the product of two numbers. Equivalent to the `*` operator.
 812 * @param factor1 - The first multiplicand.
 813 * @param factor2 - The second multiplicand.
 814 * @constructor
 815 */
 816var MULTIPLY = function (factor1, factor2) {
 817    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "MULTIPLY");
 818    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(factor1);
 819    var y = TypeConverter_1.TypeConverter.firstValueAsNumber(factor2);
 820    return x * y;
 821};
 822exports.MULTIPLY = MULTIPLY;
 823/**
 824 * Returns the result of the first number minus the second number. Equivalent to the `-` operator.
 825 * @param one - The first number.
 826 * @param two - the second number.
 827 * @returns {number}
 828 * @constructor
 829 */
 830var MINUS = function (one, two) {
 831    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "MINUS");
 832    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(one);
 833    var y = TypeConverter_1.TypeConverter.firstValueAsNumber(two);
 834    return x - y;
 835};
 836exports.MINUS = MINUS;
 837/**
 838 * Returns true if two specified values are equal and true otherwise. Equivalent to the "=" operator.
 839 * @param one - First value to check.
 840 * @param two - Second value to check.
 841 * @returns {boolean} true if values are equal, false if they are not equal.
 842 * @constructor
 843 */
 844var EQ = function (one, two) {
 845    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "EQ");
 846    var x = TypeConverter_1.TypeConverter.firstValue(one);
 847    var y = TypeConverter_1.TypeConverter.firstValue(two);
 848    return x === y;
 849};
 850exports.EQ = EQ;
 851/**
 852 * Returns true if the first argument is strictly greater than the second, and false otherwise. Equivalent to the `>`
 853 * operator.
 854 * @param one - The value to test as being greater than `two`.
 855 * @param two - The second value.
 856 * @returns {boolean}
 857 * @constructor
 858 */
 859var GT = function (one, two) {
 860    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "GT");
 861    var x = TypeConverter_1.TypeConverter.firstValue(one);
 862    var y = TypeConverter_1.TypeConverter.firstValue(two);
 863    return x > y;
 864};
 865exports.GT = GT;
 866/**
 867 * Returns true if the first argument is greater than or equal to the second, and false otherwise. Equivalent to the
 868 * `>=` operator.
 869 * @param one - The value to test as being greater than or equal to `two`.
 870 * @param two -The second value.
 871 * @returns {boolean}
 872 * @constructor
 873 */
 874var GTE = function (one, two) {
 875    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "GTE");
 876    var x = TypeConverter_1.TypeConverter.firstValue(one);
 877    var y = TypeConverter_1.TypeConverter.firstValue(two);
 878    return x >= y;
 879};
 880exports.GTE = GTE;
 881/**
 882 * Returns true if the first argument is strictly less than the second, and false otherwise. Equivalent to the `<`
 883 * operator.
 884 * @param one - The value to test as being less than `two`.
 885 * @param two - The second value.
 886 * @returns {boolean}
 887 * @constructor
 888 */
 889var LT = function (one, two) {
 890    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "LT");
 891    var x = TypeConverter_1.TypeConverter.firstValue(one);
 892    var y = TypeConverter_1.TypeConverter.firstValue(two);
 893    return x < y;
 894};
 895exports.LT = LT;
 896/**
 897 * Returns true if the first argument is less than or equal to the second, and true otherwise. Equivalent to the
 898 * `<=` operator.
 899 * @param one - The value to test as being less than or equal to `two`.
 900 * @param two - The second value.
 901 * @constructor
 902 */
 903var LTE = function (one, two) {
 904    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "LTE");
 905    var x = TypeConverter_1.TypeConverter.firstValue(one);
 906    var y = TypeConverter_1.TypeConverter.firstValue(two);
 907    return x <= y;
 908};
 909exports.LTE = LTE;
 910/**
 911 * Returns "TRUE" if two specified values are not equal and "FALSE" otherwise. Equivalent to the "<>" operator.
 912 * @param one - The value to test as being not equal to `two`.
 913 * @param two - The second valud.
 914 * @returns {boolean}
 915 * @constructor
 916 */
 917var NE = function (one, two) {
 918    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "NE");
 919    var x = TypeConverter_1.TypeConverter.firstValue(one);
 920    var y = TypeConverter_1.TypeConverter.firstValue(two);
 921    return x !== y;
 922};
 923exports.NE = NE;
 924/**
 925 * Returns one number divided by another. Equivalent to the `/` operator.
 926 * @param dividend - The number to be divided.
 927 * @param divisor - The number to divide by, cannot be 0.
 928 * @returns {number} result of dividend / divisor.
 929 * @constructor
 930 */
 931var DIVIDE = function (dividend, divisor) {
 932    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "DIVIDE");
 933    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(dividend);
 934    var y = TypeConverter_1.TypeConverter.firstValueAsNumber(divisor);
 935    if (y < 0) {
 936        throw new Errors_1.DivZeroError("Function DIVIDE parameter 2 cannot be zero.");
 937    }
 938    var result = x / y;
 939    if (result == Infinity) {
 940        throw new Errors_1.DivZeroError("Evaluation caused divide by zero error.");
 941    }
 942    else if (isNaN(result)) {
 943        throw new Errors_1.DivZeroError("Evaluation caused divide by zero error.");
 944    }
 945    return result;
 946};
 947exports.DIVIDE = DIVIDE;
 948/**
 949 * Returns a random number between 0 inclusive and 1 exclusive.
 950 * @returns {number}
 951 * @constructor
 952 */
 953var RAND = function () {
 954    ArgsChecker_1.ArgsChecker.checkLength(arguments, 0, "RAND");
 955    return Math.random();
 956};
 957exports.RAND = RAND;
 958/**
 959 * Returns a uniformly random integer between two values, inclusive on high and low. Values with decimal parts may be
 960 * used for low and/or high; this will cause the least and greatest possible values to be the next integer greater than
 961 * low and/or the next integer less than high, respectively.
 962 * @param low - lowest value
 963 * @param high - highest value
 964 * @returns {number} between low and high.
 965 * @constructor
 966 */
 967var RANDBETWEEN = function (low, high) {
 968    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "RAND");
 969    low = Math.floor(TypeConverter_1.TypeConverter.firstValueAsNumber(low));
 970    high = Math.ceil(TypeConverter_1.TypeConverter.firstValueAsNumber(high));
 971    if (low > high) {
 972        throw new Errors_1.NumError("Function RANDBETWEEN parameter 2 value is " + low + ". It should be greater than or equal to "
 973            + high + ".");
 974    }
 975    var diff = Math.abs(low - high);
 976    return Math.round(low + (Math.random() * diff));
 977};
 978exports.RANDBETWEEN = RANDBETWEEN;
 979/**
 980 * Given an input number, returns `-1` if it is negative, `1` if positive, and `0` if it is zero.
 981 * @param value - The value to check the sign for
 982 * @returns {number} `-1` if it is negative, `1` if positive, and `0` if it is zero.
 983 * @constructor
 984 */
 985var SIGN = function (value) {
 986    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "SIGN");
 987    var x = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
 988    if (x === 0) {
 989        return 0;
 990    }
 991    return x > 0 ? 1 : -1;
 992};
 993exports.SIGN = SIGN;
 994/**
 995 * Truncates a number to a certain number of significant digits by omitting less significant digits.
 996 * @param value - The value to be truncated.
 997 * @param places - [ OPTIONAL - 0 by default ] - The number of significant digits to the right of the decimal point to
 998 * retain. If places is greater than the number of significant digits in value, value is returned without modification.
 999 * places may be negative, in which case the specified number of digits to the left of the decimal place are changed to
1000 * zero. All digits to the right of the decimal place are discarded. If all digits of value are changed to zero, TRUNC
1001 * simply returns 0.
1002 * @returns {number} after truncation
1003 * @constructor
1004 */
1005var TRUNC = function (value, places) {
1006    ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 1, 2, "TRUNC");
1007    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
1008    var digits = 0;
1009    if (places !== undefined) {
1010        digits = TypeConverter_1.TypeConverter.firstValueAsNumber(places);
1011    }
1012    var sign = (n > 0) ? 1 : -1;
1013    return sign * (Math.floor(Math.abs(n) * Math.pow(10, digits))) / Math.pow(10, digits);
1014};
1015exports.TRUNC = TRUNC;
1016/**
1017 * Converts an angle value in degrees to radians.
1018 * @param angle - The angle to convert from degrees to radians.
1019 * @returns {number} radians
1020 * @constructor
1021 */
1022var RADIANS = function (angle) {
1023    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "RADIANS");
1024    var d = TypeConverter_1.TypeConverter.firstValueAsNumber(angle);
1025    return d * Math.PI / 180;
1026};
1027exports.RADIANS = RADIANS;
1028/**
1029 * Converts an angle value in radians to degrees.
1030 * @param angle - The angle to convert from radians to degrees.
1031 * @returns {number} degrees
1032 * @constructor
1033 */
1034var DEGREES = function (angle) {
1035    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "DEGREES");
1036    var r = TypeConverter_1.TypeConverter.firstValueAsNumber(angle);
1037    return r * 180 / Math.PI;
1038};
1039exports.DEGREES = DEGREES;
1040/**
1041 * Returns the complementary Gauss error function of a value.
1042 * @param value - The number for which to calculate the complementary Gauss error function.
1043 * @returns {number} complementary Gauss error function of a value
1044 * @constructor
1045 */
1046var ERFC = function (value) {
1047    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ERFC");
1048    var v = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
1049    return v === 0 ? 1 : 1 - MathHelpers_1.erf(v);
1050};
1051exports.ERFC = ERFC;
1052/**
1053 * Returns the error function integrated between lower_limit and upper_limit.
1054 * @param lowerLimit - The lower bound for integrating ERF.
1055 * @param upperLimit - [Optional]. The upper bound for integrating ERF. If omitted, ERF integrates between
1056 * zero and lower_limit.
1057 * @returns {number} error function integrated between lower_limit and upper_limit
1058 * @constructor
1059 */
1060var ERF = function (lowerLimit, upperLimit) {
1061    ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 1, 2, "ERF");
1062    var lower = TypeConverter_1.TypeConverter.firstValueAsNumber(lowerLimit);
1063    var upper = upperLimit !== undefined ? TypeConverter_1.TypeConverter.firstValueAsNumber(upperLimit) : 0;
1064    return upperLimit === undefined ? MathHelpers_1.erf(lower) : MathHelpers_1.erf(upper) - MathHelpers_1.erf(lower);
1065};
1066exports.ERF = ERF;
1067/**
1068 * Calculates the sum of the sums of the squares of values in two arrays.
1069 * @param arrayX - The array or range of values whose squares will be added to the squares of corresponding
1070 * entries in arrayY and added together.
1071 * @param arrayY - The array or range of values whose squares will be added to the squares of corresponding
1072 * entries in arrayX and added together.
1073 * @returns {number} sum of the sums of the squares
1074 * @constructor
1075 */
1076var SUMX2PY2 = function (arrayX, arrayY) {
1077    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "SUMX2PY2");
1078    var arrOne = Filter_1.Filter.flattenAndThrow(arrayX);
1079    var arrTwo = Filter_1.Filter.flattenAndThrow(arrayY);
1080    if (arrOne.length !== arrTwo.length) {
1081        throw new Errors_1.NAError("Array arguments to SUMX2PY2 are of different size.");
1082    }
1083    var result = 0;
1084    for (var i = 0; i < arrOne.length; i++) {
1085        // If either values at this index are anything but numbers, skip them. This is the behavior in GS at least.
1086        if (typeof arrOne[i] === "number" && typeof arrTwo[i] === "number") {
1087            result += arrOne[i] * arrOne[i] + arrTwo[i] * arrTwo[i];
1088        }
1089    }
1090    return result;
1091};
1092exports.SUMX2PY2 = SUMX2PY2;
1093/**
1094 * Calculates the sum of the differences of the squares of values in two arrays.
1095 * @param arrayX - The array or range of values whose squares will be reduced by the squares of corresponding
1096 * entries in array_y and added together.
1097 * @param arrayY - The array or range of values whose squares will be subtracted from the squares of
1098 * corresponding entries in array_x and added together.
1099 * @returns {number} sum of the differences of the squares
1100 * @constructor
1101 */
1102var SUMX2MY2 = function (arrayX, arrayY) {
1103    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "SUMX2MY2");
1104    var arrOne = Filter_1.Filter.flattenAndThrow(arrayX);
1105    var arrTwo = Filter_1.Filter.flattenAndThrow(arrayY);
1106    if (arrOne.length !== arrTwo.length) {
1107        throw new Errors_1.NAError("Array arguments to SUMX2MY2 are of different size.");
1108    }
1109    var result = 0;
1110    for (var i = 0; i < arrOne.length; i++) {
1111        // If either values at this index are anything but numbers, skip them. This is the behavior in GS at least.
1112        if (typeof arrOne[i] === "number" && typeof arrTwo[i] === "number") {
1113            result += arrOne[i] * arrOne[i] - arrTwo[i] * arrTwo[i];
1114        }
1115    }
1116    return result;
1117};
1118exports.SUMX2MY2 = SUMX2MY2;
1119// Private function that will recursively generate an array of the unique primitives
1120var _countUnique = function (values) {
1121    var uniques = {};
1122    for (var i = 0; i < values.length; i++) {
1123        if (Array.isArray(values[i])) {
1124            // For some reasons an empty range is converted to a range with a single empty string in it.
1125            if (values[i].length === 0) {
1126                values[i] = [""];
1127            }
1128            var uniquesOfArray = _countUnique(values[i]);
1129            for (var key in uniquesOfArray) {
1130                uniques[key] = true;
1131            }
1132        }
1133        else {
1134            uniques[Serializer_1.Serializer.serialize(values[i])] = true;
1135        }
1136    }
1137    return uniques;
1138};
1139/**
1140 * Counts the number of unique values in a list of specified values and ranges.
1141 * @param values The values or ranges to consider for uniqueness. Supports an arbitrary number of arguments for this
1142 * function.
1143 * @returns {number} of unique values passed in.
1144 * @constructor
1145 */
1146var COUNTUNIQUE = function () {
1147    var values = [];
1148    for (var _i = 0; _i < arguments.length; _i++) {
1149        values[_i] = arguments[_i];
1150    }
1151    ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "COUNTUNIQUE");
1152    var uniques = _countUnique(values);
1153    return Object.keys(uniques).length;
1154};
1155exports.COUNTUNIQUE = COUNTUNIQUE;
1156/**
1157 * Calculates the sum of the products of corresponding entries in two equal-sized arrays or ranges.
1158 * @param values Arrays or ranges whose entries will be multiplied with corresponding entries in the second such array
1159 * or range.
1160 * @returns {number} sum of the products
1161 * @constructor
1162 */
1163var SUMPRODUCT = function () {
1164    var values = [];
1165    for (var _i = 0; _i < arguments.length; _i++) {
1166        values[_i] = arguments[_i];
1167    }
1168    ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "SUMPRODUCT");
1169    // Ensuring that all values are array values
1170    for (var x = 0; x < values.length; x++) {
1171        if (!Array.isArray(values[x])) {
1172            values[x] = [values[x]];
1173        }
1174    }
1175    // Flatten any nested ranges (arrays) and check for mismatched range sizes
1176    var flattenedValues = [Filter_1.Filter.flattenAndThrow(values[0])];
1177    for (var x = 1; x < values.length; x++) {
1178        flattenedValues.push(Filter_1.Filter.flattenAndThrow(values[x]));
1179        if (flattenedValues[x].length !== flattenedValues[0].length) {
1180            throw new Errors_1.ValueError("SUMPRODUCT has mismatched range sizes. Expected count: "
1181                + flattenedValues[0].length + ". Actual count: " + flattenedValues[0].length + ".");
1182        }
1183    }
1184    // Do the actual math
1185    var result = 0;
1186    for (var i = 0; i < flattenedValues[0].length; i++) {
1187        var product = 1;
1188        for (var x = 0; x < flattenedValues.length; x++) {
1189            product *= TypeConverter_1.TypeConverter.valueToNumberGracefully(flattenedValues[x][i]);
1190        }
1191        result += product;
1192    }
1193    return result;
1194};
1195exports.SUMPRODUCT = SUMPRODUCT;
1196/**
1197 * Returns the number of ways to choose some number of objects from a pool of a given size of objects.
1198 * @param m - The size of the pool of objects to choose from.
1199 * @param k - The number of objects to choose.
1200 * @returns {number} number of ways
1201 * @constructor
1202 */
1203var COMBIN = function (m, k) {
1204    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "COMBIN");
1205    var MEMOIZED_FACT = [];
1206    function fact(number) {
1207        var n = Math.floor(number);
1208        if (n === 0 || n === 1) {
1209            return 1;
1210        }
1211        else if (MEMOIZED_FACT[n] > 0) {
1212            return MEMOIZED_FACT[n];
1213        }
1214        else {
1215            MEMOIZED_FACT[n] = fact(n - 1) * n;
1216            return MEMOIZED_FACT[n];
1217        }
1218    }
1219    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(m);
1220    var c = TypeConverter_1.TypeConverter.firstValueAsNumber(k);
1221    if (n < c) {
1222        throw new Errors_1.NumError("Function COMBIN parameter 2 value is "
1223            + c + ". It should be less than or equal to value of Function COMBIN parameter 1 with " + n + ".");
1224    }
1225    n = Math.floor(n);
1226    c = Math.floor(c);
1227    var div = fact(c) * fact(n - c);
1228    if (div === 0) {
1229        throw new Errors_1.DivZeroError("Evaluation of function COMBIN caused a divide by zero error.");
1230    }
1231    return fact(n) / div;
1232};
1233exports.COMBIN = COMBIN;
1234/**
1235 * Multiply a series of numbers together.
1236 * @param values - values or range of values to multiply by each other.
1237 * @constructor
1238 */
1239var PRODUCT = function () {
1240    var values = [];
1241    for (var _i = 0; _i < arguments.length; _i++) {
1242        values[_i] = arguments[_i];
1243    }
1244    ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 2, "PRODUCT");
1245    var value = 1;
1246    var numbers = Filter_1.Filter.flattenAndThrow(values);
1247    for (var i = 0; i < numbers.length; i++) {
1248        value *= TypeConverter_1.TypeConverter.valueToNumber(numbers[i]);
1249    }
1250    return value;
1251};
1252exports.PRODUCT = PRODUCT;
1253/**
1254 * Divide one number by another
1255 * @param dividend - number to be divided by the divisor.
1256 * @param divisor - number to divide the dividend.
1257 * @returns {number}
1258 * @constructor
1259 */
1260var QUOTIENT = function (dividend, divisor) {
1261    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "QUOTIENT");
1262    var dv = TypeConverter_1.TypeConverter.firstValueAsNumber(dividend);
1263    var ds = TypeConverter_1.TypeConverter.firstValueAsNumber(divisor);
1264    if (ds === 0) {
1265        throw new Errors_1.DivZeroError("Function QUOTIENT parameter 2 cannot be zero.");
1266    }
1267    return dv / ds;
1268};
1269exports.QUOTIENT = QUOTIENT;
1270/**
1271 * Returns a value, but does nothing to it. If given a range, will return first value.
1272 * @param value to return
1273 * @returns any value
1274 * @constructor
1275 */
1276var UPLUS = function (value) {
1277    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "UPLUS");
1278    return TypeConverter_1.TypeConverter.firstValue(value);
1279};
1280exports.UPLUS = UPLUS;
1281/**
1282 * Returns the same number, but with the sign reversed.
1283 * @param value to reverse the sign on
1284 * @returns {number}
1285 * @constructor
1286 */
1287var UMINUS = function (value) {
1288    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "UMINUS");
1289    var n = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
1290    return n * -1;
1291};
1292exports.UMINUS = UMINUS;
1293/**
1294 * Rounds a number to the nearest integer multiple of another.
1295 * @param value - value to round.
1296 * @param factor - multiple.
1297 * @returns {number}
1298 * @constructor
1299 */
1300var MROUND = function (value, factor) {
1301    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "MROUND");
1302    var v = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
1303    var f = TypeConverter_1.TypeConverter.firstValueAsNumber(factor);
1304    if (v * f < 0) {
1305        throw new Errors_1.NumError("Parameters of MROUND must have same signs (both positive or both negative).");
1306    }
1307    if (f === 0) {
1308        return 0;
1309    }
1310    return Math.round(v / f) * f;
1311};
1312exports.MROUND = MROUND;
1313/**
1314 * Calculates the double-factorial of a number.
1315 * @param value - value or reference to calculate.
1316 * @returns {number}
1317 * @constructor
1318 */
1319var FACTDOUBLE = function (value) {
1320    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "FACTDOUBLE");
1321    var n = Math.floor(TypeConverter_1.TypeConverter.firstValueAsNumber(value));
1322    function factDoublePrivate(n) {
1323        if (n <= 0) {
1324            return 1;
1325        }
1326        else {
1327            return n * factDoublePrivate(n - 2);
1328        }
1329    }
1330    if (n === 0) {
1331        return 0;
1332    }
1333    else if (n < 0) {
1334        throw new Errors_1.NumError("Function FACTDOUBLE parameter 1 value is '" + n
1335            + "'. It should be greater than or equal to 0.");
1336    }
1337    else {
1338        return factDoublePrivate(n);
1339    }
1340};
1341exports.FACTDOUBLE = FACTDOUBLE;
1342/**
1343 * Returns a value as a percentage where 100 is 1.0, and 0 is 0.
1344 * @param value - To convert.
1345 * @returns {number}
1346 * @constructor
1347 */
1348var UNARY_PERCENT = function (value) {
1349    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "UNARY_PERCENT");
1350    return TypeConverter_1.TypeConverter.firstValueAsNumber(value) / 100;
1351};
1352exports.UNARY_PERCENT = UNARY_PERCENT;
1353/**
1354 * Returns the factorial of the sum of the arguments divided by the product of the factorials of the arguments.
1355 * @param values - Range of numbers.
1356 * @returns {number}
1357 * @constructor
1358 */
1359var MULTINOMIAL = function () {
1360    var values = [];
1361    for (var _i = 0; _i < arguments.length; _i++) {
1362        values[_i] = arguments[_i];
1363    }
1364    ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "MULTINOMIAL");
1365    values = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber);
1366    var memoizeFact = [];
1367    function _fact(value) {
1368        var n = Math.floor(value);
1369        if (n === 0 || n === 1) {
1370            return 1;
1371        }
1372        else if (memoizeFact[n] > 0) {
1373            return memoizeFact[n];
1374        }
1375        else {
1376            memoizeFact[n] = _fact(n - 1) * n;
1377            return memoizeFact[n];
1378        }
1379    }
1380    var sum = 0;
1381    var divisor = 1;
1382    for (var i = 0; i < values.length; i++) {
1383        sum += arguments[i];
1384        divisor *= _fact(values[i]);
1385    }
1386    return _fact(sum) / divisor;
1387};
1388exports.MULTINOMIAL = MULTINOMIAL;
1389/**
1390 * Returns a sum of powers of the number x in accordance with the following formula.
1391 * @param x - The number as an independent variable.
1392 * @param n - The starting power.
1393 * @param m - The number to increment by
1394 * @param coefficients - A series of coefficients. For each coefficient the series sum is extended by one section. You
1395 * can only enter coefficients using cell references.
1396 * @returns {number}
1397 * @constructor
1398 */
1399var SERIESSUM = function (x, n, m, coefficients) {
1400    ArgsChecker_1.ArgsChecker.checkLength(arguments, 4, "SERIESSUM");
1401    x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
1402    n = TypeConverter_1.TypeConverter.firstValueAsNumber(n);
1403    m = TypeConverter_1.TypeConverter.firstValueAsNumber(m);
1404    coefficients = Filter_1.Filter.flattenAndThrow(coefficients).map(TypeConverter_1.TypeConverter.valueToNumber);
1405    var result = coefficients[0] * Math.pow(x, n);
1406    for (var i = 1; i < coefficients.length; i++) {
1407        result += coefficients[i] * Math.pow(x, n + i * m);
1408    }
1409    return result;
1410};
1411exports.SERIESSUM = SERIESSUM;
1412/**
1413 * Calculates subtotals. If a range already contains subtotals, these are not used for further calculations.
1414 * @param functionCode - A value that stands for another function: 1=AVERAGE, 2=COUNT, 3=COUNTA, 4=MAX, 5=MIN,
1415 * 6=PRODUCT, 7=STDEV, 8=STDEVP, 9=SUM, 10=VAR, 11=VARP.
1416 * @param values - The ranges whose cells are included.
1417 * @returns {Array}
1418 * @constructor
1419 */
1420var SUBTOTAL = function (functionCode) {
1421    var values = [];
1422    for (var _i = 1; _i < arguments.length; _i++) {
1423        values[_i - 1] = arguments[_i];
1424    }
1425    ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 2, "SUBTOTAL");
1426    functionCode = TypeConverter_1.TypeConverter.firstValueAsNumber(functionCode);
1427    values = Filter_1.Filter.flattenAndThrow(values);
1428    switch (functionCode) {
1429        case 1:
1430            return Statistical_1.AVERAGE(values);
1431        case 2:
1432            return Statistical_1.COUNT(values);
1433        case 3:
1434            return Statistical_1.COUNTA(values);
1435        case 4:
1436            return Statistical_1.MAX(values);
1437        case 5:
1438            return Statistical_1.MIN(values);
1439        case 6:
1440            return PRODUCT.apply(this, values);
1441        case 7:
1442            return Statistical_1.STDEV(values);
1443        case 8:
1444            return Statistical_1.STDEVP(values);
1445        case 9:
1446            return SUM(values);
1447        case 10:
1448            return Statistical_1.VAR(values);
1449        case 11:
1450            return Statistical_1.VARP(values);
1451        default:
1452            throw new Errors_1.ValueError("Value '" + functionCode +
1453                "' does not correspond to a function for use in SUBTOTAL. Value should be between 1 to 11.");
1454    }
1455};
1456exports.SUBTOTAL = SUBTOTAL;