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;