name:
dist/Formulas/Statistical.js
-rw-r--r--
82814
1"use strict";
2exports.__esModule = true;
3var ArgsChecker_1 = require("../Utilities/ArgsChecker");
4var CriteriaFunctionFactory_1 = require("../Utilities/CriteriaFunctionFactory");
5var Filter_1 = require("../Utilities/Filter");
6var TypeConverter_1 = require("../Utilities/TypeConverter");
7var Errors_1 = require("../Errors");
8var Math_1 = require("./Math");
9var MathHelpers_1 = require("../Utilities/MathHelpers");
10var MoreUtils_1 = require("../Utilities/MoreUtils");
11/**
12 * Calculates the sum of squares of deviations based on a sample.
13 * @param values - The values or ranges of the sample.
14 * @returns {number} sum of squares of deviations
15 * @constructor
16 */
17var DEVSQ = function () {
18 var values = [];
19 for (var _i = 0; _i < arguments.length; _i++) {
20 values[_i] = arguments[_i];
21 }
22 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "DEVSQ");
23 var range = Filter_1.Filter.flattenAndThrow(values);
24 var result = 0;
25 var count = 0;
26 for (var i = 0; i < range.length; i++) {
27 result = result + TypeConverter_1.TypeConverter.valueToNumber(range[i]);
28 count++;
29 }
30 var mean = result / count;
31 result = 0;
32 for (var i = 0; i < range.length; i++) {
33 result += Math.pow((TypeConverter_1.TypeConverter.valueToNumber(range[i]) - mean), 2);
34 }
35 return result;
36};
37exports.DEVSQ = DEVSQ;
38/**
39 * Returns the median value in a numeric dataset.
40 * @param values - The value(s) or range(s) to consider when calculating the median value.
41 * @returns {number} the median value of the dataset
42 * @constructor
43 */
44var MEDIAN = function () {
45 var values = [];
46 for (var _i = 0; _i < arguments.length; _i++) {
47 values[_i] = arguments[_i];
48 }
49 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "MEDIAN");
50 var sortedArray = [];
51 values.forEach(function (currentValue) {
52 if (currentValue instanceof Array) {
53 if (currentValue.length === 0) {
54 throw new Errors_1.RefError("Reference does not exist.");
55 }
56 var filtered = Filter_1.Filter.filterOutStringValues(currentValue);
57 sortedArray = sortedArray.concat(filtered);
58 }
59 else {
60 sortedArray.push(TypeConverter_1.TypeConverter.valueToNumber(currentValue));
61 }
62 });
63 sortedArray = sortedArray.sort(function (a, b) {
64 var aN = TypeConverter_1.TypeConverter.valueToNumber(a);
65 var bN = TypeConverter_1.TypeConverter.valueToNumber(b);
66 return aN - bN;
67 });
68 if (sortedArray.length === 1) {
69 return TypeConverter_1.TypeConverter.valueToNumber(sortedArray[0]);
70 }
71 if (sortedArray.length === 0) {
72 throw new Errors_1.NumError("MEDIAN has no valid input data.");
73 }
74 // even number of values
75 if (sortedArray.length % 2 === 0) {
76 if (sortedArray.length === 2) {
77 return AVERAGE(sortedArray[0], sortedArray[1]);
78 }
79 var top_1 = sortedArray[sortedArray.length / 2];
80 var bottom = sortedArray[(sortedArray.length / 2) - 1];
81 return AVERAGE(top_1, bottom);
82 }
83 else {
84 // odd number of values
85 return sortedArray[Math.round(sortedArray.length / 2) - 1];
86 }
87};
88exports.MEDIAN = MEDIAN;
89/**
90 * Returns the numerical average value in a dataset, ignoring text.
91 * @param values - The values or ranges to consider when calculating the average value.
92 * @returns {number} the average value of this dataset.
93 * @constructor
94 */
95var AVERAGE = function () {
96 var values = [];
97 for (var _i = 0; _i < arguments.length; _i++) {
98 values[_i] = arguments[_i];
99 }
100 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "AVERAGE");
101 var result = 0;
102 var count = 0;
103 for (var i = 0; i < values.length; i++) {
104 if (values[i] instanceof Array) {
105 if (values[i].length === 0) {
106 throw new Errors_1.RefError("Reference does not exist.");
107 }
108 var filtered = Filter_1.Filter.filterOutStringValues(values[i]);
109 result = result + Math_1.SUM.apply(this, filtered);
110 count += filtered.length;
111 }
112 else {
113 result = result + TypeConverter_1.TypeConverter.valueToNumber(values[i]);
114 count++;
115 }
116 }
117 return result / count;
118};
119exports.AVERAGE = AVERAGE;
120/**
121 * Calculates the average of the magnitudes of deviations of data from a dataset's mean.
122 * @param values - The value(s) or range(s)
123 * @returns {number} average of the magnitudes of deviations of data from a dataset's mean
124 * @constructor
125 */
126var AVEDEV = function () {
127 var values = [];
128 for (var _i = 0; _i < arguments.length; _i++) {
129 values[_i] = arguments[_i];
130 }
131 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "AVEDEV");
132 // Sort to array-values, and non-array-values
133 var arrayValues = [];
134 var nonArrayValues = [];
135 for (var i = 0; i < values.length; i++) {
136 var X = values[i];
137 if (X instanceof Array) {
138 if (X.length === 0) {
139 throw new Errors_1.RefError("Reference does not exist.");
140 }
141 arrayValues.push(X);
142 }
143 else {
144 nonArrayValues.push(TypeConverter_1.TypeConverter.valueToNumber(X));
145 }
146 }
147 // Remove string values from array-values, but not from non-array-values, and concat.
148 var flatValues = Filter_1.Filter.filterOutStringValues(Filter_1.Filter.flatten(arrayValues)).map(function (value) {
149 return TypeConverter_1.TypeConverter.valueToNumber(value);
150 }).concat(nonArrayValues);
151 // Calculating mean
152 var result = 0;
153 var count = 0;
154 for (var i = 0; i < flatValues.length; i++) {
155 result = result + TypeConverter_1.TypeConverter.valueToNumber(flatValues[i]);
156 count++;
157 }
158 if (count === 0) {
159 throw new Errors_1.DivZeroError("Evaluation of function AVEDEV caused a devide by zero error.");
160 }
161 var mean = result / count;
162 for (var i = 0; i < flatValues.length; i++) {
163 flatValues[i] = Math_1.ABS(TypeConverter_1.TypeConverter.valueToNumber(flatValues[i]) - mean);
164 }
165 return Math_1.SUM(flatValues) / flatValues.length;
166};
167exports.AVEDEV = AVEDEV;
168/**
169 * Returns the numerical average value in a dataset, coercing text values in ranges to 0 values.
170 * @param values - value(s) or range(s) to consider when calculating the average value.
171 * @returns {number} the numerical average value in a dataset
172 * @constructor
173 */
174var AVERAGEA = function () {
175 var values = [];
176 for (var _i = 0; _i < arguments.length; _i++) {
177 values[_i] = arguments[_i];
178 }
179 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "AVERAGEA");
180 var result = 0;
181 var count = 0;
182 for (var i = 0; i < values.length; i++) {
183 if (values[i] instanceof Array) {
184 if (values[i].length === 0) {
185 throw new Errors_1.RefError("Reference does not exist.");
186 }
187 var filtered = Filter_1.Filter.stringValuesToZeros(values[i]);
188 result = result + Math_1.SUM.apply(this, filtered);
189 count += filtered.length;
190 }
191 else {
192 result = result + TypeConverter_1.TypeConverter.valueToNumber(values[i]);
193 count++;
194 }
195 }
196 if (count === 0) {
197 throw new Errors_1.DivZeroError("Evaluation of function AVEDEV caused a devide by zero error.");
198 }
199 return result / count;
200};
201exports.AVERAGEA = AVERAGEA;
202/**
203 * Calculates r, the Pearson product-moment correlation coefficient of a dataset. Any text encountered in the arguments
204 * will be ignored. CORREL is synonymous with PEARSON.
205 * @param dataY - The range representing the array or matrix of dependent data.
206 * @param dataX - The range representing the array or matrix of independent data.
207 * @returns {number} the Pearson product-moment correlation coefficient.
208 * @constructor
209 */
210var CORREL = function (dataY, dataX) {
211 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "CORREL");
212 if (!Array.isArray(dataY)) {
213 dataY = [dataY];
214 }
215 if (!Array.isArray(dataX)) {
216 dataX = [dataX];
217 }
218 if (dataY.length !== dataX.length) {
219 throw new Errors_1.NAError("CORREL has mismatched argument count " + dataY + " vs " + dataX + ".");
220 }
221 var arr1 = Filter_1.Filter.filterOutNonNumberValues(Filter_1.Filter.flattenAndThrow(dataY));
222 var arr2 = Filter_1.Filter.filterOutNonNumberValues(Filter_1.Filter.flattenAndThrow(dataX));
223 var stdevArr1 = MathHelpers_1.stdev(arr1, 1);
224 var stdevArr2 = MathHelpers_1.stdev(arr2, 1);
225 if (stdevArr1 === 0 || stdevArr2 === 0) {
226 throw new Errors_1.DivZeroError("Evaluation of function CORREL caused a divide by zero error.");
227 }
228 return MathHelpers_1.covariance(arr1, arr2) / stdevArr1 / stdevArr2;
229};
230exports.CORREL = CORREL;
231/**
232 * Calculates r, the Pearson product-moment correlation coefficient of a dataset. Any text encountered in the arguments
233 * will be ignored. PEARSON is synonymous with CORREL.
234 * @param dataY - The range representing the array or matrix of dependent data.
235 * @param dataX - The range representing the array or matrix of independent data.
236 * @returns {number} the Pearson product-moment correlation coefficient.
237 * @constructor
238 */
239var PEARSON = function (dataY, dataX) {
240 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "PEARSON");
241 return CORREL.apply(this, [dataY, dataX]);
242};
243exports.PEARSON = PEARSON;
244/**
245 * Returns the value of the exponential distribution function with a specified lambda at a specified value.
246 * @param x - The input to the exponential distribution function. If cumulative is TRUE then EXPONDIST returns
247 * the cumulative probability of all values up to x.
248 * @param lambda - The lambda to specify the exponential distribution function.
249 * @param cumulative - Whether to use the exponential cumulative distribution.
250 * @returns {number} value of the exponential distribution function.
251 * @constructor
252 */
253var EXPONDIST = function (x, lambda, cumulative) {
254 ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "EXPONDIST");
255 function cdf(x, rate) {
256 return x < 0 ? 0 : 1 - Math.exp(-rate * x);
257 }
258 function pdf(x, rate) {
259 return x < 0 ? 0 : rate * Math.exp(-rate * x);
260 }
261 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
262 lambda = TypeConverter_1.TypeConverter.firstValueAsNumber(lambda);
263 cumulative = TypeConverter_1.TypeConverter.firstValueAsBoolean(cumulative);
264 return (cumulative) ? cdf(x, lambda) : pdf(x, lambda);
265};
266exports.EXPONDIST = EXPONDIST;
267/**
268 * Calculates the left-tailed F probability distribution (degree of diversity) for two data sets with given input x.
269 * Alternately called Fisher-Snedecor distribution or Snecdor's F distribution.
270 * @param x - The input to the F probability distribution function. The value at which to evaluate the function.
271 * Must be a positive number.
272 * @param degreesFreedom1 - The numerator degrees of freedom.
273 * @param degreesFreedom2 - The denominator degrees of freedom.
274 * @param cumulative - Logical value that determines the form of the function. If true returns the cumulative
275 * distribution function. If false returns the probability density function.
276 * @returns {number|boolean} left-tailed F probability distribution
277 * @constructor
278 * TODO: This function should be stricter in its return type.
279 */
280var FDIST$LEFTTAILED = function (x, degreesFreedom1, degreesFreedom2, cumulative) {
281 ArgsChecker_1.ArgsChecker.checkLength(arguments, 4, "FDIST$LEFTTAILED");
282 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
283 if (x < 0) {
284 throw new Errors_1.NumError("Function F.DIST parameter 1 value is " + x + ". It should be greater than or equal to 0.");
285 }
286 var d1 = TypeConverter_1.TypeConverter.firstValueAsNumber(degreesFreedom1);
287 var d2 = TypeConverter_1.TypeConverter.firstValueAsNumber(degreesFreedom2);
288 var cum = TypeConverter_1.TypeConverter.firstValueAsBoolean(cumulative);
289 return (cum) ? MathHelpers_1.cdf(x, d1, d2) : MathHelpers_1.pdf(x, d1, d2);
290};
291exports.FDIST$LEFTTAILED = FDIST$LEFTTAILED;
292/**
293 * Returns the inverse of the (right-tailed) F probability distribution. If p = FDIST(x,...), then FINV(p,...) = x. The
294 * F distribution can be used in an F-test that compares the degree of variability in two data sets.
295 * @param probability - A probability associated with the F cumulative distribution.
296 * @param degFreedom1 - Required. The numerator degrees of freedom.
297 * @param degFreedom2 - Required. The denominator degrees of freedom.
298 * @returns {number} inverse of the (right-tailed) F probability distribution
299 * @constructor
300 */
301var FINV = function (probability, degFreedom1, degFreedom2) {
302 ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "FINV");
303 probability = TypeConverter_1.TypeConverter.firstValueAsNumber(probability);
304 if (probability <= 0.0 || probability > 1.0) {
305 throw new Errors_1.NumError("Function FINV parameter 1 value is " + probability
306 + ". It should be greater than or equal to 0, and less than 1.");
307 }
308 var d1 = TypeConverter_1.TypeConverter.firstValueAsNumber(degFreedom1);
309 var d2 = TypeConverter_1.TypeConverter.firstValueAsNumber(degFreedom2);
310 return MathHelpers_1.inv(1.0 - probability, d1, d2);
311};
312exports.FINV = FINV;
313/**
314 * Returns the Fisher transformation of a specified value.
315 * @param value - The value for which to calculate the Fisher transformation.
316 * @returns {number} Fisher transformation
317 * @constructor
318 */
319var FISHER = function (value) {
320 ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "FISHER");
321 var x = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
322 if (x <= -1 || x >= 1) {
323 throw new Errors_1.NumError("Function FISHER parameter 1 value is " + x + ". Valid values are between -1 and 1 exclusive.");
324 }
325 return Math.log((1 + x) / (1 - x)) / 2;
326};
327exports.FISHER = FISHER;
328/**
329 * Returns the inverse Fisher transformation of a specified value.
330 * @param value - The value for which to calculate the inverse Fisher transformation.
331 * @returns {number} inverse Fisher transformation
332 * @constructor
333 */
334var FISHERINV = function (value) {
335 ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "FISHERINV");
336 var y = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
337 var e2y = Math.exp(2 * y);
338 return (e2y - 1) / (e2y + 1);
339};
340exports.FISHERINV = FISHERINV;
341/**
342 * Returns the maximum value in a numeric dataset.
343 * @param values - The values or range(s) to consider when calculating the maximum value.
344 * @returns {number} the maximum value of the dataset
345 * @constructor
346 */
347var MAX = function () {
348 var values = [];
349 for (var _i = 0; _i < arguments.length; _i++) {
350 values[_i] = arguments[_i];
351 }
352 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "MAX");
353 var maxSoFar = -Infinity;
354 for (var i = 0; i < values.length; i++) {
355 if (values[i] instanceof Array) {
356 if (values[i].length === 0) {
357 throw new Errors_1.RefError("Reference does not exist.");
358 }
359 var filtered = Filter_1.Filter.filterOutStringValues(values[i]);
360 if (filtered.length !== 0) {
361 maxSoFar = Math.max(MAX.apply(this, filtered), maxSoFar);
362 }
363 }
364 else {
365 maxSoFar = Math.max(TypeConverter_1.TypeConverter.valueToNumber(values[i]), maxSoFar);
366 }
367 }
368 return maxSoFar;
369};
370exports.MAX = MAX;
371/**
372 * Returns the maximum numeric value in a dataset.
373 * @param values - The value(s) or range(s) to consider when calculating the maximum value.
374 * @returns {number} maximum value of the dataset
375 * @constructor
376 */
377var MAXA = function () {
378 var values = [];
379 for (var _i = 0; _i < arguments.length; _i++) {
380 values[_i] = arguments[_i];
381 }
382 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "MAXA");
383 var maxSoFar = -Infinity;
384 var filteredValues = Filter_1.Filter.stringValuesToZeros(values);
385 for (var i = 0; i < filteredValues.length; i++) {
386 if (filteredValues[i] instanceof Array) {
387 if (values[i].length === 0) {
388 throw new Errors_1.RefError("Reference does not exist.");
389 }
390 var filtered = Filter_1.Filter.stringValuesToZeros(filteredValues[i]);
391 if (filtered.length !== 0) {
392 maxSoFar = Math.max(MAXA.apply(this, filtered), maxSoFar);
393 }
394 }
395 else {
396 maxSoFar = Math.max(TypeConverter_1.TypeConverter.valueToNumber(filteredValues[i]), maxSoFar);
397 }
398 }
399 return maxSoFar;
400};
401exports.MAXA = MAXA;
402/**
403 * Returns the minimum value in a numeric dataset.
404 * @param values - The value(s) or range(s) to consider when calculating the minimum value.
405 * @returns {number} the minimum value of the dataset
406 * @constructor
407 */
408var MIN = function () {
409 var values = [];
410 for (var _i = 0; _i < arguments.length; _i++) {
411 values[_i] = arguments[_i];
412 }
413 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "MIN");
414 var minSoFar = Infinity;
415 for (var i = 0; i < values.length; i++) {
416 if (values[i] instanceof Array) {
417 if (values[i].length === 0) {
418 throw new Errors_1.RefError("Reference does not exist.");
419 }
420 var filtered = Filter_1.Filter.filterOutStringValues(values[i]);
421 if (filtered.length !== 0) {
422 minSoFar = Math.min(MIN.apply(this, filtered), minSoFar);
423 }
424 }
425 else {
426 minSoFar = Math.min(TypeConverter_1.TypeConverter.valueToNumber(values[i]), minSoFar);
427 }
428 }
429 return minSoFar;
430};
431exports.MIN = MIN;
432/**
433 * Returns the minimum numeric value in a dataset.
434 * @param values - The value(s) or range(s) to consider when calculating the minimum value.
435 * @returns {number} the minimum value in the dataset
436 * @constructor
437 */
438var MINA = function () {
439 var values = [];
440 for (var _i = 0; _i < arguments.length; _i++) {
441 values[_i] = arguments[_i];
442 }
443 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "MINA");
444 return MIN.apply(this, values);
445};
446exports.MINA = MINA;
447/**
448 * Returns the average of a range depending on criteria.
449 * @param criteriaRange - The range to check against criterion.
450 * @param criterion - The pattern or test to apply to criteria_range.
451 * @param averageRange - [optional] The range to average. If not included, criteria_range is used for the
452 * average instead.
453 * @returns {number}
454 * @constructor
455 * TODO: This needs to also accept a third parameter "average_range"
456 */
457var AVERAGEIF = function (criteriaRange, criterion, averageRange) {
458 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "AVERAGEIF");
459 var range = Filter_1.Filter.flatten(criteriaRange);
460 var criteriaEvaluation = CriteriaFunctionFactory_1.CriteriaFunctionFactory.createCriteriaFunction(criterion);
461 var result = 0;
462 var count = 0;
463 for (var i = 0; i < range.length; i++) {
464 var val = TypeConverter_1.TypeConverter.valueToNumber(range[i]);
465 if (criteriaEvaluation(val)) {
466 result = result + val;
467 count++;
468 }
469 }
470 if (count === 0) {
471 throw new Errors_1.DivZeroError("Evaluation of function AVERAGEIF caused a divide by zero error.");
472 }
473 return result / count;
474};
475exports.AVERAGEIF = AVERAGEIF;
476/**
477 * Returns the a count of the number of numeric values in a dataset.
478 * @param values - The values or ranges to consider when counting.
479 * @returns {number} number of numeric values in a dataset.
480 * @constructor
481 */
482var COUNT = function () {
483 var values = [];
484 for (var _i = 0; _i < arguments.length; _i++) {
485 values[_i] = arguments[_i];
486 }
487 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "COUNT");
488 var count = 0;
489 for (var i = 0; i < values.length; i++) {
490 if (values[i] instanceof Array) {
491 if (values[i].length > 0) {
492 count += COUNT.apply(this, values[i]);
493 }
494 }
495 else if (TypeConverter_1.TypeConverter.canCoerceToNumber(values[i])) {
496 count++;
497 }
498 }
499 return count;
500};
501exports.COUNT = COUNT;
502/**
503 * Returns the a count of the number of values in a dataset.
504 * @param values - The values or ranges to consider when counting.
505 * @returns {number} number of values in a dataset.
506 * @constructor
507 */
508var COUNTA = function () {
509 var values = [];
510 for (var _i = 0; _i < arguments.length; _i++) {
511 values[_i] = arguments[_i];
512 }
513 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 1, "COUNTA");
514 var count = 0;
515 for (var i = 0; i < values.length; i++) {
516 if (values[i] instanceof Array) {
517 if (values[i].length > 0) {
518 count += COUNTA.apply(this, values[i]);
519 }
520 else {
521 count++;
522 }
523 }
524 else {
525 count++;
526 }
527 }
528 return count;
529};
530exports.COUNTA = COUNTA;
531/**
532 * Returns the value at a given percentile of a set of data.
533 * @param data - The array or range containing the dataset to consider.
534 * @param percent - percentile to be calculated and returned.
535 * @returns {number}
536 * @constructor
537 */
538var PERCENTILE = function (data, percent) {
539 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "PERCENTILE");
540 var p = TypeConverter_1.TypeConverter.firstValueAsNumber(percent);
541 if (p < 0 || p > 1) {
542 throw new Errors_1.NumError("Function PERCENTILE parameter 2 value " + p + " is out of range.");
543 }
544 var range = Filter_1.Filter.flattenAndThrow(data).sort(function (a, b) {
545 return a - b;
546 }).map(function (value) {
547 return TypeConverter_1.TypeConverter.valueToNumber(value);
548 });
549 var n = range.length;
550 var l = p * (n - 1);
551 var fl = Math.floor(l);
552 return MathHelpers_1.cleanFloat((l === fl) ? range[l] : range[fl] + (l - fl) * (range[fl + 1] - range[fl]));
553};
554exports.PERCENTILE = PERCENTILE;
555/**
556 * Returns a value nearest to a specified quartile of a set of data.
557 * @param data - The array or range containing the set of data to consider.
558 * @param quartile - Which quartile value to return. 0 returns 0 percent mark, 1 returns 25 percent mark, 2 returns 50
559 * percent mark, 3 returns 75 percent mark, 4 returns 100 percent mark.
560 * @constructor
561 */
562var QUARTILE = function (data, quartile) {
563 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "QUARTILE");
564 var q = TypeConverter_1.TypeConverter.firstValueAsNumber(quartile);
565 if (q < 0 || q > 4) {
566 throw new Errors_1.NumError("Function QUARTILE parameter 2 value " + q + " is out of range.");
567 }
568 var range = Filter_1.Filter.flattenAndThrow(data).sort(function (a, b) {
569 return a - b;
570 }).map(function (value) {
571 return TypeConverter_1.TypeConverter.valueToNumber(value);
572 });
573 switch (q) {
574 case 0:
575 return PERCENTILE(range, 0);
576 case 1:
577 return PERCENTILE(range, 0.25);
578 case 2:
579 return PERCENTILE(range, 0.5);
580 case 3:
581 return PERCENTILE(range, 0.75);
582 case 4:
583 return PERCENTILE(range, 1);
584 }
585};
586exports.QUARTILE = QUARTILE;
587/**
588 * Calculates the standard deviation of a range, ignoring string values, regardless of whether they can be converted to
589 * numbers.
590 * @param values - Range of sample.
591 * @returns {number}
592 * @constructor
593 */
594var STDEV = function () {
595 var values = [];
596 for (var _i = 0; _i < arguments.length; _i++) {
597 values[_i] = arguments[_i];
598 }
599 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "STDEV");
600 var range = Filter_1.Filter.flattenAndThrow(values);
601 var n = range.length;
602 var sigma = 0;
603 var count = 0;
604 var mean = AVERAGE(range);
605 for (var i = 0; i < n; i++) {
606 var value = TypeConverter_1.TypeConverter.firstValue(range[i]);
607 if (typeof value !== "string") {
608 sigma += Math.pow(TypeConverter_1.TypeConverter.valueToNumber(value) - mean, 2);
609 count++;
610 }
611 }
612 return Math.sqrt(sigma / (count - 1));
613};
614exports.STDEV = STDEV;
615/**
616 * Calculates the standard deviation of a range, converting string values to numbers, if possible. If a value cannot
617 * be converted to a number, formula will throw a value error.
618 * @param values - Range of sample.
619 * @returns {number}
620 * @constructor
621 */
622var STDEVA = function () {
623 var values = [];
624 for (var _i = 0; _i < arguments.length; _i++) {
625 values[_i] = arguments[_i];
626 }
627 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "STDEVA");
628 var range = Filter_1.Filter.flattenAndThrow(values).map(function (value) {
629 return TypeConverter_1.TypeConverter.firstValueAsNumber(value);
630 });
631 var n = range.length;
632 var sigma = 0;
633 var m = MathHelpers_1.mean(range);
634 for (var i = 0; i < n; i++) {
635 sigma += Math.pow(range[i] - m, 2);
636 }
637 return Math.sqrt(sigma / (n - 1));
638};
639exports.STDEVA = STDEVA;
640/**
641 * Calculates the standard deviation of an entire population, ignoring string values, regardless of whether they can be
642 * converted to numbers.
643 * @param values - Entire sample.
644 * @returns {number}
645 * @constructor
646 */
647var STDEVP = function () {
648 var values = [];
649 for (var _i = 0; _i < arguments.length; _i++) {
650 values[_i] = arguments[_i];
651 }
652 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "STDEVP");
653 var range = Filter_1.Filter.flattenAndThrow(values);
654 var n = range.length;
655 var sigma = 0;
656 var count = 0;
657 var m = AVERAGE(range);
658 for (var i = 0; i < n; i++) {
659 var value = TypeConverter_1.TypeConverter.firstValue(range[i]);
660 if (typeof value !== "string") {
661 sigma += Math.pow(value - m, 2);
662 count++;
663 }
664 }
665 return Math.sqrt(sigma / count);
666};
667exports.STDEVP = STDEVP;
668/**
669 * Calculates the standard deviation of an entire population, including text and boolean values, if possible. If a value
670 * cannot be converted to a number, formula will throw a value error.
671 * @param values - Entire sample.
672 * @returns {number}
673 * @constructor
674 */
675var STDEVPA = function () {
676 var values = [];
677 for (var _i = 0; _i < arguments.length; _i++) {
678 values[_i] = arguments[_i];
679 }
680 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "STDEVPA");
681 var range = Filter_1.Filter.flattenAndThrow(values).map(function (value) {
682 return TypeConverter_1.TypeConverter.firstValueAsNumber(value);
683 });
684 var n = range.length;
685 var sigma = 0;
686 var count = 0;
687 var m = AVERAGE(range);
688 for (var i = 0; i < n; i++) {
689 var value = TypeConverter_1.TypeConverter.firstValue(range[i]);
690 if (typeof value !== "string") {
691 sigma += Math.pow(value - m, 2);
692 count++;
693 }
694 }
695 return Math.sqrt(sigma / count);
696};
697exports.STDEVPA = STDEVPA;
698/**
699 * Returns the mean value of a range excluding some percentage of the range on the high and low ends of the range.
700 * @param range - Array or range to consider.
701 * @param percent - The portion of the data to exclude on both ends of the range.
702 * @returns {number}
703 * @constructor
704 */
705var TRIMMEAN = function (range, percent) {
706 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "TRIMMEAN");
707 var p = TypeConverter_1.TypeConverter.firstValueAsNumber(percent);
708 if (p < 0) {
709 throw new Errors_1.NumError("Function TRIMMEAN parameter 2 value is " + p + ". It should be greater than or equal to 0.");
710 }
711 if (p >= 1) {
712 throw new Errors_1.NumError("Function TRIMMEAN parameter 2 value is " + p + ". It should be less than 1.");
713 }
714 var data = Filter_1.Filter.flattenAndThrow(range).sort(function (a, b) {
715 return a - b;
716 }).map(function (value) {
717 return TypeConverter_1.TypeConverter.valueToNumber(value);
718 });
719 if (data.length === 0) {
720 throw new Errors_1.RefError("TRIMMEAN has no valid input data.");
721 }
722 var trim = Math_1.FLOOR(data.length * p, 2) / 2;
723 var tmp = data.slice(trim, data.length);
724 return MathHelpers_1.mean(tmp.slice(0, tmp.length - trim));
725};
726exports.TRIMMEAN = TRIMMEAN;
727/**
728 * Returns the slope of the line calculated from linear regression of a range. Any text values passed in will be ignored
729 * @param rangeY - The range or array representing the dependent data.
730 * @param rangeX - The range or array representing the independent data.
731 * @constructor
732 */
733var SLOPE = function (rangeY, rangeX) {
734 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "SLOPE");
735 var dataX = Filter_1.Filter.flattenAndThrow(rangeX).filter(function (value) {
736 return typeof value !== "string";
737 }).map(function (value) {
738 return TypeConverter_1.TypeConverter.valueToNumber(value);
739 });
740 var dataY = Filter_1.Filter.flattenAndThrow(rangeY).filter(function (value) {
741 return typeof value !== "string";
742 }).map(function (value) {
743 return TypeConverter_1.TypeConverter.valueToNumber(value);
744 });
745 if (dataX.length !== dataY.length) {
746 throw new Errors_1.NAError("SLOPE has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
747 }
748 var xmean = MathHelpers_1.mean(dataX);
749 var ymean = MathHelpers_1.mean(dataY);
750 var n = dataX.length;
751 var num = 0;
752 var den = 0;
753 for (var i = 0; i < n; i++) {
754 num += (dataX[i] - xmean) * (dataY[i] - ymean);
755 den += Math.pow(dataX[i] - xmean, 2);
756 }
757 if (den === 0) {
758 throw new Errors_1.DivZeroError("Evaluation of function SLOPE caused a divide by zero error.");
759 }
760 return num / den;
761};
762exports.SLOPE = SLOPE;
763/**
764 * Returns the normalized equivalent of a random variable given mean and standard deviation of the distribution.
765 * @param value - Value to be standardized.
766 * @param meanValue - Arithmetic mean of the distribution
767 * @param std - The standard deviation of the distribution or range.
768 * @returns {number}
769 * @constructor
770 */
771var STANDARDIZE = function (value, meanValue, std) {
772 ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "STANDARDIZE");
773 value = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
774 meanValue = TypeConverter_1.TypeConverter.firstValueAsNumber(meanValue);
775 std = TypeConverter_1.TypeConverter.firstValueAsNumber(std);
776 if (std <= 0) {
777 throw new Errors_1.NumError("Function STANDARDIZE parameter 3 value is " + std + ". It should be greater than 0.");
778 }
779 return (value - meanValue) / std;
780};
781exports.STANDARDIZE = STANDARDIZE;
782/**
783 * Returns the Nth smallest value in the range, ignoring text values.
784 * @param range - Range or data-set to consider.
785 * @param n - N in 'Nth'.
786 * @constructor
787 */
788var SMALL = function (range, n) {
789 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "SMALL");
790 var data = Filter_1.Filter.flattenAndThrow(range).filter(function (value) {
791 return typeof value != "string";
792 }).map(function (value) {
793 return TypeConverter_1.TypeConverter.valueToNumber(value);
794 }).sort(function (a, b) {
795 return a - b;
796 });
797 if (n > data.length || n < 1) {
798 throw new Errors_1.NumError("Function SMALL parameter 2 value " + n + " is out of range.");
799 }
800 return data[n - 1];
801};
802exports.SMALL = SMALL;
803/**
804 * Returns the Nth largest value in the range, ignoring text values.
805 * @param range - Range or data-set to consider.
806 * @param n - N in 'Nth'.
807 * @constructor
808 */
809var LARGE = function (range, n) {
810 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "LARGE");
811 var data = Filter_1.Filter.flattenAndThrow(range).filter(function (value) {
812 return typeof value != "string";
813 }).map(function (value) {
814 return TypeConverter_1.TypeConverter.valueToNumber(value);
815 }).sort(function (a, b) {
816 return b - a;
817 });
818 if (n > data.length || n < 1) {
819 throw new Errors_1.NumError("Function LARGE parameter 2 value " + n + " is out of range.");
820 }
821 return data[n - 1];
822};
823exports.LARGE = LARGE;
824/**
825 * Returns the kurtosis of a data set or range. Ignores text values.
826 * @param values - data set or range to calculate. Must be at least 4 values.
827 * @returns {number}
828 * @constructor
829 */
830var KURT = function () {
831 var values = [];
832 for (var _i = 0; _i < arguments.length; _i++) {
833 values[_i] = arguments[_i];
834 }
835 ArgsChecker_1.ArgsChecker.checkAtLeastLength(values, 4, "KURT");
836 var range = Filter_1.Filter.flattenAndThrow(values).filter(function (value) {
837 return typeof value !== "string";
838 }).map(function (value) {
839 return TypeConverter_1.TypeConverter.valueToNumber(value);
840 });
841 if (range.length < 4) {
842 throw new Errors_1.DivZeroError("KURT requires more values in range. Expected: 4, found: " + range.length + ".");
843 }
844 var m = MathHelpers_1.mean(range);
845 var n = range.length;
846 var sigma = 0;
847 for (var i = 0; i < n; i++) {
848 sigma += Math.pow(range[i] - m, 4);
849 }
850 sigma = sigma / Math.pow(MathHelpers_1.stdev(range, true), 4);
851 return ((n * (n + 1)) / ((n - 1) * (n - 2) * (n - 3))) * sigma - 3 * (n - 1) * (n - 1) / ((n - 2) * (n - 3));
852};
853exports.KURT = KURT;
854/**
855 * Calculates the y-value at which a line will intersect the y-axis by using known x-values and y-values. Any text
856 * values will be ignored.
857 * @param rangeY - Dependent range of values.
858 * @param rangeX - Independent range of values.
859 * @returns {number}
860 * @constructor
861 */
862var INTERCEPT = function (rangeY, rangeX) {
863 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "INTERCEPT");
864 var dataX = Filter_1.Filter.flattenAndThrow(rangeX).filter(function (value) {
865 return typeof value !== "string";
866 }).map(function (value) {
867 return TypeConverter_1.TypeConverter.valueToNumber(value);
868 });
869 var dataY = Filter_1.Filter.flattenAndThrow(rangeY).filter(function (value) {
870 return typeof value !== "string";
871 }).map(function (value) {
872 return TypeConverter_1.TypeConverter.valueToNumber(value);
873 });
874 if (dataX.length !== dataY.length) {
875 throw new Errors_1.NAError("INTERCEPT has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
876 }
877 var xMean = MathHelpers_1.mean(dataX);
878 var yMean = MathHelpers_1.mean(dataY);
879 var n = dataX.length;
880 var num = 0;
881 var den = 0;
882 for (var i = 0; i < n; i++) {
883 num += (dataX[i] - xMean) * (dataY[i] - yMean);
884 den += Math.pow(dataX[i] - xMean, 2);
885 }
886 if (den === 0) {
887 throw new Errors_1.DivZeroError("Evaluation of function INTERCEPT caused a divide by zero error.");
888 }
889 var b = num / den;
890 return yMean - b * xMean;
891};
892exports.INTERCEPT = INTERCEPT;
893/**
894 * Calculates the a future value using existing x-values and y-values. Any text values will be ignored.
895 * @param x - The data point for which you would like to predict the value.
896 * @param rangeY - Dependent range of values.
897 * @param rangeX - Independent range of values.
898 * @returns {number}
899 * @constructor
900 * TODO: This formula will fail to parse since the first argument is followed by an argument that is an array.
901 * TODO (continued) This is a known issue.
902 */
903var FORECAST = function (x, rangeY, rangeX) {
904 ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "FORECAST");
905 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
906 var dataX = Filter_1.Filter.flattenAndThrow(rangeX).filter(function (value) {
907 return typeof value !== "string";
908 }).map(function (value) {
909 return TypeConverter_1.TypeConverter.valueToNumber(value);
910 });
911 var dataY = Filter_1.Filter.flattenAndThrow(rangeY).filter(function (value) {
912 return typeof value !== "string";
913 }).map(function (value) {
914 return TypeConverter_1.TypeConverter.valueToNumber(value);
915 });
916 if (dataX.length !== dataY.length) {
917 throw new Errors_1.NAError("FORECAST has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
918 }
919 var xMean = MathHelpers_1.mean(dataX);
920 var yMean = MathHelpers_1.mean(dataY);
921 var n = dataX.length;
922 var num = 0;
923 var den = 0;
924 for (var i = 0; i < n; i++) {
925 num += (dataX[i] - xMean) * (dataY[i] - yMean);
926 den += Math.pow(dataX[i] - xMean, 2);
927 }
928 if (den === 0) {
929 throw new Errors_1.DivZeroError("Evaluation of function FORECAST caused a divide by zero error.");
930 }
931 var b = num / den;
932 var a = yMean - b * xMean;
933 return a + b * x;
934};
935exports.FORECAST = FORECAST;
936/**
937 * Returns the Poisson distribution for the given number. Functions the same as POISSON.DIST.
938 * @param x - Number to use.
939 * @param meanValue - The middle value for the Poisson distribution.
940 * @param cumulative - [OPTIONAL] - 0 calculates the density function, 1 calculates the distribution. Defaults to 0.
941 * @returns {number}
942 * @constructor
943 */
944var POISSON = function (x, meanValue, cumulative) {
945 ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 2, 3, "POISSON");
946 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
947 meanValue = TypeConverter_1.TypeConverter.firstValueAsNumber(meanValue);
948 cumulative = (cumulative === undefined) ? 0 : TypeConverter_1.TypeConverter.firstValueAsNumber(cumulative);
949 if (x < 0) {
950 throw new Errors_1.NumError("Function POISSON parameter 1 value is " + x + ". It should be greater than or equal to 0.");
951 }
952 if (meanValue < 0) {
953 throw new Errors_1.NumError("Function POISSON parameter 2 value is " + x + ". It should be greater than or equal to 0.");
954 }
955 function factorial(n) {
956 return n < 0 ? NaN : MathHelpers_1.gammafn(n + 1);
957 }
958 function poissonPDF(k, l) {
959 return Math.pow(l, k) * Math.exp(-l) / factorial(k);
960 }
961 function poissonCDF(x, l) {
962 var sumarr = [], k = 0;
963 if (x < 0)
964 return 0;
965 for (; k <= x; k++) {
966 sumarr.push(poissonPDF(k, l));
967 }
968 return MathHelpers_1.sum(sumarr);
969 }
970 ;
971 return (cumulative) ? poissonCDF(x, meanValue) : poissonPDF(x, meanValue);
972};
973exports.POISSON = POISSON;
974/**
975 * Returns the percentage rank (percentile) of the given value in a sample. Functions the same as PERCENTRANK.INC.
976 * @param data - The array or range of data in the sample.
977 * @param x - The value.
978 * @param significance - [OPTIONAL] - The number of significant digits to use in the calculation. Defaults to 3.
979 * @returns {number}
980 * @constructor
981 */
982var PERCENTRANK = function (data, x, significance) {
983 ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 2, 3, "PERCENTRANK");
984 data = Filter_1.Filter.flattenAndThrow(data).map(TypeConverter_1.TypeConverter.valueToNumber).sort(function (a, b) {
985 return a - b;
986 });
987 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
988 var uniques = Filter_1.Filter.unique(data);
989 var n = data.length;
990 var m = uniques.length;
991 if (x < uniques[0] || x > uniques[m - 1]) {
992 throw new Errors_1.NAError("PERCENTRANK does not have valid input data.");
993 }
994 if (m === 1 && uniques[0] === x) {
995 return 1;
996 }
997 significance = (typeof significance === 'undefined') ? 3 : TypeConverter_1.TypeConverter.firstValueAsNumber(significance);
998 var power = Math.pow(10, significance);
999 var result = 0;
1000 var match = false;
1001 var i = 0;
1002 while (!match && i < m) {
1003 if (x === uniques[i]) {
1004 result = data.indexOf(uniques[i]) / (n - 1);
1005 match = true;
1006 }
1007 else if (x >= uniques[i] && (x < uniques[i + 1] || i === m - 1)) {
1008 result = (data.indexOf(uniques[i]) + (x - uniques[i]) / (uniques[i + 1] - uniques[i])) / (n - 1);
1009 match = true;
1010 }
1011 i++;
1012 }
1013 var v = Math.floor(result * power) / power;
1014 if (isNaN(v)) {
1015 throw new Errors_1.NAError("PERCENTRANK does not have valid input data.");
1016 }
1017 return v;
1018};
1019exports.PERCENTRANK = PERCENTRANK;
1020/**
1021 * Returns the percentage rank (percentile) from 0 to 1 exclusive for a value in a sample.
1022 * @param data - The array or range of data in the sample.
1023 * @param x - The value
1024 * @param significance - [OPTIONAL] - The number of significant digits to use in the calculation. Defaults to 3.
1025 * @returns {number}
1026 * @constructor
1027 */
1028var PERCENTRANK$EXC = function (data, x, significance) {
1029 ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 2, 3, "PERCENTRANK.EXC");
1030 data = Filter_1.Filter.flattenAndThrow(data).map(TypeConverter_1.TypeConverter.valueToNumber).sort(function (a, b) {
1031 return a - b;
1032 });
1033 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
1034 var uniques = Filter_1.Filter.unique(data);
1035 var n = data.length;
1036 var m = uniques.length;
1037 if (x < uniques[0] || x > uniques[m - 1]) {
1038 throw new Errors_1.NAError("PERCENTRANK.EXC does not have valid input data.");
1039 }
1040 if (m === 1 && uniques[0] === x) {
1041 return 1;
1042 }
1043 significance = (typeof significance === 'undefined') ? 3 : TypeConverter_1.TypeConverter.firstValueAsNumber(significance);
1044 var power = Math.pow(10, significance);
1045 var result = 0;
1046 var match = false;
1047 var i = 0;
1048 while (!match && i < m) {
1049 if (x === uniques[i]) {
1050 result = (data.indexOf(uniques[i]) + 1) / (n + 1);
1051 match = true;
1052 }
1053 else if (x >= uniques[i] && (x < uniques[i + 1] || i === m - 1)) {
1054 result = (data.indexOf(uniques[i]) + 1 + (x - uniques[i]) / (uniques[i + 1] - uniques[i])) / (n + 1);
1055 match = true;
1056 }
1057 i++;
1058 }
1059 var v = Math.floor(result * power) / power;
1060 if (isNaN(v)) {
1061 throw new Errors_1.NAError("PERCENTRANK.EXC does not have valid input data.");
1062 }
1063 return v;
1064};
1065exports.PERCENTRANK$EXC = PERCENTRANK$EXC;
1066/**
1067 * Returns the inverse of the standard normal distribution for the given number.
1068 * @param probability - The probability value.
1069 * @returns {number}
1070 * @constructor
1071 */
1072var NORMSINV = function (probability) {
1073 ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "NORMSINV");
1074 probability = TypeConverter_1.TypeConverter.firstValueAsNumber(probability);
1075 function erfc(x) {
1076 return 1 - MathHelpers_1.erf(x);
1077 }
1078 function erfcinv(p) {
1079 var j = 0;
1080 var x, err, t, pp;
1081 if (p >= 2)
1082 return -100;
1083 if (p <= 0)
1084 return 100;
1085 pp = (p < 1) ? p : 2 - p;
1086 t = Math.sqrt(-2 * Math.log(pp / 2));
1087 x = -0.70711 * ((2.30753 + t * 0.27061) /
1088 (1 + t * (0.99229 + t * 0.04481)) - t);
1089 for (; j < 2; j++) {
1090 err = erfc(x) - pp;
1091 x += err / (1.12837916709551257 * Math.exp(-x * x) - x * err);
1092 }
1093 return (p < 1) ? x : -x;
1094 }
1095 function inv(p, mean, std) {
1096 return -1.41421356237309505 * std * erfcinv(2 * p) + mean;
1097 }
1098 if (probability <= 0 || probability >= 1) {
1099 throw new Errors_1.NumError("Function NORMSINV parameter 1 value is " + probability +
1100 ". Valid values are between 0 and 1 exclusive.");
1101 }
1102 return inv(probability, 0, 1);
1103};
1104exports.NORMSINV = NORMSINV;
1105function _cdf(x, mValue, stdVal) {
1106 return 0.5 * (1 + MathHelpers_1.erf((x - mValue) / Math.sqrt(2 * stdVal * stdVal)));
1107}
1108function _pdf(x, meanVal, std) {
1109 return Math.exp(-0.5 * Math.log(2 * Math.PI) -
1110 Math.log(std) - Math.pow(x - meanVal, 2) / (2 * std * std));
1111}
1112/**
1113 * Returns the standard normal cumulative distribution for the given number.
1114 * @param z - Value to use in calculation.
1115 * @returns {number}
1116 * @constructor
1117 */
1118var NORMSDIST = function (z) {
1119 ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "NORMSDIST");
1120 z = TypeConverter_1.TypeConverter.firstValueAsNumber(z);
1121 return _cdf(z, 0, 1);
1122};
1123exports.NORMSDIST = NORMSDIST;
1124/**
1125 * Returns the normal distribution for the given number in the distribution.
1126 * @param x - Value to use.
1127 * @param meanValue - The mean value of the distribution.
1128 * @param standDev - The standard deviation of the distribution.
1129 * @param cumulative - 0 calculates the density function, 1 calculates the distribution.
1130 * @returns {number}
1131 * @constructor
1132 */
1133var NORMDIST = function (x, meanValue, standDev, cumulative) {
1134 ArgsChecker_1.ArgsChecker.checkLength(arguments, 4, "NORMDIST");
1135 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
1136 meanValue = TypeConverter_1.TypeConverter.firstValueAsNumber(meanValue);
1137 standDev = TypeConverter_1.TypeConverter.firstValueAsNumber(standDev);
1138 cumulative = TypeConverter_1.TypeConverter.firstValueAsNumber(cumulative);
1139 if (standDev <= 0) {
1140 throw new Errors_1.NumError("Function NORMDIST parameter 3 value should be greater than 0. It is " + standDev + ".");
1141 }
1142 return (cumulative === 0) ? _pdf(x, meanValue, standDev) : _cdf(x, meanValue, standDev);
1143};
1144exports.NORMDIST = NORMDIST;
1145/**
1146 * Returns the inverse of the normal distribution for the given number in the distribution.
1147 * @param probability - Number in the distribution.
1148 * @param meanVal - The mean value in the normal distribution.
1149 * @param standDev - The standard deviation of the normal distribution.
1150 * @returns {number}
1151 * @constructor
1152 */
1153var NORMINV = function (probability, meanVal, standDev) {
1154 ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "NORMINV");
1155 function erf(x) {
1156 var cof = [-1.3026537197817094, 6.4196979235649026e-1, 1.9476473204185836e-2,
1157 -9.561514786808631e-3, -9.46595344482036e-4, 3.66839497852761e-4,
1158 4.2523324806907e-5, -2.0278578112534e-5, -1.624290004647e-6,
1159 1.303655835580e-6, 1.5626441722e-8, -8.5238095915e-8,
1160 6.529054439e-9, 5.059343495e-9, -9.91364156e-10,
1161 -2.27365122e-10, 9.6467911e-11, 2.394038e-12,
1162 -6.886027e-12, 8.94487e-13, 3.13092e-13,
1163 -1.12708e-13, 3.81e-16, 7.106e-15,
1164 -1.523e-15, -9.4e-17, 1.21e-16,
1165 -2.8e-17];
1166 var j = cof.length - 1;
1167 var isneg = false;
1168 var d = 0;
1169 var dd = 0;
1170 var t, ty, tmp, res;
1171 if (x < 0) {
1172 x = -x;
1173 isneg = true;
1174 }
1175 t = 2 / (2 + x);
1176 ty = 4 * t - 2;
1177 for (; j > 0; j--) {
1178 tmp = d;
1179 d = ty * d - dd + cof[j];
1180 dd = tmp;
1181 }
1182 res = t * Math.exp(-x * x + 0.5 * (cof[0] + ty * d) - dd);
1183 return isneg ? res - 1 : 1 - res;
1184 }
1185 function erfc(x) {
1186 return 1 - erf(x);
1187 }
1188 function erfcinv(p) {
1189 var j = 0;
1190 var x, err, t, pp;
1191 if (p >= 2)
1192 return -100;
1193 if (p <= 0)
1194 return 100;
1195 pp = (p < 1) ? p : 2 - p;
1196 t = Math.sqrt(-2 * Math.log(pp / 2));
1197 x = -0.70711 * ((2.30753 + t * 0.27061) /
1198 (1 + t * (0.99229 + t * 0.04481)) - t);
1199 for (; j < 2; j++) {
1200 err = erfc(x) - pp;
1201 x += err / (1.12837916709551257 * Math.exp(-x * x) - x * err);
1202 }
1203 return (p < 1) ? x : -x;
1204 }
1205 function inv(p, meanVal, std) {
1206 return -1.41421356237309505 * std * erfcinv(2 * p) + meanVal;
1207 }
1208 probability = TypeConverter_1.TypeConverter.firstValueAsNumber(probability);
1209 meanVal = TypeConverter_1.TypeConverter.firstValueAsNumber(meanVal);
1210 standDev = TypeConverter_1.TypeConverter.firstValueAsNumber(standDev);
1211 if (probability <= 0 || probability >= 1) {
1212 throw new Errors_1.NumError("Function NORMINV parameter 1 value is " + probability +
1213 ". Valid values are between 0 and 1 exclusive.");
1214 }
1215 if (standDev <= 0) {
1216 throw new Errors_1.NumError("Function NORMINV parameter 3 value is " + standDev + ". It should be greater than 0.");
1217 }
1218 return inv(probability, meanVal, standDev);
1219};
1220exports.NORMINV = NORMINV;
1221/**
1222 * Returns the negative binomial distribution.
1223 * @param k - The value returned for unsuccessful tests.
1224 * @param r - The value returned for successful tests.
1225 * @param p - The probability of the success of an attempt, between 0 and 1 inclusively.
1226 * @returns {number}
1227 * @constructor
1228 */
1229var NEGBINOMDIST = function (k, r, p) {
1230 ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "NEGBINOMDIST");
1231 function _gammaln(x) {
1232 var j = 0;
1233 var cof = [
1234 76.18009172947146, -86.50532032941677, 24.01409824083091,
1235 -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5
1236 ];
1237 var ser = 1.000000000190015;
1238 var xx, y, tmp;
1239 tmp = (y = xx = x) + 5.5;
1240 tmp -= (xx + 0.5) * Math.log(tmp);
1241 for (; j < 6; j++)
1242 ser += cof[j] / ++y;
1243 return Math.log(2.5066282746310005 * ser / xx) - tmp;
1244 }
1245 function _combinationln(n, m) {
1246 return _factorialln(n) - _factorialln(m) - _factorialln(n - m);
1247 }
1248 function _factorialln(n) {
1249 return n < 0 ? NaN : _gammaln(n + 1);
1250 }
1251 function _factorial(n) {
1252 return n < 0 ? NaN : MathHelpers_1.gammafn(n + 1);
1253 }
1254 function _combination(n, m) {
1255 return (n > 170 || m > 170)
1256 ? Math.exp(_combinationln(n, m))
1257 : (_factorial(n) / _factorial(m)) / _factorial(n - m);
1258 }
1259 function _pdf(k, r, p) {
1260 return k !== (k | 0)
1261 ? 0
1262 : k < 0
1263 ? 0
1264 : _combination(k + r - 1, r - 1) * Math.pow(1 - p, k) * Math.pow(p, r);
1265 }
1266 k = TypeConverter_1.TypeConverter.firstValueAsNumber(k);
1267 r = TypeConverter_1.TypeConverter.firstValueAsNumber(r);
1268 p = TypeConverter_1.TypeConverter.firstValueAsNumber(p);
1269 if (k < 1) {
1270 throw new Errors_1.NumError("Function NEGBINOMDIST parameter 1 value is " + k + ". Should be greater than 0.");
1271 }
1272 if (r < 1) {
1273 throw new Errors_1.NumError("Function NEGBINOMDIST parameter 2 value is " + r + ". Should be greater than 0.");
1274 }
1275 if (p < 0 || p > 1) {
1276 throw new Errors_1.NumError("Function NEGBINOMDIST parameter 3 value is " + p +
1277 ". Valid values are between 0 and 1 inclusive.");
1278 }
1279 return _pdf(k, r, p);
1280};
1281exports.NEGBINOMDIST = NEGBINOMDIST;
1282/**
1283 * Returns the geometric mean of a sample.
1284 * @param values - The numerical arguments or ranges that represent a random sample.
1285 * @returns {number}
1286 * @constructor
1287 */
1288var GEOMEAN = function () {
1289 var values = [];
1290 for (var _i = 0; _i < arguments.length; _i++) {
1291 values[_i] = arguments[_i];
1292 }
1293 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "GEOMEAN");
1294 function _product(arr) {
1295 var prod = 1;
1296 var i = arr.length;
1297 while (--i >= 0) {
1298 prod *= arr[i];
1299 }
1300 return prod;
1301 }
1302 values = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber).map(function (value) {
1303 if (value <= 0) {
1304 throw new Errors_1.NumError("GEOMEAN requires inputs greater than 0, but one of the values entered is " + value + ".");
1305 }
1306 return value;
1307 });
1308 return Math.pow(_product(values), 1 / values.length);
1309};
1310exports.GEOMEAN = GEOMEAN;
1311/**
1312 * Returns the harmonic mean of a data set.
1313 * @param values - The numerical arguments or ranges that represent a sample.
1314 * @returns {number}
1315 * @constructor
1316 */
1317var HARMEAN = function () {
1318 var values = [];
1319 for (var _i = 0; _i < arguments.length; _i++) {
1320 values[_i] = arguments[_i];
1321 }
1322 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "HARMEAN");
1323 var range = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber).map(function (value) {
1324 if (value <= 0) {
1325 throw new Errors_1.NumError("HARMEAN requires inputs greater than 0, but one of the values entered is " + value + ".");
1326 }
1327 return value;
1328 });
1329 var n = range.length;
1330 var den = 0;
1331 for (var i = 0; i < n; i++) {
1332 den += 1 / range[i];
1333 }
1334 return n / den;
1335};
1336exports.HARMEAN = HARMEAN;
1337/**
1338 * Returns the (1-alpha) confidence interval for a normal distribution.
1339 * @param alpha - The level of the confidence interval
1340 * @param standDev - The standard deviation for the total population
1341 * @param size - The size of the population.
1342 * @returns {number}
1343 * @constructor
1344 */
1345var CONFIDENCE = function (alpha, standDev, size) {
1346 ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "CONFIDENCE");
1347 alpha = TypeConverter_1.TypeConverter.firstValueAsNumber(alpha);
1348 standDev = TypeConverter_1.TypeConverter.firstValueAsNumber(standDev);
1349 size = TypeConverter_1.TypeConverter.firstValueAsNumber(size);
1350 if (alpha <= 0 || alpha >= 1) {
1351 throw new Errors_1.NumError("Function CONFIDENCE parameter 1 value is " + alpha
1352 + ". Valid values are between 0 and 1 exclusively.");
1353 }
1354 if (standDev <= 0) {
1355 throw new Errors_1.NumError("Function CONFIDENCE parameter 2 value is " + standDev + ". It should be greater than 0.");
1356 }
1357 if (size <= 0) {
1358 throw new Errors_1.NumError("Function CONFIDENCE parameter 3 value is " + size + ". It should be at least 1.");
1359 }
1360 function _erfc(x) {
1361 return 1 - MathHelpers_1.erf(x);
1362 }
1363 function _erfcinv(p) {
1364 var j = 0;
1365 var x, err, t, pp;
1366 if (p >= 2)
1367 return -100;
1368 if (p <= 0)
1369 return 100;
1370 pp = (p < 1) ? p : 2 - p;
1371 t = Math.sqrt(-2 * Math.log(pp / 2));
1372 x = -0.70711 * ((2.30753 + t * 0.27061) /
1373 (1 + t * (0.99229 + t * 0.04481)) - t);
1374 for (; j < 2; j++) {
1375 err = _erfc(x) - pp;
1376 x += err / (1.12837916709551257 * Math.exp(-x * x) - x * err);
1377 }
1378 return (p < 1) ? x : -x;
1379 }
1380 function _normalInv(p, m, std) {
1381 return -1.41421356237309505 * std * _erfcinv(2 * p) + m;
1382 }
1383 function _sumsqerr(arr) {
1384 var m = MathHelpers_1.mean(arr);
1385 var sum = 0;
1386 var i = arr.length;
1387 var tmp;
1388 while (--i >= 0) {
1389 tmp = arr[i] - m;
1390 sum += tmp * tmp;
1391 }
1392 return sum;
1393 }
1394 function _variance(arr, flag) {
1395 return _sumsqerr(arr) / (arr.length - (flag ? 1 : 0));
1396 }
1397 function _normalci() {
1398 var values = [];
1399 for (var _i = 0; _i < arguments.length; _i++) {
1400 values[_i] = arguments[_i];
1401 }
1402 var ans = new Array(2);
1403 var change;
1404 if (values.length === 4) {
1405 change = Math.abs(_normalInv(values[1] / 2, 0, 1) *
1406 values[2] / Math.sqrt(values[3]));
1407 }
1408 else {
1409 change = Math.abs(_normalInv(values[1] / 2, 0, 1) *
1410 Math.sqrt(_variance(arguments[2])) / Math.sqrt(values[2].length));
1411 }
1412 ans[0] = values[0] - change;
1413 ans[1] = values[0] + change;
1414 return ans;
1415 }
1416 return _normalci(1, alpha, standDev, size)[1] - 1;
1417};
1418exports.CONFIDENCE = CONFIDENCE;
1419/**
1420 * Returns the individual term binomial distribution probability.
1421 * @param successes - The number of successes in a set of trials.
1422 * @param trials - The number of independent trials.
1423 * @param probability - The probability of success on each trial.
1424 * @param cumulative - 0 calculates the probability of a single event, 1 calculates the cumulative probability.
1425 * @returns {number}
1426 * @constructor
1427 */
1428var BINOMDIST = function (successes, trials, probability, cumulative) {
1429 ArgsChecker_1.ArgsChecker.checkLength(arguments, 4, "BINOMDIST");
1430 successes = TypeConverter_1.TypeConverter.firstValueAsNumber(successes);
1431 trials = TypeConverter_1.TypeConverter.firstValueAsNumber(trials);
1432 probability = TypeConverter_1.TypeConverter.firstValueAsNumber(probability);
1433 cumulative = TypeConverter_1.TypeConverter.firstValueAsNumber(cumulative);
1434 function _binomialCDF(x, n, p) {
1435 var binomarr = [], k = 0;
1436 if (x < 0) {
1437 return 0;
1438 }
1439 if (x < n) {
1440 for (; k <= x; k++) {
1441 binomarr[k] = _binomialPDF(k, n, p);
1442 }
1443 return MathHelpers_1.sum(binomarr);
1444 }
1445 return 1;
1446 }
1447 function _combination(n, m) {
1448 // make sure n or m don't exceed the upper limit of usable values
1449 return (n > 170 || m > 170)
1450 ? Math.exp(_combinationln(n, m))
1451 : (_factorial(n) / _factorial(m)) / _factorial(n - m);
1452 }
1453 function _factorial(n) {
1454 return n < 0 ? NaN : MathHelpers_1.gammafn(n + 1);
1455 }
1456 function _factorialln(n) {
1457 return n < 0 ? NaN : MathHelpers_1.gammaln(n + 1);
1458 }
1459 function _combinationln(n, m) {
1460 return _factorialln(n) - _factorialln(m) - _factorialln(n - m);
1461 }
1462 function _binomialPDF(k, n, p) {
1463 return (p === 0 || p === 1) ?
1464 ((n * p) === k ? 1 : 0) :
1465 _combination(n, k) * Math.pow(p, k) * Math.pow(1 - p, n - k);
1466 }
1467 if (trials < 0) {
1468 throw new Errors_1.NumError("Function BINOMDIST parameter 2 value is " + trials + ", but should be greater than 0.");
1469 }
1470 if (trials < successes) {
1471 throw new Errors_1.NumError("Function BINOMDIST parameter 1 value is " + trials
1472 + ". It should be less than or equal to value of Function BINOMDIST parameter 2 with " + successes + ".");
1473 }
1474 if (probability > 1 || probability < 0) {
1475 throw new Errors_1.NumError("Function BINOMDIST parameter 3 value is " + probability
1476 + ", but should be between 0 and 1 inclusive.");
1477 }
1478 return (cumulative) ? _binomialCDF(successes, trials, probability) : _binomialPDF(successes, trials, probability);
1479};
1480exports.BINOMDIST = BINOMDIST;
1481/**
1482 * Returns the covariance of the product of paired deviations.
1483 * @param dataY - The first range of data.
1484 * @param dataX - The second range of data.
1485 * @returns {number}
1486 * @constructor
1487 */
1488var COVAR = function (dataY, dataX) {
1489 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "COVAR");
1490 dataY = Filter_1.Filter.flattenAndThrow(dataY).map(TypeConverter_1.TypeConverter.valueToNumber);
1491 dataX = Filter_1.Filter.flattenAndThrow(dataX).map(TypeConverter_1.TypeConverter.valueToNumber);
1492 if (dataX.length !== dataY.length) {
1493 throw new Errors_1.NAError("COlet has mismatched argument count " + dataY.length + " vs " + dataX.length + ".");
1494 }
1495 var mean1 = MathHelpers_1.mean(dataY);
1496 var mean2 = MathHelpers_1.mean(dataX);
1497 var result = 0;
1498 var n = dataY.length;
1499 for (var i = 0; i < n; i++) {
1500 result += (dataY[i] - mean1) * (dataX[i] - mean2);
1501 }
1502 return result / n;
1503};
1504exports.COVAR = COVAR;
1505/**
1506 * Returns the values of the Weibull distribution for the given number.
1507 * @param x - Number to use in calculation.
1508 * @param shape - The Alpha parameter of the Weibull distribution. Should be greater than 0.
1509 * @param scale - The Beta parameter of the Weibull distribution. Should be greater than 0.
1510 * @param cumulative - Indicates the type of function: If 0 the form of the function is calculated, if 1 then the
1511 * distribution is calculated.
1512 * @returns {number}
1513 * @constructor
1514 */
1515var WEIBULL = function (x, shape, scale, cumulative) {
1516 ArgsChecker_1.ArgsChecker.checkLength(arguments, 4, "WEIBULL");
1517 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
1518 if (x < 0) {
1519 throw new Errors_1.NumError("Function WEIBULL parameter 1 value is " + x + ", but should be greater than or equal to 0.");
1520 }
1521 shape = TypeConverter_1.TypeConverter.firstValueAsNumber(shape);
1522 if (shape <= 0) {
1523 throw new Errors_1.NumError("Function WEIBULL parameter 2 value is " + shape + ", but should be greater than 0.");
1524 }
1525 scale = TypeConverter_1.TypeConverter.firstValueAsNumber(scale);
1526 if (scale <= 0) {
1527 throw new Errors_1.NumError("Function WEIBULL parameter 2 value is " + scale + ", but should be greater than 0.");
1528 }
1529 cumulative = TypeConverter_1.TypeConverter.firstValueAsNumber(cumulative);
1530 return (cumulative) ? 1 - Math.exp(-Math.pow(x / scale, shape)) : Math.pow(x, shape - 1)
1531 * Math.exp(-Math.pow(x / scale, shape)) * shape / Math.pow(scale, shape);
1532};
1533exports.WEIBULL = WEIBULL;
1534/**
1535 * Estimate the variance based on the entire population. Text will be converted to numbers, if possible.
1536 * @param values - Values of population.
1537 * @returns {number}
1538 * @constructor
1539 */
1540var VARPA = function () {
1541 var values = [];
1542 for (var _i = 0; _i < arguments.length; _i++) {
1543 values[_i] = arguments[_i];
1544 }
1545 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "VARPA");
1546 var range = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber);
1547 var n = range.length;
1548 if (n < 2) {
1549 throw new Errors_1.DivZeroError("Evaluation of function VARP caused a divide by zero error.");
1550 }
1551 var sigma = 0;
1552 var count = 0;
1553 var mean = AVERAGEA(range);
1554 for (var i = 0; i < n; i++) {
1555 var el = range[i];
1556 if (typeof el === 'number') {
1557 sigma += Math.pow(el - mean, 2);
1558 }
1559 else if (el === true) {
1560 sigma += Math.pow(1 - mean, 2);
1561 }
1562 else {
1563 sigma += Math.pow(0 - mean, 2);
1564 }
1565 if (el !== null) {
1566 count++;
1567 }
1568 }
1569 return sigma / count;
1570};
1571exports.VARPA = VARPA;
1572/**
1573 * Estimate the variance based on the entire population.
1574 * @param values - Values of entire population.
1575 * @returns {number}
1576 * @constructor
1577 */
1578var VARP = function () {
1579 var values = [];
1580 for (var _i = 0; _i < arguments.length; _i++) {
1581 values[_i] = arguments[_i];
1582 }
1583 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "VARP");
1584 var range = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber);
1585 var n = range.length;
1586 if (n < 2) {
1587 throw new Errors_1.DivZeroError("Evaluation of function VARP caused a divide by zero error.");
1588 }
1589 var sigma = 0;
1590 var count = 0;
1591 var mean = AVERAGE(range);
1592 for (var i = 0; i < n; i++) {
1593 sigma += Math.pow(range[i] - mean, 2);
1594 count++;
1595 }
1596 return sigma / count;
1597};
1598exports.VARP = VARP;
1599/**
1600 * Estimate the variance based on a sample.
1601 * @param values
1602 * @returns {number}
1603 * @constructor
1604 */
1605var VARA = function () {
1606 var values = [];
1607 for (var _i = 0; _i < arguments.length; _i++) {
1608 values[_i] = arguments[_i];
1609 }
1610 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "VARA");
1611 var range = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber);
1612 var n = range.length;
1613 if (n < 2) {
1614 throw new Errors_1.DivZeroError("Evaluation of function VARA caused a divide by zero error.");
1615 }
1616 var sigma = 0;
1617 var count = 0;
1618 var mean = AVERAGEA(range);
1619 for (var i = 0; i < n; i++) {
1620 var el = range[i];
1621 if (typeof el === 'number') {
1622 sigma += Math.pow(el - mean, 2);
1623 }
1624 else if (el === true) {
1625 sigma += Math.pow(1 - mean, 2);
1626 }
1627 else {
1628 sigma += Math.pow(0 - mean, 2);
1629 }
1630 if (el !== null) {
1631 count++;
1632 }
1633 }
1634 return sigma / (count - 1);
1635};
1636exports.VARA = VARA;
1637/**
1638 * Estimate the variance based on a sample.
1639 * @param values - Values in sample.
1640 * @constructor
1641 */
1642var VAR = function () {
1643 var values = [];
1644 for (var _i = 0; _i < arguments.length; _i++) {
1645 values[_i] = arguments[_i];
1646 }
1647 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "VAR");
1648 var range = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber);
1649 var n = range.length;
1650 if (n < 2) {
1651 throw new Errors_1.DivZeroError("Evaluation of function let caused a divide by zero error.");
1652 }
1653 var sigma = 0;
1654 var count = 0;
1655 var mean = AVERAGE(range);
1656 for (var i = 0; i < n; i++) {
1657 sigma += Math.pow(range[i] - mean, 2);
1658 count++;
1659 }
1660 return sigma / (count - 1);
1661};
1662exports.VAR = VAR;
1663/**
1664 * Returns the number of permutations for a given number of objects.
1665 * @param total - The total number of objects
1666 * @param objects - The number of objects in each permutation.
1667 * @returns {number}
1668 * @constructor
1669 */
1670var PERMUT = function (total, objects) {
1671 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "PERMUT");
1672 total = TypeConverter_1.TypeConverter.firstValueAsNumber(total);
1673 objects = TypeConverter_1.TypeConverter.firstValueAsNumber(objects);
1674 if (total < objects) {
1675 throw new Errors_1.NumError("Function PERMUT parameter 2 value is " + objects +
1676 ", should be less than or equal to value of Function PERMUT parameter 1 of " + objects + ".");
1677 }
1678 var memoizeFact = [];
1679 function _fact(value) {
1680 var n = Math.floor(value);
1681 if (n === 0 || n === 1) {
1682 return 1;
1683 }
1684 else if (memoizeFact[n] > 0) {
1685 return memoizeFact[n];
1686 }
1687 else {
1688 memoizeFact[n] = _fact(n - 1) * n;
1689 return memoizeFact[n];
1690 }
1691 }
1692 return _fact(total) / _fact(total - objects);
1693};
1694exports.PERMUT = PERMUT;
1695/**
1696 * Returns the square of the Pearson correlation coefficient based on the given values.
1697 * @param rangeY - An array or range of data points.
1698 * @param rangeX - An array or range of data points.
1699 * @returns {number}
1700 * @constructor
1701 */
1702var RSQ = function (rangeY, rangeX) {
1703 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "RSQ");
1704 if (!Array.isArray(rangeY)) {
1705 rangeY = [rangeY];
1706 }
1707 if (!Array.isArray(rangeX)) {
1708 rangeX = [rangeX];
1709 }
1710 var dataX = Filter_1.Filter.flattenAndThrow(rangeX).map(TypeConverter_1.TypeConverter.valueToNumber);
1711 var dataY = Filter_1.Filter.flattenAndThrow(rangeY).map(TypeConverter_1.TypeConverter.valueToNumber);
1712 if (dataX.length !== dataY.length) {
1713 throw new Errors_1.NAError("SLOPE has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
1714 }
1715 if (dataY.length === 1 && dataX.length === 1) {
1716 throw new Errors_1.DivZeroError("Evaluation of function RSQ caused a divide by zero error.");
1717 }
1718 return Math.pow(PEARSON(dataX, dataY), 2);
1719};
1720exports.RSQ = RSQ;
1721/**
1722 * Returns the skewness of a distribution.
1723 * @param values - The numerical values or range.
1724 * @returns {number}
1725 * @constructor
1726 */
1727var SKEW = function () {
1728 var values = [];
1729 for (var _i = 0; _i < arguments.length; _i++) {
1730 values[_i] = arguments[_i];
1731 }
1732 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "SKEW");
1733 var range = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber);
1734 var n = range.length;
1735 if (n < 3) {
1736 throw new Errors_1.DivZeroError("SKEW requires at least 3 data points.");
1737 }
1738 var meanValue = MathHelpers_1.mean(range);
1739 var sigma = 0;
1740 for (var i = 0; i < n; i++) {
1741 sigma += Math.pow(range[i] - meanValue, 3);
1742 }
1743 var d = ((n - 1) * (n - 2) * Math.pow(MathHelpers_1.stdev(range, true), 3));
1744 if (d === 0) {
1745 throw new Errors_1.DivZeroError("Evaluation of function SKEW caused a divide by zero error.");
1746 }
1747 return n * sigma / d;
1748};
1749exports.SKEW = SKEW;
1750/**
1751 * Returns the standard error of the predicted y value for each x in the regression. Text values will be ignored.
1752 * @param rangeY - An array or range of data points.
1753 * @param rangeX - An array or range of data points.
1754 * @returns {number}
1755 * @constructor
1756 */
1757var STEYX = function (rangeY, rangeX) {
1758 ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "STEYX");
1759 if (!Array.isArray(rangeY)) {
1760 rangeY = [rangeY];
1761 }
1762 if (!Array.isArray(rangeX)) {
1763 rangeX = [rangeX];
1764 }
1765 var dataX = Filter_1.Filter.flattenAndThrow(rangeX).filter(function (value) {
1766 return typeof value !== "string";
1767 }).map(TypeConverter_1.TypeConverter.valueToNumber);
1768 var dataY = Filter_1.Filter.flattenAndThrow(rangeY).filter(function (value) {
1769 return typeof value !== "string";
1770 }).map(TypeConverter_1.TypeConverter.valueToNumber);
1771 if (dataX.length !== dataY.length) {
1772 throw new Errors_1.NAError("STEYX has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
1773 }
1774 if (dataY.length === 2 && dataX.length === 2) {
1775 throw new Errors_1.DivZeroError("Evaluation of function STEYX caused a divide by zero error.");
1776 }
1777 var xmean = MathHelpers_1.mean(dataX);
1778 var ymean = MathHelpers_1.mean(dataY);
1779 var n = dataX.length;
1780 var lft = 0;
1781 var num = 0;
1782 var den = 0;
1783 for (var i = 0; i < n; i++) {
1784 lft += Math.pow(dataY[i] - ymean, 2);
1785 num += (dataX[i] - xmean) * (dataY[i] - ymean);
1786 den += Math.pow(dataX[i] - xmean, 2);
1787 }
1788 return Math.sqrt((lft - num * num / den) / (n - 2));
1789};
1790exports.STEYX = STEYX;
1791/**
1792 * Returns the probability that values in a range are between two limits. Data is the array or range of data in the
1793 * sample.
1794 * @param range - The array or range of data in the sample.
1795 * @param probability - The array or range of the corresponding probabilities
1796 * @param start - The start value of the interval whose probabilities are to be summed.
1797 * @param end - [OPTIONAL] - The end value of the interval whose probabilities are to be summed. If this parameter is
1798 * missing, the probability for the start value is calculated
1799 * @returns {number}
1800 * @constructor
1801 */
1802var PROB = function (range, probability, start, end) {
1803 ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 3, 4, "PROB");
1804 range = Filter_1.Filter.flattenAndThrow(range);
1805 probability = Filter_1.Filter.flattenAndThrow(probability);
1806 if (range.length !== probability.length) {
1807 throw new Errors_1.NAError("PROB has mismatched argument count " + range.length + " vs " + probability.length + ".");
1808 }
1809 var sum = Math_1.SUM(probability);
1810 if (sum <= 0 || sum > 1) {
1811 throw new Errors_1.ValueError("Function PROB parameter 2 should sum to 1, but sums to " + sum + ".");
1812 }
1813 start = TypeConverter_1.TypeConverter.firstValueAsNumber(start);
1814 end = (end === undefined) ? start : TypeConverter_1.TypeConverter.firstValueAsNumber(end);
1815 if (start === end) {
1816 return (range.indexOf(start) >= 0) ? probability[range.indexOf(start)] : 0;
1817 }
1818 var sorted = range.sort(function (a, b) {
1819 return a - b;
1820 });
1821 var n = sorted.length;
1822 var result = 0;
1823 for (var i = 0; i < n; i++) {
1824 if (sorted[i] >= start && sorted[i] <= end) {
1825 result += probability[range.indexOf(sorted[i])];
1826 }
1827 }
1828 return result;
1829};
1830exports.PROB = PROB;
1831/**
1832 * Returns the most commonly occurring value in a range.
1833 * @param values - Range(s) or values to consider.
1834 * @returns {number}
1835 * @constructor
1836 */
1837var MODE = function () {
1838 var values = [];
1839 for (var _i = 0; _i < arguments.length; _i++) {
1840 values[_i] = arguments[_i];
1841 }
1842 ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "MODE");
1843 var range = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber);
1844 var n = range.length;
1845 var count = {};
1846 var maxItems = [];
1847 var max = 0;
1848 var currentItem;
1849 for (var i = 0; i < n; i++) {
1850 currentItem = range[i];
1851 count[currentItem] = count[currentItem] ? count[currentItem] + 1 : 1;
1852 if (count[currentItem] > max) {
1853 max = count[currentItem];
1854 maxItems = [];
1855 }
1856 if (count[currentItem] === max) {
1857 maxItems[maxItems.length] = currentItem;
1858 }
1859 }
1860 if (max === 1 && range.length !== 1) {
1861 throw new Errors_1.NAError("MODE cannot produce a result because no values occur more than once.");
1862 }
1863 return maxItems[0];
1864};
1865exports.MODE = MODE;
1866/**
1867 * Returns the position of a given entry in the entire list, measured either from top to bottom or bottom to top.
1868 * @param value - Value to find the rank of.
1869 * @param data - Values or range of the data-set.
1870 * @param isAscending - [OPTIONAL] The type of rank: 0 to rank from the highest, 1 to rank from the lowest. Defaults to
1871 * 0.
1872 * @returns {number}
1873 * @constructor
1874 */
1875var RANK = function (value, data, isAscending) {
1876 ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 2, 3, "RANK");
1877 value = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
1878 var range = Filter_1.Filter.flattenAndThrow(data).map(TypeConverter_1.TypeConverter.valueToNumber);
1879 isAscending = (typeof isAscending === 'undefined') ? false : isAscending;
1880 var sort = (isAscending) ? function (a, b) {
1881 return a - b;
1882 } : function (a, b) {
1883 return b - a;
1884 };
1885 range = range.sort(sort);
1886 var rangeIndex = range.indexOf(value);
1887 if (rangeIndex === -1) {
1888 throw new Errors_1.NAError("RANK can't produce a result because parameter 1 is not in the dataset.");
1889 }
1890 return range.indexOf(value) + 1;
1891};
1892exports.RANK = RANK;
1893/**
1894 * Returns the position of a given entry in the entire list, measured either from top to bottom or bottom to top. If
1895 * more than one value exists in the same data-set, the average range of the values will be returned.
1896 * @param value - Value to find the rank of.
1897 * @param data - Values or range of the data-set.
1898 * @param isAscending - [OPTIONAL] The type of rank: 0 to rank from the highest, 1 to rank from the lowest. Defaults to
1899 * 0.
1900 * @returns {number}
1901 * @constructor
1902 */
1903var RANK$AVG = function (value, data, isAscending) {
1904 ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 2, 3, "RANK.AVG");
1905 value = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
1906 var range = Filter_1.Filter.flattenAndThrow(data).map(TypeConverter_1.TypeConverter.valueToNumber);
1907 function _countIn(range, value) {
1908 var result = 0;
1909 for (var i = 0; i < range.length; i++) {
1910 if (range[i] === value) {
1911 result++;
1912 }
1913 }
1914 return result;
1915 }
1916 isAscending = (typeof isAscending === 'undefined') ? false : isAscending;
1917 var sort = (isAscending) ? function (a, b) {
1918 return a - b;
1919 } : function (a, b) {
1920 return b - a;
1921 };
1922 range = range.sort(sort);
1923 var rangeIndex = range.indexOf(value);
1924 if (rangeIndex === -1) {
1925 throw new Errors_1.NAError("RANK.AVG can't produce a result because parameter 1 is not in the dataset.");
1926 }
1927 var count = _countIn(range, value);
1928 return (count > 1) ? (2 * rangeIndex + count + 1) / 2 : rangeIndex + 1;
1929};
1930exports.RANK$AVG = RANK$AVG;
1931/**
1932 * Returns the position of a given entry in the entire list, measured either from top to bottom or bottom to top. If
1933 * there is more than one entry of the same value in the dataset, the top rank of the entries will be returned.
1934 * @param value - Value to find the rank of.
1935 * @param data - Values or range of the data-set.
1936 * @param isAscending - [OPTIONAL] The type of rank: 0 to rank from the highest, 1 to rank from the lowest. Defaults to
1937 * 0.
1938 * @returns {number}
1939 * @constructor
1940 */
1941var RANK$EQ = function (value, data, isAscending) {
1942 ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 2, 3, "RANK.EQ");
1943 value = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
1944 var range = Filter_1.Filter.flattenAndThrow(data).map(TypeConverter_1.TypeConverter.valueToNumber);
1945 isAscending = (typeof isAscending === 'undefined') ? false : isAscending;
1946 var sort = (isAscending) ? function (a, b) {
1947 return a - b;
1948 } : function (a, b) {
1949 return b - a;
1950 };
1951 range = range.sort(sort);
1952 var rangeIndex = range.indexOf(value);
1953 if (rangeIndex === -1) {
1954 throw new Errors_1.NAError("RANK.EQ can't produce a result because parameter 1 is not in the dataset.");
1955 }
1956 return range.indexOf(value) + 1;
1957};
1958exports.RANK$EQ = RANK$EQ;
1959/**
1960 * Returns the cumulative lognormal distribution for the given number.
1961 * @param x - The probability value.
1962 * @param meanValue - The mean value of the standard logarithmic distribution.
1963 * @param standardDev - The standard deviation of the standard logarithmic distribution.
1964 * @returns {number}
1965 * @constructor
1966 */
1967var LOGNORMDIST = function (x, meanValue, standardDev) {
1968 ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "LOGNORMDIST");
1969 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
1970 meanValue = TypeConverter_1.TypeConverter.firstValueAsNumber(meanValue);
1971 standardDev = TypeConverter_1.TypeConverter.firstValueAsNumber(standardDev);
1972 if (x <= 0) {
1973 throw new Errors_1.NumError("Function LOGNORMDIST parameter 1 value is " + x + ", but should be greater than 0.");
1974 }
1975 if (standardDev <= 0) {
1976 throw new Errors_1.NumError("Function LOGNORMDIST parameter 3 value is " + standardDev + ", but should be greater than 0.");
1977 }
1978 var a = (Math.log(x) - meanValue) / Math.sqrt(2 * standardDev * standardDev);
1979 return 0.5 + 0.5 * MathHelpers_1.erf(a);
1980};
1981exports.LOGNORMDIST = LOGNORMDIST;
1982/**
1983 * Returns the t-distribution for the given number.
1984 * @param x - Value to use in calculation.
1985 * @param degreesOfFreedom - The number of degrees of freedom for the t-distribution.
1986 * @param tails - 1 returns the one-tailed test, 2 returns the two-tailed test.
1987 * @returns {number}
1988 * @constructor
1989 */
1990var TDIST = function (x, degreesOfFreedom, tails) {
1991 ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "TDIST");
1992 x = TypeConverter_1.TypeConverter.firstValueAsNumber(x);
1993 degreesOfFreedom = TypeConverter_1.TypeConverter.firstValueAsNumber(degreesOfFreedom);
1994 tails = TypeConverter_1.TypeConverter.firstValueAsNumber(tails);
1995 if (tails < 1 || tails > 2) {
1996 throw new Errors_1.NumError("Function TDIST parameter 3 value is " + tails +
1997 ", but valid values are between 1 and 2, inclusively.");
1998 }
1999 if (degreesOfFreedom < 1) {
2000 throw new Errors_1.NumError("Function TDIST parameter 2 value is " + degreesOfFreedom +
2001 ", but it should be greater than or equal to 1.");
2002 }
2003 if (x < 0) {
2004 throw new Errors_1.NumError("Function TDIST parameter 1 value is " + x + ", but it should be greater than or equal to 0.");
2005 }
2006 function _betacf(x, a, b) {
2007 var fpmin = 1e-30;
2008 var m = 1;
2009 var qab = a + b;
2010 var qap = a + 1;
2011 var qam = a - 1;
2012 var c = 1;
2013 var d = 1 - qab * x / qap;
2014 var m2, aa, del, h;
2015 if (Math.abs(d) < fpmin)
2016 d = fpmin;
2017 d = 1 / d;
2018 h = d;
2019 for (; m <= 100; m++) {
2020 m2 = 2 * m;
2021 aa = m * (b - m) * x / ((qam + m2) * (a + m2));
2022 d = 1 + aa * d;
2023 if (Math.abs(d) < fpmin)
2024 d = fpmin;
2025 c = 1 + aa / c;
2026 if (Math.abs(c) < fpmin)
2027 c = fpmin;
2028 d = 1 / d;
2029 h *= d * c;
2030 aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2));
2031 d = 1 + aa * d;
2032 if (Math.abs(d) < fpmin)
2033 d = fpmin;
2034 c = 1 + aa / c;
2035 if (Math.abs(c) < fpmin)
2036 c = fpmin;
2037 d = 1 / d;
2038 del = d * c;
2039 h *= del;
2040 if (Math.abs(del - 1.0) < 3e-7)
2041 break;
2042 }
2043 return h;
2044 }
2045 function _ibeta(x, a, b) {
2046 var bt = (x === 0 || x === 1) ? 0 :
2047 Math.exp(MathHelpers_1.gammaln(a + b) - MathHelpers_1.gammaln(a) -
2048 MathHelpers_1.gammaln(b) + a * Math.log(x) + b *
2049 Math.log(1 - x));
2050 if (x < 0 || x > 1)
2051 return 0;
2052 if (x < (a + 1) / (a + b + 2))
2053 return bt * _betacf(x, a, b) / a;
2054 return 1 - bt * _betacf(1 - x, b, a) / b;
2055 }
2056 function _studenttCDF(x, dof) {
2057 var dof2 = dof / 2;
2058 return _ibeta((x + Math.sqrt(x * x + dof)) /
2059 (2 * Math.sqrt(x * x + dof)), dof2, dof2);
2060 }
2061 return tails * (1 - _studenttCDF(x, degreesOfFreedom));
2062};
2063exports.TDIST = TDIST;
2064/**
2065 * Returns the hypergeometric distribution. X is the number of results achieved in the random sample.
2066 * @param numberOfSuccesses - The number of results achieved in the random sample.
2067 * @param numberOfDraws - The size of the random sample.
2068 * @param successesInPop - The number of possible results in the total population.
2069 * @param populationSize - The size of the total population.
2070 * @returns {number}
2071 * @constructor
2072 */
2073var HYPGEOMDIST = function (numberOfSuccesses, numberOfDraws, successesInPop, populationSize) {
2074 ArgsChecker_1.ArgsChecker.checkLength(arguments, 4, "HYPGEOMDIST");
2075 numberOfSuccesses = TypeConverter_1.TypeConverter.firstValueAsNumber(numberOfSuccesses);
2076 numberOfDraws = TypeConverter_1.TypeConverter.firstValueAsNumber(numberOfDraws);
2077 if (numberOfSuccesses > numberOfDraws) {
2078 throw new Errors_1.NumError("HYPGEOMDIST parameter 1 value is " + numberOfSuccesses
2079 + ", but should be less than or equal to parameter 2 with " + numberOfDraws + ".");
2080 }
2081 if (numberOfSuccesses < 0) {
2082 throw new Errors_1.NumError("HYPGEOMDIST parameter 1 value is " + numberOfSuccesses
2083 + ", but should be greater than or equal to 0.");
2084 }
2085 if (numberOfSuccesses < (numberOfDraws + successesInPop - populationSize)) {
2086 throw new Errors_1.NumError("HYPGEOMDIST parameter 1 value is " + numberOfSuccesses
2087 + ", but should be greater than or equal to " + (numberOfDraws + successesInPop - populationSize) + ".");
2088 }
2089 successesInPop = TypeConverter_1.TypeConverter.firstValueAsNumber(successesInPop);
2090 populationSize = TypeConverter_1.TypeConverter.firstValueAsNumber(populationSize);
2091 return Math_1.COMBIN(successesInPop, numberOfSuccesses) *
2092 Math_1.COMBIN(populationSize - successesInPop, numberOfDraws - numberOfSuccesses) /
2093 Math_1.COMBIN(populationSize, numberOfDraws);
2094};
2095exports.HYPGEOMDIST = HYPGEOMDIST;
2096/**
2097 * Returns the two-tailed P value of a z test with standard distribution.
2098 * @param range - Te array of the data.
2099 * @param value - The value to be tested.
2100 * @param stdDev - [OPTIONAL] The standard deviation of the total population. If this argument is missing, the standard
2101 * deviation of the sample is processed.
2102 * @returns {number}
2103 * @constructor
2104 */
2105var ZTEST = function (range, value, stdDev) {
2106 ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 2, 3, "ZTEST");
2107 range = Filter_1.Filter.flattenAndThrow(range);
2108 value = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
2109 var sd = MoreUtils_1.isUndefined(stdDev) ? STDEV(range) : TypeConverter_1.TypeConverter.firstValueAsNumber(stdDev);
2110 return 1 - NORMSDIST((AVERAGE(range) - value) / (sd / Math.sqrt(range.length)));
2111};
2112exports.ZTEST = ZTEST;