Make JetStream 2
[WebKit-https.git] / PerformanceTests / JetStream2 / ARES-6 / ml / index.js
1 /*
2  * The MIT License (MIT)
3  * 
4  * Copyright (c) 2015 ml.js
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  * 
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  * 
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23 */
24 'use strict';
25
26 // ml-stat array.js
27 const MLStatArray = {};
28 {
29     function compareNumbers(a, b) {
30         return a - b;
31     }
32
33     /**
34      * Computes the sum of the given values
35      * @param {Array} values
36      * @returns {number}
37      */
38     MLStatArray.sum = function sum(values) {
39         var sum = 0;
40         for (var i = 0; i < values.length; i++) {
41             sum += values[i];
42         }
43         return sum;
44     };
45
46     /**
47      * Computes the maximum of the given values
48      * @param {Array} values
49      * @returns {number}
50      */
51     MLStatArray.max = function max(values) {
52         var max = values[0];
53         var l = values.length;
54         for (var i = 1; i < l; i++) {
55             if (values[i] > max) max = values[i];
56         }
57         return max;
58     };
59
60     /**
61      * Computes the minimum of the given values
62      * @param {Array} values
63      * @returns {number}
64      */
65     MLStatArray.min = function min(values) {
66         var min = values[0];
67         var l = values.length;
68         for (var i = 1; i < l; i++) {
69             if (values[i] < min) min = values[i];
70         }
71         return min;
72     };
73
74     /**
75      * Computes the min and max of the given values
76      * @param {Array} values
77      * @returns {{min: number, max: number}}
78      */
79     MLStatArray.minMax = function minMax(values) {
80         var min = values[0];
81         var max = values[0];
82         var l = values.length;
83         for (var i = 1; i < l; i++) {
84             if (values[i] < min) min = values[i];
85             if (values[i] > max) max = values[i];
86         }
87         return {
88             min: min,
89             max: max
90         };
91     };
92
93     /**
94      * Computes the arithmetic mean of the given values
95      * @param {Array} values
96      * @returns {number}
97      */
98     MLStatArray.arithmeticMean = function arithmeticMean(values) {
99         var sum = 0;
100         var l = values.length;
101         for (var i = 0; i < l; i++) {
102             sum += values[i];
103         }
104         return sum / l;
105     };
106
107     /**
108      * {@link arithmeticMean}
109      */
110     MLStatArray.mean = MLStatArray.arithmeticMean;
111
112     /**
113      * Computes the geometric mean of the given values
114      * @param {Array} values
115      * @returns {number}
116      */
117     MLStatArray.geometricMean = function geometricMean(values) {
118         var mul = 1;
119         var l = values.length;
120         for (var i = 0; i < l; i++) {
121             mul *= values[i];
122         }
123         return Math.pow(mul, 1 / l);
124     };
125
126     /**
127      * Computes the mean of the log of the given values
128      * If the return value is exponentiated, it gives the same result as the
129      * geometric mean.
130      * @param {Array} values
131      * @returns {number}
132      */
133     MLStatArray.logMean = function logMean(values) {
134         var lnsum = 0;
135         var l = values.length;
136         for (var i = 0; i < l; i++) {
137             lnsum += Math.log(values[i]);
138         }
139         return lnsum / l;
140     };
141
142     /**
143      * Computes the weighted grand mean for a list of means and sample sizes
144      * @param {Array} means - Mean values for each set of samples
145      * @param {Array} samples - Number of original values for each set of samples
146      * @returns {number}
147      */
148     MLStatArray.grandMean = function grandMean(means, samples) {
149         var sum = 0;
150         var n = 0;
151         var l = means.length;
152         for (var i = 0; i < l; i++) {
153             sum += samples[i] * means[i];
154             n += samples[i];
155         }
156         return sum / n;
157     };
158
159     /**
160      * Computes the truncated mean of the given values using a given percentage
161      * @param {Array} values
162      * @param {number} percent - The percentage of values to keep (range: [0,1])
163      * @param {boolean} [alreadySorted=false]
164      * @returns {number}
165      */
166     MLStatArray.truncatedMean = function truncatedMean(values, percent, alreadySorted) {
167         if (alreadySorted === undefined) alreadySorted = false;
168         if (!alreadySorted) {
169             values = [].concat(values).sort(compareNumbers);
170         }
171         var l = values.length;
172         var k = Math.floor(l * percent);
173         var sum = 0;
174         for (var i = k; i < (l - k); i++) {
175             sum += values[i];
176         }
177         return sum / (l - 2 * k);
178     };
179
180     /**
181      * Computes the harmonic mean of the given values
182      * @param {Array} values
183      * @returns {number}
184      */
185     MLStatArray.harmonicMean = function harmonicMean(values) {
186         var sum = 0;
187         var l = values.length;
188         for (var i = 0; i < l; i++) {
189             if (values[i] === 0) {
190                 throw new RangeError('value at index ' + i + 'is zero');
191             }
192             sum += 1 / values[i];
193         }
194         return l / sum;
195     };
196
197     /**
198      * Computes the contraharmonic mean of the given values
199      * @param {Array} values
200      * @returns {number}
201      */
202     MLStatArray.contraHarmonicMean = function contraHarmonicMean(values) {
203         var r1 = 0;
204         var r2 = 0;
205         var l = values.length;
206         for (var i = 0; i < l; i++) {
207             r1 += values[i] * values[i];
208             r2 += values[i];
209         }
210         if (r2 < 0) {
211             throw new RangeError('sum of values is negative');
212         }
213         return r1 / r2;
214     };
215
216     /**
217      * Computes the median of the given values
218      * @param {Array} values
219      * @param {boolean} [alreadySorted=false]
220      * @returns {number}
221      */
222     MLStatArray.median = function median(values, alreadySorted) {
223         if (alreadySorted === undefined) alreadySorted = false;
224         if (!alreadySorted) {
225             values = [].concat(values).sort(compareNumbers);
226         }
227         var l = values.length;
228         var half = Math.floor(l / 2);
229         if (l % 2 === 0) {
230             return (values[half - 1] + values[half]) * 0.5;
231         } else {
232             return values[half];
233         }
234     };
235
236     /**
237      * Computes the variance of the given values
238      * @param {Array} values
239      * @param {boolean} [unbiased=true] - if true, divide by (n-1); if false, divide by n.
240      * @returns {number}
241      */
242     MLStatArray.variance = function variance(values, unbiased) {
243         if (unbiased === undefined) unbiased = true;
244         var theMean = MLStatArray.mean(values);
245         var theVariance = 0;
246         var l = values.length;
247
248         for (var i = 0; i < l; i++) {
249             var x = values[i] - theMean;
250             theVariance += x * x;
251         }
252
253         if (unbiased) {
254             return theVariance / (l - 1);
255         } else {
256             return theVariance / l;
257         }
258     };
259
260     /**
261      * Computes the standard deviation of the given values
262      * @param {Array} values
263      * @param {boolean} [unbiased=true] - if true, divide by (n-1); if false, divide by n.
264      * @returns {number}
265      */
266     MLStatArray.standardDeviation = function standardDeviation(values, unbiased) {
267         return Math.sqrt(MLStatArray.variance(values, unbiased));
268     };
269
270     MLStatArray.standardError = function standardError(values) {
271         return MLStatArray.standardDeviation(values) / Math.sqrt(values.length);
272     };
273
274     /**
275      * IEEE Transactions on biomedical engineering, vol. 52, no. 1, january 2005, p. 76-
276      * Calculate the standard deviation via the Median of the absolute deviation
277      *  The formula for the standard deviation only holds for Gaussian random variables.
278      * @returns {{mean: number, stdev: number}}
279      */
280     MLStatArray.robustMeanAndStdev = function robustMeanAndStdev(y) {
281         var mean = 0, stdev = 0;
282         var length = y.length, i = 0;
283         for (i = 0; i < length; i++) {
284             mean += y[i];
285         }
286         mean /= length;
287         var averageDeviations = new Array(length);
288         for (i = 0; i < length; i++)
289             averageDeviations[i] = Math.abs(y[i] - mean);
290         averageDeviations.sort(compareNumbers);
291         if (length % 2 === 1) {
292             stdev = averageDeviations[(length - 1) / 2] / 0.6745;
293         } else {
294             stdev = 0.5 * (averageDeviations[length / 2] + averageDeviations[length / 2 - 1]) / 0.6745;
295         }
296
297         return {
298             mean: mean,
299             stdev: stdev
300         };
301     };
302
303     MLStatArray.quartiles = function quartiles(values, alreadySorted) {
304         if (typeof (alreadySorted) === 'undefined') alreadySorted = false;
305         if (!alreadySorted) {
306             values = [].concat(values).sort(compareNumbers);
307         }
308
309         var quart = values.length / 4;
310         var q1 = values[Math.ceil(quart) - 1];
311         var q2 = MLStatArray.median(values, true);
312         var q3 = values[Math.ceil(quart * 3) - 1];
313
314         return {q1: q1, q2: q2, q3: q3};
315     };
316
317     MLStatArray.pooledStandardDeviation = function pooledStandardDeviation(samples, unbiased) {
318         return Math.sqrt(MLStatArray.pooledVariance(samples, unbiased));
319     };
320
321     MLStatArray.pooledVariance = function pooledVariance(samples, unbiased) {
322         if (typeof (unbiased) === 'undefined') unbiased = true;
323         var sum = 0;
324         var length = 0, l = samples.length;
325         for (var i = 0; i < l; i++) {
326             var values = samples[i];
327             var vari = MLStatArray.variance(values);
328
329             sum += (values.length - 1) * vari;
330
331             if (unbiased)
332                 length += values.length - 1;
333             else
334                 length += values.length;
335         }
336         return sum / length;
337     };
338
339     MLStatArray.mode = function mode(values) {
340         var l = values.length,
341             itemCount = new Array(l),
342             i;
343         for (i = 0; i < l; i++) {
344             itemCount[i] = 0;
345         }
346         var itemArray = new Array(l);
347         var count = 0;
348
349         for (i = 0; i < l; i++) {
350             var index = itemArray.indexOf(values[i]);
351             if (index >= 0)
352                 itemCount[index]++;
353             else {
354                 itemArray[count] = values[i];
355                 itemCount[count] = 1;
356                 count++;
357             }
358         }
359
360         var maxValue = 0, maxIndex = 0;
361         for (i = 0; i < count; i++) {
362             if (itemCount[i] > maxValue) {
363                 maxValue = itemCount[i];
364                 maxIndex = i;
365             }
366         }
367
368         return itemArray[maxIndex];
369     };
370
371     MLStatArray.covariance = function covariance(vector1, vector2, unbiased) {
372         if (typeof (unbiased) === 'undefined') unbiased = true;
373         var mean1 = MLStatArray.mean(vector1);
374         var mean2 = MLStatArray.mean(vector2);
375
376         if (vector1.length !== vector2.length)
377             throw 'Vectors do not have the same dimensions';
378
379         var cov = 0, l = vector1.length;
380         for (var i = 0; i < l; i++) {
381             var x = vector1[i] - mean1;
382             var y = vector2[i] - mean2;
383             cov += x * y;
384         }
385
386         if (unbiased)
387             return cov / (l - 1);
388         else
389             return cov / l;
390     };
391
392     MLStatArray.skewness = function skewness(values, unbiased) {
393         if (typeof (unbiased) === 'undefined') unbiased = true;
394         var theMean = MLStatArray.mean(values);
395
396         var s2 = 0, s3 = 0, l = values.length;
397         for (var i = 0; i < l; i++) {
398             var dev = values[i] - theMean;
399             s2 += dev * dev;
400             s3 += dev * dev * dev;
401         }
402         var m2 = s2 / l;
403         var m3 = s3 / l;
404
405         var g = m3 / (Math.pow(m2, 3 / 2.0));
406         if (unbiased) {
407             var a = Math.sqrt(l * (l - 1));
408             var b = l - 2;
409             return (a / b) * g;
410         } else {
411             return g;
412         }
413     };
414
415     MLStatArray.kurtosis = function kurtosis(values, unbiased) {
416         if (typeof (unbiased) === 'undefined') unbiased = true;
417         var theMean = MLStatArray.mean(values);
418         var n = values.length, s2 = 0, s4 = 0;
419
420         for (var i = 0; i < n; i++) {
421             var dev = values[i] - theMean;
422             s2 += dev * dev;
423             s4 += dev * dev * dev * dev;
424         }
425         var m2 = s2 / n;
426         var m4 = s4 / n;
427
428         if (unbiased) {
429             var v = s2 / (n - 1);
430             var a = (n * (n + 1)) / ((n - 1) * (n - 2) * (n - 3));
431             var b = s4 / (v * v);
432             var c = ((n - 1) * (n - 1)) / ((n - 2) * (n - 3));
433
434             return a * b - 3 * c;
435         } else {
436             return m4 / (m2 * m2) - 3;
437         }
438     };
439
440     MLStatArray.entropy = function entropy(values, eps) {
441         if (typeof (eps) === 'undefined') eps = 0;
442         var sum = 0, l = values.length;
443         for (var i = 0; i < l; i++)
444             sum += values[i] * Math.log(values[i] + eps);
445         return -sum;
446     };
447
448     MLStatArray.weightedMean = function weightedMean(values, weights) {
449         var sum = 0, l = values.length;
450         for (var i = 0; i < l; i++)
451             sum += values[i] * weights[i];
452         return sum;
453     };
454
455     MLStatArray.weightedStandardDeviation = function weightedStandardDeviation(values, weights) {
456         return Math.sqrt(MLStatArray.weightedVariance(values, weights));
457     };
458
459     MLStatArray.weightedVariance = function weightedVariance(values, weights) {
460         var theMean = MLStatArray.weightedMean(values, weights);
461         var vari = 0, l = values.length;
462         var a = 0, b = 0;
463
464         for (var i = 0; i < l; i++) {
465             var z = values[i] - theMean;
466             var w = weights[i];
467
468             vari += w * (z * z);
469             b += w;
470             a += w * w;
471         }
472
473         return vari * (b / (b * b - a));
474     };
475
476     MLStatArray.center = function center(values, inPlace) {
477         if (typeof (inPlace) === 'undefined') inPlace = false;
478
479         var result = values;
480         if (!inPlace)
481             result = [].concat(values);
482
483         var theMean = MLStatArray.mean(result), l = result.length;
484         for (var i = 0; i < l; i++)
485             result[i] -= theMean;
486     };
487
488     MLStatArray.standardize = function standardize(values, standardDev, inPlace) {
489         if (typeof (standardDev) === 'undefined') standardDev = MLStatArray.standardDeviation(values);
490         if (typeof (inPlace) === 'undefined') inPlace = false;
491         var l = values.length;
492         var result = inPlace ? values : new Array(l);
493         for (var i = 0; i < l; i++)
494             result[i] = values[i] / standardDev;
495         return result;
496     };
497
498     MLStatArray.cumulativeSum = function cumulativeSum(array) {
499         var l = array.length;
500         var result = new Array(l);
501         result[0] = array[0];
502         for (var i = 1; i < l; i++)
503             result[i] = result[i - 1] + array[i];
504         return result;
505     };
506 }
507
508
509 // ml-stat matrix.js
510 const MLStatMatrix = {};
511 {
512     let arrayStat = MLStatArray;
513
514     function compareNumbers(a, b) {
515         return a - b;
516     }
517
518     MLStatMatrix.max = function max(matrix) {
519         var max = -Infinity;
520         for (var i = 0; i < matrix.length; i++) {
521             for (var j = 0; j < matrix[i].length; j++) {
522                 if (matrix[i][j] > max) max = matrix[i][j];
523             }
524         }
525         return max;
526     };
527
528     MLStatMatrix.min = function min(matrix) {
529         var min = Infinity;
530         for (var i = 0; i < matrix.length; i++) {
531             for (var j = 0; j < matrix[i].length; j++) {
532                 if (matrix[i][j] < min) min = matrix[i][j];
533             }
534         }
535         return min;
536     };
537
538     MLStatMatrix.minMax = function minMax(matrix) {
539         var min = Infinity;
540         var max = -Infinity;
541         for (var i = 0; i < matrix.length; i++) {
542             for (var j = 0; j < matrix[i].length; j++) {
543                 if (matrix[i][j] < min) min = matrix[i][j];
544                 if (matrix[i][j] > max) max = matrix[i][j];
545             }
546         }
547         return {
548             min:min,
549             max:max
550         };
551     };
552
553     MLStatMatrix.entropy = function entropy(matrix, eps) {
554         if (typeof (eps) === 'undefined') {
555             eps = 0;
556         }
557         var sum = 0,
558             l1 = matrix.length,
559             l2 = matrix[0].length;
560         for (var i = 0; i < l1; i++) {
561             for (var j = 0; j < l2; j++) {
562                 sum += matrix[i][j] * Math.log(matrix[i][j] + eps);
563             }
564         }
565         return -sum;
566     };
567
568     MLStatMatrix.mean = function mean(matrix, dimension) {
569         if (typeof (dimension) === 'undefined') {
570             dimension = 0;
571         }
572         var rows = matrix.length,
573             cols = matrix[0].length,
574             theMean, N, i, j;
575
576         if (dimension === -1) {
577             theMean = [0];
578             N = rows * cols;
579             for (i = 0; i < rows; i++) {
580                 for (j = 0; j < cols; j++) {
581                     theMean[0] += matrix[i][j];
582                 }
583             }
584             theMean[0] /= N;
585         } else if (dimension === 0) {
586             theMean = new Array(cols);
587             N = rows;
588             for (j = 0; j < cols; j++) {
589                 theMean[j] = 0;
590                 for (i = 0; i < rows; i++) {
591                     theMean[j] += matrix[i][j];
592                 }
593                 theMean[j] /= N;
594             }
595         } else if (dimension === 1) {
596             theMean = new Array(rows);
597             N = cols;
598             for (j = 0; j < rows; j++) {
599                 theMean[j] = 0;
600                 for (i = 0; i < cols; i++) {
601                     theMean[j] += matrix[j][i];
602                 }
603                 theMean[j] /= N;
604             }
605         } else {
606             throw new Error('Invalid dimension');
607         }
608         return theMean;
609     };
610
611     MLStatMatrix.sum = function sum(matrix, dimension) {
612         if (typeof (dimension) === 'undefined') {
613             dimension = 0;
614         }
615         var rows = matrix.length,
616             cols = matrix[0].length,
617             theSum, i, j;
618
619         if (dimension === -1) {
620             theSum = [0];
621             for (i = 0; i < rows; i++) {
622                 for (j = 0; j < cols; j++) {
623                     theSum[0] += matrix[i][j];
624                 }
625             }
626         } else if (dimension === 0) {
627             theSum = new Array(cols);
628             for (j = 0; j < cols; j++) {
629                 theSum[j] = 0;
630                 for (i = 0; i < rows; i++) {
631                     theSum[j] += matrix[i][j];
632                 }
633             }
634         } else if (dimension === 1) {
635             theSum = new Array(rows);
636             for (j = 0; j < rows; j++) {
637                 theSum[j] = 0;
638                 for (i = 0; i < cols; i++) {
639                     theSum[j] += matrix[j][i];
640                 }
641             }
642         } else {
643             throw new Error('Invalid dimension');
644         }
645         return theSum;
646     };
647
648     MLStatMatrix.product = function product(matrix, dimension) {
649         if (typeof (dimension) === 'undefined') {
650             dimension = 0;
651         }
652         var rows = matrix.length,
653             cols = matrix[0].length,
654             theProduct, i, j;
655
656         if (dimension === -1) {
657             theProduct = [1];
658             for (i = 0; i < rows; i++) {
659                 for (j = 0; j < cols; j++) {
660                     theProduct[0] *= matrix[i][j];
661                 }
662             }
663         } else if (dimension === 0) {
664             theProduct = new Array(cols);
665             for (j = 0; j < cols; j++) {
666                 theProduct[j] = 1;
667                 for (i = 0; i < rows; i++) {
668                     theProduct[j] *= matrix[i][j];
669                 }
670             }
671         } else if (dimension === 1) {
672             theProduct = new Array(rows);
673             for (j = 0; j < rows; j++) {
674                 theProduct[j] = 1;
675                 for (i = 0; i < cols; i++) {
676                     theProduct[j] *= matrix[j][i];
677                 }
678             }
679         } else {
680             throw new Error('Invalid dimension');
681         }
682         return theProduct;
683     };
684
685     MLStatMatrix.standardDeviation = function standardDeviation(matrix, means, unbiased) {
686         var vari = MLStatMatrix.variance(matrix, means, unbiased), l = vari.length;
687         for (var i = 0; i < l; i++) {
688             vari[i] = Math.sqrt(vari[i]);
689         }
690         return vari;
691     };
692
693     MLStatMatrix.variance = function variance(matrix, means, unbiased) {
694         if (typeof (unbiased) === 'undefined') {
695             unbiased = true;
696         }
697         means = means || MLStatMatrix.mean(matrix);
698         var rows = matrix.length;
699         if (rows === 0) return [];
700         var cols = matrix[0].length;
701         var vari = new Array(cols);
702
703         for (var j = 0; j < cols; j++) {
704             var sum1 = 0, sum2 = 0, x = 0;
705             for (var i = 0; i < rows; i++) {
706                 x = matrix[i][j] - means[j];
707                 sum1 += x;
708                 sum2 += x * x;
709             }
710             if (unbiased) {
711                 vari[j] = (sum2 - ((sum1 * sum1) / rows)) / (rows - 1);
712             } else {
713                 vari[j] = (sum2 - ((sum1 * sum1) / rows)) / rows;
714             }
715         }
716         return vari;
717     };
718
719     MLStatMatrix.median = function median(matrix) {
720         var rows = matrix.length, cols = matrix[0].length;
721         var medians = new Array(cols);
722
723         for (var i = 0; i < cols; i++) {
724             var data = new Array(rows);
725             for (var j = 0; j < rows; j++) {
726                 data[j] = matrix[j][i];
727             }
728             data.sort(compareNumbers);
729             var N = data.length;
730             if (N % 2 === 0) {
731                 medians[i] = (data[N / 2] + data[(N / 2) - 1]) * 0.5;
732             } else {
733                 medians[i] = data[Math.floor(N / 2)];
734             }
735         }
736         return medians;
737     };
738
739     MLStatMatrix.mode = function mode(matrix) {
740         var rows = matrix.length,
741             cols = matrix[0].length,
742             modes = new Array(cols),
743             i, j;
744         for (i = 0; i < cols; i++) {
745             var itemCount = new Array(rows);
746             for (var k = 0; k < rows; k++) {
747                 itemCount[k] = 0;
748             }
749             var itemArray = new Array(rows);
750             var count = 0;
751
752             for (j = 0; j < rows; j++) {
753                 var index = itemArray.indexOf(matrix[j][i]);
754                 if (index >= 0) {
755                     itemCount[index]++;
756                 } else {
757                     itemArray[count] = matrix[j][i];
758                     itemCount[count] = 1;
759                     count++;
760                 }
761             }
762
763             var maxValue = 0, maxIndex = 0;
764             for (j = 0; j < count; j++) {
765                 if (itemCount[j] > maxValue) {
766                     maxValue = itemCount[j];
767                     maxIndex = j;
768                 }
769             }
770
771             modes[i] = itemArray[maxIndex];
772         }
773         return modes;
774     };
775
776     MLStatMatrix.skewness = function skewness(matrix, unbiased) {
777         if (typeof (unbiased) === 'undefined') unbiased = true;
778         var means = MLStatMatrix.mean(matrix);
779         var n = matrix.length, l = means.length;
780         var skew = new Array(l);
781
782         for (var j = 0; j < l; j++) {
783             var s2 = 0, s3 = 0;
784             for (var i = 0; i < n; i++) {
785                 var dev = matrix[i][j] - means[j];
786                 s2 += dev * dev;
787                 s3 += dev * dev * dev;
788             }
789
790             var m2 = s2 / n;
791             var m3 = s3 / n;
792             var g = m3 / Math.pow(m2, 3 / 2);
793
794             if (unbiased) {
795                 var a = Math.sqrt(n * (n - 1));
796                 var b = n - 2;
797                 skew[j] = (a / b) * g;
798             } else {
799                 skew[j] = g;
800             }
801         }
802         return skew;
803     };
804
805     MLStatMatrix.kurtosis = function kurtosis(matrix, unbiased) {
806         if (typeof (unbiased) === 'undefined') unbiased = true;
807         var means = MLStatMatrix.mean(matrix);
808         var n = matrix.length, m = matrix[0].length;
809         var kurt = new Array(m);
810
811         for (var j = 0; j < m; j++) {
812             var s2 = 0, s4 = 0;
813             for (var i = 0; i < n; i++) {
814                 var dev = matrix[i][j] - means[j];
815                 s2 += dev * dev;
816                 s4 += dev * dev * dev * dev;
817             }
818             var m2 = s2 / n;
819             var m4 = s4 / n;
820
821             if (unbiased) {
822                 var v = s2 / (n - 1);
823                 var a = (n * (n + 1)) / ((n - 1) * (n - 2) * (n - 3));
824                 var b = s4 / (v * v);
825                 var c = ((n - 1) * (n - 1)) / ((n - 2) * (n - 3));
826                 kurt[j] = a * b - 3 * c;
827             } else {
828                 kurt[j] = m4 / (m2 * m2) - 3;
829             }
830         }
831         return kurt;
832     };
833
834     MLStatMatrix.standardError = function standardError(matrix) {
835         var samples = matrix.length;
836         var standardDeviations = MLStatMatrix.standardDeviation(matrix);
837         var l = standardDeviations.length;
838         var standardErrors = new Array(l);
839         var sqrtN = Math.sqrt(samples);
840
841         for (var i = 0; i < l; i++) {
842             standardErrors[i] = standardDeviations[i] / sqrtN;
843         }
844         return standardErrors;
845     };
846
847     MLStatMatrix.covariance = function covariance(matrix, dimension) {
848         return MLStatMatrix.scatter(matrix, undefined, dimension);
849     };
850
851     MLStatMatrix.scatter = function scatter(matrix, divisor, dimension) {
852         if (typeof (dimension) === 'undefined') {
853             dimension = 0;
854         }
855         if (typeof (divisor) === 'undefined') {
856             if (dimension === 0) {
857                 divisor = matrix.length - 1;
858             } else if (dimension === 1) {
859                 divisor = matrix[0].length - 1;
860             }
861         }
862         var means = MLStatMatrix.mean(matrix, dimension);
863         var rows = matrix.length;
864         if (rows === 0) {
865             return [[]];
866         }
867         var cols = matrix[0].length,
868             cov, i, j, s, k;
869
870         if (dimension === 0) {
871             cov = new Array(cols);
872             for (i = 0; i < cols; i++) {
873                 cov[i] = new Array(cols);
874             }
875             for (i = 0; i < cols; i++) {
876                 for (j = i; j < cols; j++) {
877                     s = 0;
878                     for (k = 0; k < rows; k++) {
879                         s += (matrix[k][j] - means[j]) * (matrix[k][i] - means[i]);
880                     }
881                     s /= divisor;
882                     cov[i][j] = s;
883                     cov[j][i] = s;
884                 }
885             }
886         } else if (dimension === 1) {
887             cov = new Array(rows);
888             for (i = 0; i < rows; i++) {
889                 cov[i] = new Array(rows);
890             }
891             for (i = 0; i < rows; i++) {
892                 for (j = i; j < rows; j++) {
893                     s = 0;
894                     for (k = 0; k < cols; k++) {
895                         s += (matrix[j][k] - means[j]) * (matrix[i][k] - means[i]);
896                     }
897                     s /= divisor;
898                     cov[i][j] = s;
899                     cov[j][i] = s;
900                 }
901             }
902         } else {
903             throw new Error('Invalid dimension');
904         }
905
906         return cov;
907     };
908
909     MLStatMatrix.correlation = function correlation(matrix) {
910         var means = MLStatMatrix.mean(matrix),
911             standardDeviations = MLStatMatrix.standardDeviation(matrix, true, means),
912             scores = MLStatMatrix.zScores(matrix, means, standardDeviations),
913             rows = matrix.length,
914             cols = matrix[0].length,
915             i, j;
916
917         var cor = new Array(cols);
918         for (i = 0; i < cols; i++) {
919             cor[i] = new Array(cols);
920         }
921         for (i = 0; i < cols; i++) {
922             for (j = i; j < cols; j++) {
923                 var c = 0;
924                 for (var k = 0, l = scores.length; k < l; k++) {
925                     c += scores[k][j] * scores[k][i];
926                 }
927                 c /= rows - 1;
928                 cor[i][j] = c;
929                 cor[j][i] = c;
930             }
931         }
932         return cor;
933     };
934
935     MLStatMatrix.zScores = function zScores(matrix, means, standardDeviations) {
936         means = means || MLStatMatrix.mean(matrix);
937         if (typeof (standardDeviations) === 'undefined') standardDeviations = MLStatMatrix.standardDeviation(matrix, true, means);
938         return MLStatMatrix.standardize(MLStatMatrix.center(matrix, means, false), standardDeviations, true);
939     };
940
941     MLStatMatrix.center = function center(matrix, means, inPlace) {
942         means = means || MLStatMatrix.mean(matrix);
943         var result = matrix,
944             l = matrix.length,
945             i, j, jj;
946
947         if (!inPlace) {
948             result = new Array(l);
949             for (i = 0; i < l; i++) {
950                 result[i] = new Array(matrix[i].length);
951             }
952         }
953
954         for (i = 0; i < l; i++) {
955             var row = result[i];
956             for (j = 0, jj = row.length; j < jj; j++) {
957                 row[j] = matrix[i][j] - means[j];
958             }
959         }
960         return result;
961     };
962
963     MLStatMatrix.standardize = function standardize(matrix, standardDeviations, inPlace) {
964         if (typeof (standardDeviations) === 'undefined') standardDeviations = MLStatMatrix.standardDeviation(matrix);
965         var result = matrix,
966             l = matrix.length,
967             i, j, jj;
968
969         if (!inPlace) {
970             result = new Array(l);
971             for (i = 0; i < l; i++) {
972                 result[i] = new Array(matrix[i].length);
973             }
974         }
975
976         for (i = 0; i < l; i++) {
977             var resultRow = result[i];
978             var sourceRow = matrix[i];
979             for (j = 0, jj = resultRow.length; j < jj; j++) {
980                 if (standardDeviations[j] !== 0 && !isNaN(standardDeviations[j])) {
981                     resultRow[j] = sourceRow[j] / standardDeviations[j];
982                 }
983             }
984         }
985         return result;
986     };
987
988     MLStatMatrix.weightedVariance = function weightedVariance(matrix, weights) {
989         var means = MLStatMatrix.mean(matrix);
990         var rows = matrix.length;
991         if (rows === 0) return [];
992         var cols = matrix[0].length;
993         var vari = new Array(cols);
994
995         for (var j = 0; j < cols; j++) {
996             var sum = 0;
997             var a = 0, b = 0;
998
999             for (var i = 0; i < rows; i++) {
1000                 var z = matrix[i][j] - means[j];
1001                 var w = weights[i];
1002
1003                 sum += w * (z * z);
1004                 b += w;
1005                 a += w * w;
1006             }
1007
1008             vari[j] = sum * (b / (b * b - a));
1009         }
1010
1011         return vari;
1012     };
1013
1014     MLStatMatrix.weightedMean = function weightedMean(matrix, weights, dimension) {
1015         if (typeof (dimension) === 'undefined') {
1016             dimension = 0;
1017         }
1018         var rows = matrix.length;
1019         if (rows === 0) return [];
1020         var cols = matrix[0].length,
1021             means, i, ii, j, w, row;
1022
1023         if (dimension === 0) {
1024             means = new Array(cols);
1025             for (i = 0; i < cols; i++) {
1026                 means[i] = 0;
1027             }
1028             for (i = 0; i < rows; i++) {
1029                 row = matrix[i];
1030                 w = weights[i];
1031                 for (j = 0; j < cols; j++) {
1032                     means[j] += row[j] * w;
1033                 }
1034             }
1035         } else if (dimension === 1) {
1036             means = new Array(rows);
1037             for (i = 0; i < rows; i++) {
1038                 means[i] = 0;
1039             }
1040             for (j = 0; j < rows; j++) {
1041                 row = matrix[j];
1042                 w = weights[j];
1043                 for (i = 0; i < cols; i++) {
1044                     means[j] += row[i] * w;
1045                 }
1046             }
1047         } else {
1048             throw new Error('Invalid dimension');
1049         }
1050
1051         var weightSum = arrayStat.sum(weights);
1052         if (weightSum !== 0) {
1053             for (i = 0, ii = means.length; i < ii; i++) {
1054                 means[i] /= weightSum;
1055             }
1056         }
1057         return means;
1058     };
1059
1060     MLStatMatrix.weightedCovariance = function weightedCovariance(matrix, weights, means, dimension) {
1061         dimension = dimension || 0;
1062         means = means || MLStatMatrix.weightedMean(matrix, weights, dimension);
1063         var s1 = 0, s2 = 0;
1064         for (var i = 0, ii = weights.length; i < ii; i++) {
1065             s1 += weights[i];
1066             s2 += weights[i] * weights[i];
1067         }
1068         var factor = s1 / (s1 * s1 - s2);
1069         return MLStatMatrix.weightedScatter(matrix, weights, means, factor, dimension);
1070     };
1071
1072     MLStatMatrix.weightedScatter = function weightedScatter(matrix, weights, means, factor, dimension) {
1073         dimension = dimension || 0;
1074         means = means || MLStatMatrix.weightedMean(matrix, weights, dimension);
1075         if (typeof (factor) === 'undefined') {
1076             factor = 1;
1077         }
1078         var rows = matrix.length;
1079         if (rows === 0) {
1080             return [[]];
1081         }
1082         var cols = matrix[0].length,
1083             cov, i, j, k, s;
1084
1085         if (dimension === 0) {
1086             cov = new Array(cols);
1087             for (i = 0; i < cols; i++) {
1088                 cov[i] = new Array(cols);
1089             }
1090             for (i = 0; i < cols; i++) {
1091                 for (j = i; j < cols; j++) {
1092                     s = 0;
1093                     for (k = 0; k < rows; k++) {
1094                         s += weights[k] * (matrix[k][j] - means[j]) * (matrix[k][i] - means[i]);
1095                     }
1096                     cov[i][j] = s * factor;
1097                     cov[j][i] = s * factor;
1098                 }
1099             }
1100         } else if (dimension === 1) {
1101             cov = new Array(rows);
1102             for (i = 0; i < rows; i++) {
1103                 cov[i] = new Array(rows);
1104             }
1105             for (i = 0; i < rows; i++) {
1106                 for (j = i; j < rows; j++) {
1107                     s = 0;
1108                     for (k = 0; k < cols; k++) {
1109                         s += weights[k] * (matrix[j][k] - means[j]) * (matrix[i][k] - means[i]);
1110                     }
1111                     cov[i][j] = s * factor;
1112                     cov[j][i] = s * factor;
1113                 }
1114             }
1115         } else {
1116             throw new Error('Invalid dimension');
1117         }
1118
1119         return cov;
1120     };
1121 }
1122
1123 // ml-stat index.js
1124 const MLStat = {};
1125 {
1126     MLStat.array = MLStatArray;
1127     MLStat.matrix = MLStatMatrix;
1128 }
1129
1130
1131 // ml-array-utils ArrayUtils.js
1132 const MLArrayUtilsArrayUtils = {};
1133 {
1134     const Stat = MLStat.array;
1135     /**
1136      * Function that returns an array of points given 1D array as follows:
1137      *
1138      * [x1, y1, .. , x2, y2, ..]
1139      *
1140      * And receive the number of dimensions of each point.
1141      * @param array
1142      * @param dimensions
1143      * @returns {Array} - Array of points.
1144      */
1145     function coordArrayToPoints(array, dimensions) {
1146         if(array.length % dimensions !== 0) {
1147             throw new RangeError('Dimensions number must be accordance with the size of the array.');
1148         }
1149
1150         var length = array.length / dimensions;
1151         var pointsArr = new Array(length);
1152
1153         var k = 0;
1154         for(var i = 0; i < array.length; i += dimensions) {
1155             var point = new Array(dimensions);
1156             for(var j = 0; j < dimensions; ++j) {
1157                 point[j] = array[i + j];
1158             }
1159
1160             pointsArr[k] = point;
1161             k++;
1162         }
1163
1164         return pointsArr;
1165     }
1166
1167
1168     /**
1169      * Function that given an array as follows:
1170      * [x1, y1, .. , x2, y2, ..]
1171      *
1172      * Returns an array as follows:
1173      * [[x1, x2, ..], [y1, y2, ..], [ .. ]]
1174      *
1175      * And receives the number of dimensions of each coordinate.
1176      * @param array
1177      * @param dimensions
1178      * @returns {Array} - Matrix of coordinates
1179      */
1180     function coordArrayToCoordMatrix(array, dimensions) {
1181         if(array.length % dimensions !== 0) {
1182             throw new RangeError('Dimensions number must be accordance with the size of the array.');
1183         }
1184
1185         var coordinatesArray = new Array(dimensions);
1186         var points = array.length / dimensions;
1187         for (var i = 0; i < coordinatesArray.length; i++) {
1188             coordinatesArray[i] = new Array(points);
1189         }
1190
1191         for(i = 0; i < array.length; i += dimensions) {
1192             for(var j = 0; j < dimensions; ++j) {
1193                 var currentPoint = Math.floor(i / dimensions);
1194                 coordinatesArray[j][currentPoint] = array[i + j];
1195             }
1196         }
1197
1198         return coordinatesArray;
1199     }
1200
1201     /**
1202      * Function that receives a coordinate matrix as follows:
1203      * [[x1, x2, ..], [y1, y2, ..], [ .. ]]
1204      *
1205      * Returns an array of coordinates as follows:
1206      * [x1, y1, .. , x2, y2, ..]
1207      *
1208      * @param coordMatrix
1209      * @returns {Array}
1210      */
1211     function coordMatrixToCoordArray(coordMatrix) {
1212         var coodinatesArray = new Array(coordMatrix.length * coordMatrix[0].length);
1213         var k = 0;
1214         for(var i = 0; i < coordMatrix[0].length; ++i) {
1215             for(var j = 0; j < coordMatrix.length; ++j) {
1216                 coodinatesArray[k] = coordMatrix[j][i];
1217                 ++k;
1218             }
1219         }
1220
1221         return coodinatesArray;
1222     }
1223
1224     /**
1225      * Tranpose a matrix, this method is for coordMatrixToPoints and
1226      * pointsToCoordMatrix, that because only transposing the matrix
1227      * you can change your representation.
1228      *
1229      * @param matrix
1230      * @returns {Array}
1231      */
1232     function transpose(matrix) {
1233         var resultMatrix = new Array(matrix[0].length);
1234         for(var i = 0; i < resultMatrix.length; ++i) {
1235             resultMatrix[i] = new Array(matrix.length);
1236         }
1237
1238         for (i = 0; i < matrix.length; ++i) {
1239             for(var j = 0; j < matrix[0].length; ++j) {
1240                 resultMatrix[j][i] = matrix[i][j];
1241             }
1242         }
1243
1244         return resultMatrix;
1245     }
1246
1247     /**
1248      * Function that transform an array of points into a coordinates array
1249      * as follows:
1250      * [x1, y1, .. , x2, y2, ..]
1251      *
1252      * @param points
1253      * @returns {Array}
1254      */
1255     function pointsToCoordArray(points) {
1256         var coodinatesArray = new Array(points.length * points[0].length);
1257         var k = 0;
1258         for(var i = 0; i < points.length; ++i) {
1259             for(var j = 0; j < points[0].length; ++j) {
1260                 coodinatesArray[k] = points[i][j];
1261                 ++k;
1262             }
1263         }
1264
1265         return coodinatesArray;
1266     }
1267
1268     /**
1269      * Apply the dot product between the smaller vector and a subsets of the
1270      * largest one.
1271      *
1272      * @param firstVector
1273      * @param secondVector
1274      * @returns {Array} each dot product of size of the difference between the
1275      *                  larger and the smallest one.
1276      */
1277     function applyDotProduct(firstVector, secondVector) {
1278         var largestVector, smallestVector;
1279         if(firstVector.length <= secondVector.length) {
1280             smallestVector = firstVector;
1281             largestVector = secondVector;
1282         } else {
1283             smallestVector = secondVector;
1284             largestVector = firstVector;
1285         }
1286
1287         var difference = largestVector.length - smallestVector.length + 1;
1288         var dotProductApplied = new Array(difference);
1289
1290         for (var i = 0; i < difference; ++i) {
1291             var sum = 0;
1292             for (var j = 0; j < smallestVector.length; ++j) {
1293                 sum += smallestVector[j] * largestVector[i + j];
1294             }
1295             dotProductApplied[i] = sum;
1296         }
1297
1298         return dotProductApplied;
1299     }
1300     /**
1301      * To scale the input array between the specified min and max values. The operation is performed inplace
1302      * if the options.inplace is specified. If only one of the min or max parameters is specified, then the scaling
1303      * will multiply the input array by min/min(input) or max/max(input)
1304      * @param input
1305      * @param options
1306      * @returns {*}
1307      */
1308     function scale(input, options){
1309         var y;
1310         if(options.inPlace){
1311             y = input;
1312         }
1313         else{
1314             y = new Array(input.length);
1315         }
1316         const max = options.max;
1317         const min = options.min;
1318         if(typeof max === "number"){
1319             if(typeof min === "number"){
1320                 var minMax = Stat.minMax(input);
1321                 var factor = (max - min)/(minMax.max-minMax.min);
1322                 for(var i=0;i< y.length;i++){
1323                     y[i]=(input[i]-minMax.min)*factor+min;
1324                 }
1325             }
1326             else{
1327                 var currentMin = Stat.max(input);
1328                 var factor = max/currentMin;
1329                 for(var i=0;i< y.length;i++){
1330                     y[i] = input[i]*factor;
1331                 }
1332             }
1333         }
1334         else{
1335             if(typeof min === "number"){
1336                 var currentMin = Stat.min(input);
1337                 var factor = min/currentMin;
1338                 for(var i=0;i< y.length;i++){
1339                     y[i] = input[i]*factor;
1340                 }
1341             }
1342         }
1343         return y;
1344     }
1345
1346     MLArrayUtilsArrayUtils.coordArrayToPoints = coordArrayToPoints;
1347     MLArrayUtilsArrayUtils.coordArrayToCoordMatrix = coordArrayToCoordMatrix;
1348     MLArrayUtilsArrayUtils.coordMatrixToCoordArray = coordMatrixToCoordArray;
1349     MLArrayUtilsArrayUtils.coordMatrixToPoints = transpose;
1350     MLArrayUtilsArrayUtils.pointsToCoordArray = pointsToCoordArray;
1351     MLArrayUtilsArrayUtils.pointsToCoordMatrix = transpose;
1352     MLArrayUtilsArrayUtils.applyDotProduct = applyDotProduct;
1353     MLArrayUtilsArrayUtils.scale = scale;
1354 }
1355
1356
1357 // ml-array-utils getEquallySpaced.js
1358 const MLArrayUtilsGetEquallySpaced = {};
1359 {
1360     /**
1361      *
1362      * Function that returns a Number array of equally spaced numberOfPoints
1363      * containing a representation of intensities of the spectra arguments x
1364      * and y.
1365      *
1366      * The options parameter contains an object in the following form:
1367      * from: starting point
1368      * to: last point
1369      * numberOfPoints: number of points between from and to
1370      * variant: "slot" or "smooth" - smooth is the default option
1371      *
1372      * The slot variant consist that each point in the new array is calculated
1373      * averaging the existing points between the slot that belongs to the current
1374      * value. The smooth variant is the same but takes the integral of the range
1375      * of the slot and divide by the step size between two points in the new array.
1376      *
1377      * @param x - sorted increasing x values
1378      * @param y
1379      * @param options
1380      * @returns {Array} new array with the equally spaced data.
1381      *
1382      */
1383     function getEquallySpacedData(x, y, options) {
1384         if (x.length>1 && x[0]>x[1]) {
1385             x=x.slice().reverse();
1386             y=y.slice().reverse();
1387         }
1388
1389         var xLength = x.length;
1390         if(xLength !== y.length)
1391             throw new RangeError("the x and y vector doesn't have the same size.");
1392
1393         if (options === undefined) options = {};
1394
1395         var from = options.from === undefined ? x[0] : options.from
1396         if (isNaN(from) || !isFinite(from)) {
1397             throw new RangeError("'From' value must be a number");
1398         }
1399         var to = options.to === undefined ? x[x.length - 1] : options.to;
1400         if (isNaN(to) || !isFinite(to)) {
1401             throw new RangeError("'To' value must be a number");
1402         }
1403
1404         var reverse = from > to;
1405         if(reverse) {
1406             var temp = from;
1407             from = to;
1408             to = temp;
1409         }
1410
1411         var numberOfPoints = options.numberOfPoints === undefined ? 100 : options.numberOfPoints;
1412         if (isNaN(numberOfPoints) || !isFinite(numberOfPoints)) {
1413             throw new RangeError("'Number of points' value must be a number");
1414         }
1415         if(numberOfPoints < 1)
1416             throw new RangeError("the number of point must be higher than 1");
1417
1418         var algorithm = options.variant === "slot" ? "slot" : "smooth"; // default value: smooth
1419
1420         var output = algorithm === "slot" ? getEquallySpacedSlot(x, y, from, to, numberOfPoints) : getEquallySpacedSmooth(x, y, from, to, numberOfPoints);
1421
1422         return reverse ? output.reverse() : output;
1423     }
1424
1425     /**
1426      * function that retrieves the getEquallySpacedData with the variant "smooth"
1427      *
1428      * @param x
1429      * @param y
1430      * @param from - Initial point
1431      * @param to - Final point
1432      * @param numberOfPoints
1433      * @returns {Array} - Array of y's equally spaced with the variant "smooth"
1434      */
1435     function getEquallySpacedSmooth(x, y, from, to, numberOfPoints) {
1436         var xLength = x.length;
1437
1438         var step = (to - from) / (numberOfPoints - 1);
1439         var halfStep = step / 2;
1440
1441         var start = from - halfStep;
1442         var output = new Array(numberOfPoints);
1443
1444         var initialOriginalStep = x[1] - x[0];
1445         var lastOriginalStep = x[x.length - 1] - x[x.length - 2];
1446
1447         // Init main variables
1448         var min = start;
1449         var max = start + step;
1450
1451         var previousX = Number.MIN_VALUE;
1452         var previousY = 0;
1453         var nextX = x[0] - initialOriginalStep;
1454         var nextY = 0;
1455
1456         var currentValue = 0;
1457         var slope = 0;
1458         var intercept = 0;
1459         var sumAtMin = 0;
1460         var sumAtMax = 0;
1461
1462         var i = 0; // index of input
1463         var j = 0; // index of output
1464
1465         function getSlope(x0, y0, x1, y1) {
1466             return (y1 - y0) / (x1 - x0);
1467         }
1468
1469         main: while(true) {
1470             while (nextX - max >= 0) {
1471                 // no overlap with original point, just consume current value
1472                 var add = integral(0, max - previousX, slope, previousY);
1473                 sumAtMax = currentValue + add;
1474
1475                 output[j] = (sumAtMax - sumAtMin) / step;
1476                 j++;
1477
1478                 if (j === numberOfPoints)
1479                     break main;
1480
1481                 min = max;
1482                 max += step;
1483                 sumAtMin = sumAtMax;
1484             }
1485
1486             if(previousX <= min && min <= nextX) {
1487                 add = integral(0, min - previousX, slope, previousY);
1488                 sumAtMin = currentValue + add;
1489             }
1490
1491             currentValue += integral(previousX, nextX, slope, intercept);
1492
1493             previousX = nextX;
1494             previousY = nextY;
1495
1496             if (i < xLength) {
1497                 nextX = x[i];
1498                 nextY = y[i];
1499                 i++;
1500             } else if (i === xLength) {
1501                 nextX += lastOriginalStep;
1502                 nextY = 0;
1503             }
1504             // updating parameters
1505             slope = getSlope(previousX, previousY, nextX, nextY);
1506             intercept = -slope*previousX + previousY;
1507         }
1508
1509         return output;
1510     }
1511
1512     /**
1513      * function that retrieves the getEquallySpacedData with the variant "slot"
1514      *
1515      * @param x
1516      * @param y
1517      * @param from - Initial point
1518      * @param to - Final point
1519      * @param numberOfPoints
1520      * @returns {Array} - Array of y's equally spaced with the variant "slot"
1521      */
1522     function getEquallySpacedSlot(x, y, from, to, numberOfPoints) {
1523         var xLength = x.length;
1524
1525         var step = (to - from) / (numberOfPoints - 1);
1526         var halfStep = step / 2;
1527         var lastStep = x[x.length - 1] - x[x.length - 2];
1528
1529         var start = from - halfStep;
1530         var output = new Array(numberOfPoints);
1531
1532         // Init main variables
1533         var min = start;
1534         var max = start + step;
1535
1536         var previousX = -Number.MAX_VALUE;
1537         var previousY = 0;
1538         var nextX = x[0];
1539         var nextY = y[0];
1540         var frontOutsideSpectra = 0;
1541         var backOutsideSpectra = true;
1542
1543         var currentValue = 0;
1544
1545         // for slot algorithm
1546         var currentPoints = 0;
1547
1548         var i = 1; // index of input
1549         var j = 0; // index of output
1550
1551         main: while(true) {
1552             if (previousX>=nextX) throw (new Error('x must be an increasing serie'));
1553             while (previousX - max > 0) {
1554                 // no overlap with original point, just consume current value
1555                 if(backOutsideSpectra) {
1556                     currentPoints++;
1557                     backOutsideSpectra = false;
1558                 }
1559
1560                 output[j] = currentPoints <= 0 ? 0 : currentValue / currentPoints;
1561                 j++;
1562
1563                 if (j === numberOfPoints)
1564                     break main;
1565
1566                 min = max;
1567                 max += step;
1568                 currentValue = 0;
1569                 currentPoints = 0;
1570             }
1571
1572             if(previousX > min) {
1573                 currentValue += previousY;
1574                 currentPoints++;
1575             }
1576
1577             if(previousX === -Number.MAX_VALUE || frontOutsideSpectra > 1)
1578                 currentPoints--;
1579
1580             previousX = nextX;
1581             previousY = nextY;
1582
1583             if (i < xLength) {
1584                 nextX = x[i];
1585                 nextY = y[i];
1586                 i++;
1587             } else {
1588                 nextX += lastStep;
1589                 nextY = 0;
1590                 frontOutsideSpectra++;
1591             }
1592         }
1593
1594         return output;
1595     }
1596     /**
1597      * Function that calculates the integral of the line between two
1598      * x-coordinates, given the slope and intercept of the line.
1599      *
1600      * @param x0
1601      * @param x1
1602      * @param slope
1603      * @param intercept
1604      * @returns {number} integral value.
1605      */
1606     function integral(x0, x1, slope, intercept) {
1607         return (0.5 * slope * x1 * x1 + intercept * x1) - (0.5 * slope * x0 * x0 + intercept * x0);
1608     }
1609
1610     MLArrayUtilsGetEquallySpaced.getEquallySpacedData = getEquallySpacedData;
1611     MLArrayUtilsGetEquallySpaced.integral = integral;
1612 }
1613
1614
1615 // ml-array-utils snv.js
1616 const MLArrayUtilsSNV = {};
1617 {
1618     MLArrayUtilsSNV.SNV = SNV;
1619     let Stat = MLStat.array;
1620
1621     /**
1622      * Function that applies the standard normal variate (SNV) to an array of values.
1623      *
1624      * @param data - Array of values.
1625      * @returns {Array} - applied the SNV.
1626      */
1627     function SNV(data) {
1628         var mean = Stat.mean(data);
1629         var std = Stat.standardDeviation(data);
1630         var result = data.slice();
1631         for (var i = 0; i < data.length; i++) {
1632             result[i] = (result[i] - mean) / std;
1633         }
1634         return result;
1635     }
1636 }
1637
1638 // ml-array-utils index.js
1639 const MLArrayUtils = {};
1640 {
1641     MLArrayUtils.getEquallySpacedData = MLArrayUtilsGetEquallySpaced.getEquallySpacedData;
1642     MLArrayUtils.SNV = MLArrayUtilsSNV.SNV;
1643 }
1644
1645
1646
1647 // do this early so things can use it. This is from ml-matrix src/matrix.js
1648 const MLMatrixMatrix = {};
1649
1650 // ml-matrix src/util.js
1651 const MLMatrixUtil = {};
1652 {
1653     let exports = MLMatrixUtil;
1654     let Matrix = MLMatrixMatrix;
1655
1656     /**
1657      * @private
1658      * Check that a row index is not out of bounds
1659      * @param {Matrix} matrix
1660      * @param {number} index
1661      * @param {boolean} [outer]
1662      */
1663     exports.checkRowIndex = function checkRowIndex(matrix, index, outer) {
1664         var max = outer ? matrix.rows : matrix.rows - 1;
1665         if (index < 0 || index > max) {
1666             throw new RangeError('Row index out of range');
1667         }
1668     };
1669
1670     /**
1671      * @private
1672      * Check that a column index is not out of bounds
1673      * @param {Matrix} matrix
1674      * @param {number} index
1675      * @param {boolean} [outer]
1676      */
1677     exports.checkColumnIndex = function checkColumnIndex(matrix, index, outer) {
1678         var max = outer ? matrix.columns : matrix.columns - 1;
1679         if (index < 0 || index > max) {
1680             throw new RangeError('Column index out of range');
1681         }
1682     };
1683
1684     /**
1685      * @private
1686      * Check that the provided vector is an array with the right length
1687      * @param {Matrix} matrix
1688      * @param {Array|Matrix} vector
1689      * @return {Array}
1690      * @throws {RangeError}
1691      */
1692     exports.checkRowVector = function checkRowVector(matrix, vector) {
1693         if (vector.to1DArray) {
1694             vector = vector.to1DArray();
1695         }
1696         if (vector.length !== matrix.columns) {
1697             throw new RangeError('vector size must be the same as the number of columns');
1698         }
1699         return vector;
1700     };
1701
1702     /**
1703      * @private
1704      * Check that the provided vector is an array with the right length
1705      * @param {Matrix} matrix
1706      * @param {Array|Matrix} vector
1707      * @return {Array}
1708      * @throws {RangeError}
1709      */
1710     exports.checkColumnVector = function checkColumnVector(matrix, vector) {
1711         if (vector.to1DArray) {
1712             vector = vector.to1DArray();
1713         }
1714         if (vector.length !== matrix.rows) {
1715             throw new RangeError('vector size must be the same as the number of rows');
1716         }
1717         return vector;
1718     };
1719
1720     exports.checkIndices = function checkIndices(matrix, rowIndices, columnIndices) {
1721         var rowOut = rowIndices.some(r => {
1722             return r < 0 || r >= matrix.rows;
1723
1724         });
1725
1726         var columnOut = columnIndices.some(c => {
1727             return c < 0 || c >= matrix.columns;
1728         });
1729
1730         if (rowOut || columnOut) {
1731             throw new RangeError('Indices are out of range');
1732         }
1733
1734         if (typeof rowIndices !== 'object' || typeof columnIndices !== 'object') {
1735             throw new TypeError('Unexpected type for row/column indices');
1736         }
1737         if (!Array.isArray(rowIndices)) rowIndices = Array.from(rowIndices);
1738         if (!Array.isArray(columnIndices)) rowIndices = Array.from(columnIndices);
1739
1740         return {
1741             row: rowIndices,
1742             column: columnIndices
1743         };
1744     };
1745
1746     exports.checkRange = function checkRange(matrix, startRow, endRow, startColumn, endColumn) {
1747         if (arguments.length !== 5) throw new TypeError('Invalid argument type');
1748         var notAllNumbers = Array.from(arguments).slice(1).some(function (arg) {
1749             return typeof arg !== 'number';
1750         });
1751         if (notAllNumbers) throw new TypeError('Invalid argument type');
1752         if (startRow > endRow || startColumn > endColumn || startRow < 0 || startRow >= matrix.rows || endRow < 0 || endRow >= matrix.rows || startColumn < 0 || startColumn >= matrix.columns || endColumn < 0 || endColumn >= matrix.columns) {
1753             throw new RangeError('Submatrix indices are out of range');
1754         }
1755     };
1756
1757     exports.getRange = function getRange(from, to) {
1758         var arr = new Array(to - from + 1);
1759         for (var i = 0; i < arr.length; i++) {
1760             arr[i] = from + i;
1761         }
1762         return arr;
1763     };
1764
1765     exports.sumByRow = function sumByRow(matrix) {
1766         var sum = Matrix.Matrix.zeros(matrix.rows, 1);
1767         for (var i = 0; i < matrix.rows; ++i) {
1768             for (var j = 0; j < matrix.columns; ++j) {
1769                 sum.set(i, 0, sum.get(i, 0) + matrix.get(i, j));
1770             }
1771         }
1772         return sum;
1773     };
1774
1775     exports.sumByColumn = function sumByColumn(matrix) {
1776         var sum = Matrix.Matrix.zeros(1, matrix.columns);
1777         for (var i = 0; i < matrix.rows; ++i) {
1778             for (var j = 0; j < matrix.columns; ++j) {
1779                 sum.set(0, j, sum.get(0, j) + matrix.get(i, j));
1780             }
1781         }
1782         return sum;
1783     };
1784
1785     exports.sumAll = function sumAll(matrix) {
1786         var v = 0;
1787         for (var i = 0; i < matrix.rows; i++) {
1788             for (var j = 0; j < matrix.columns; j++) {
1789                 v += matrix.get(i, j);
1790             }
1791         }
1792         return v;
1793     };
1794 }
1795
1796 // ml-matrix symbolsspecies.js
1797 if (!Symbol.species) {
1798     Symbol.species = Symbol.for('@@species');
1799 }
1800
1801
1802 // ml-matrix src/dc/util.js
1803 const MLMatrixDCUtil = {};
1804 {
1805     let exports = MLMatrixDCUtil;
1806     exports.hypotenuse = function hypotenuse(a, b) {
1807         var r;
1808         if (Math.abs(a) > Math.abs(b)) {
1809             r = b / a;
1810             return Math.abs(a) * Math.sqrt(1 + r * r);
1811         }
1812         if (b !== 0) {
1813             r = a / b;
1814             return Math.abs(b) * Math.sqrt(1 + r * r);
1815         }
1816         return 0;
1817     };
1818
1819     // For use in the decomposition algorithms. With big matrices, access time is
1820     // too long on elements from array subclass
1821     // todo check when it is fixed in v8
1822     // http://jsperf.com/access-and-write-array-subclass
1823     exports.getEmpty2DArray = function (rows, columns) {
1824         var array = new Array(rows);
1825         for (var i = 0; i < rows; i++) {
1826             array[i] = new Array(columns);
1827         }
1828         return array;
1829     };
1830
1831     exports.getFilled2DArray = function (rows, columns, value) {
1832         var array = new Array(rows);
1833         for (var i = 0; i < rows; i++) {
1834             array[i] = new Array(columns);
1835             for (var j = 0; j < columns; j++) {
1836                 array[i][j] = value;
1837             }
1838         }
1839         return array;
1840     };
1841 }
1842
1843 // ml-matrix src/dc/lu.js
1844 let MLMatrixDCLU = {};
1845 {
1846     let Matrix = MLMatrixMatrix;
1847
1848     // https://github.com/lutzroeder/Mapack/blob/master/Source/LuDecomposition.cs
1849     function LuDecomposition(matrix) {
1850         if (!(this instanceof LuDecomposition)) {
1851             return new LuDecomposition(matrix);
1852         }
1853
1854         matrix = Matrix.Matrix.checkMatrix(matrix);
1855
1856         var lu = matrix.clone(),
1857             rows = lu.rows,
1858             columns = lu.columns,
1859             pivotVector = new Array(rows),
1860             pivotSign = 1,
1861             i, j, k, p, s, t, v,
1862             LUrowi, LUcolj, kmax;
1863
1864         for (i = 0; i < rows; i++) {
1865             pivotVector[i] = i;
1866         }
1867
1868         LUcolj = new Array(rows);
1869
1870         for (j = 0; j < columns; j++) {
1871
1872             for (i = 0; i < rows; i++) {
1873                 LUcolj[i] = lu[i][j];
1874             }
1875
1876             for (i = 0; i < rows; i++) {
1877                 LUrowi = lu[i];
1878                 kmax = Math.min(i, j);
1879                 s = 0;
1880                 for (k = 0; k < kmax; k++) {
1881                     s += LUrowi[k] * LUcolj[k];
1882                 }
1883                 LUrowi[j] = LUcolj[i] -= s;
1884             }
1885
1886             p = j;
1887             for (i = j + 1; i < rows; i++) {
1888                 if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) {
1889                     p = i;
1890                 }
1891             }
1892
1893             if (p !== j) {
1894                 for (k = 0; k < columns; k++) {
1895                     t = lu[p][k];
1896                     lu[p][k] = lu[j][k];
1897                     lu[j][k] = t;
1898                 }
1899
1900                 v = pivotVector[p];
1901                 pivotVector[p] = pivotVector[j];
1902                 pivotVector[j] = v;
1903
1904                 pivotSign = -pivotSign;
1905             }
1906
1907             if (j < rows && lu[j][j] !== 0) {
1908                 for (i = j + 1; i < rows; i++) {
1909                     lu[i][j] /= lu[j][j];
1910                 }
1911             }
1912         }
1913
1914         this.LU = lu;
1915         this.pivotVector = pivotVector;
1916         this.pivotSign = pivotSign;
1917     }
1918
1919     LuDecomposition.prototype = {
1920         isSingular: function () {
1921             var data = this.LU,
1922                 col = data.columns;
1923             for (var j = 0; j < col; j++) {
1924                 if (data[j][j] === 0) {
1925                     return true;
1926                 }
1927             }
1928             return false;
1929         },
1930         get determinant() {
1931             var data = this.LU;
1932             if (!data.isSquare()) {
1933                 throw new Error('Matrix must be square');
1934             }
1935             var determinant = this.pivotSign, col = data.columns;
1936             for (var j = 0; j < col; j++) {
1937                 determinant *= data[j][j];
1938             }
1939             return determinant;
1940         },
1941         get lowerTriangularMatrix() {
1942             var data = this.LU,
1943                 rows = data.rows,
1944                 columns = data.columns,
1945                 X = new Matrix.Matrix(rows, columns);
1946             for (var i = 0; i < rows; i++) {
1947                 for (var j = 0; j < columns; j++) {
1948                     if (i > j) {
1949                         X[i][j] = data[i][j];
1950                     } else if (i === j) {
1951                         X[i][j] = 1;
1952                     } else {
1953                         X[i][j] = 0;
1954                     }
1955                 }
1956             }
1957             return X;
1958         },
1959         get upperTriangularMatrix() {
1960             var data = this.LU,
1961                 rows = data.rows,
1962                 columns = data.columns,
1963                 X = new Matrix.Matrix(rows, columns);
1964             for (var i = 0; i < rows; i++) {
1965                 for (var j = 0; j < columns; j++) {
1966                     if (i <= j) {
1967                         X[i][j] = data[i][j];
1968                     } else {
1969                         X[i][j] = 0;
1970                     }
1971                 }
1972             }
1973             return X;
1974         },
1975         get pivotPermutationVector() {
1976             return this.pivotVector.slice();
1977         },
1978         solve: function (value) {
1979             value = Matrix.Matrix.checkMatrix(value);
1980
1981             var lu = this.LU,
1982                 rows = lu.rows;
1983
1984             if (rows !== value.rows) {
1985                 throw new Error('Invalid matrix dimensions');
1986             }
1987             if (this.isSingular()) {
1988                 throw new Error('LU matrix is singular');
1989             }
1990
1991             var count = value.columns;
1992             var X = value.subMatrixRow(this.pivotVector, 0, count - 1);
1993             var columns = lu.columns;
1994             var i, j, k;
1995
1996             for (k = 0; k < columns; k++) {
1997                 for (i = k + 1; i < columns; i++) {
1998                     for (j = 0; j < count; j++) {
1999                         X[i][j] -= X[k][j] * lu[i][k];
2000                     }
2001                 }
2002             }
2003             for (k = columns - 1; k >= 0; k--) {
2004                 for (j = 0; j < count; j++) {
2005                     X[k][j] /= lu[k][k];
2006                 }
2007                 for (i = 0; i < k; i++) {
2008                     for (j = 0; j < count; j++) {
2009                         X[i][j] -= X[k][j] * lu[i][k];
2010                     }
2011                 }
2012             }
2013             return X;
2014         }
2015     };
2016
2017     MLMatrixDCLU = LuDecomposition;
2018 }
2019
2020
2021 // ml-matrix src/dc/svd.js
2022 let MLMatrixDCSVD = {};
2023 {
2024     let Matrix = MLMatrixMatrix;
2025     let util = MLMatrixDCUtil;
2026     let hypotenuse = util.hypotenuse;
2027     let getFilled2DArray = util.getFilled2DArray;
2028
2029     // https://github.com/lutzroeder/Mapack/blob/master/Source/SingularValueDecomposition.cs
2030     function SingularValueDecomposition(value, options) {
2031         if (!(this instanceof SingularValueDecomposition)) {
2032             return new SingularValueDecomposition(value, options);
2033         }
2034         value = Matrix.Matrix.checkMatrix(value);
2035
2036         options = options || {};
2037
2038         var m = value.rows,
2039             n = value.columns,
2040             nu = Math.min(m, n);
2041
2042         var wantu = true, wantv = true;
2043         if (options.computeLeftSingularVectors === false) wantu = false;
2044         if (options.computeRightSingularVectors === false) wantv = false;
2045         var autoTranspose = options.autoTranspose === true;
2046
2047         var swapped = false;
2048         var a;
2049         if (m < n) {
2050             if (!autoTranspose) {
2051                 a = value.clone();
2052                 // eslint-disable-next-line no-console
2053                 console.warn('Computing SVD on a matrix with more columns than rows. Consider enabling autoTranspose');
2054             } else {
2055                 a = value.transpose();
2056                 m = a.rows;
2057                 n = a.columns;
2058                 swapped = true;
2059                 var aux = wantu;
2060                 wantu = wantv;
2061                 wantv = aux;
2062             }
2063         } else {
2064             a = value.clone();
2065         }
2066
2067         var s = new Array(Math.min(m + 1, n)),
2068             U = getFilled2DArray(m, nu, 0),
2069             V = getFilled2DArray(n, n, 0),
2070             e = new Array(n),
2071             work = new Array(m);
2072
2073         var nct = Math.min(m - 1, n);
2074         var nrt = Math.max(0, Math.min(n - 2, m));
2075
2076         var i, j, k, p, t, ks, f, cs, sn, max, kase,
2077             scale, sp, spm1, epm1, sk, ek, b, c, shift, g;
2078
2079         for (k = 0, max = Math.max(nct, nrt); k < max; k++) {
2080             if (k < nct) {
2081                 s[k] = 0;
2082                 for (i = k; i < m; i++) {
2083                     s[k] = hypotenuse(s[k], a[i][k]);
2084                 }
2085                 if (s[k] !== 0) {
2086                     if (a[k][k] < 0) {
2087                         s[k] = -s[k];
2088                     }
2089                     for (i = k; i < m; i++) {
2090                         a[i][k] /= s[k];
2091                     }
2092                     a[k][k] += 1;
2093                 }
2094                 s[k] = -s[k];
2095             }
2096
2097             for (j = k + 1; j < n; j++) {
2098                 if ((k < nct) && (s[k] !== 0)) {
2099                     t = 0;
2100                     for (i = k; i < m; i++) {
2101                         t += a[i][k] * a[i][j];
2102                     }
2103                     t = -t / a[k][k];
2104                     for (i = k; i < m; i++) {
2105                         a[i][j] += t * a[i][k];
2106                     }
2107                 }
2108                 e[j] = a[k][j];
2109             }
2110
2111             if (wantu && (k < nct)) {
2112                 for (i = k; i < m; i++) {
2113                     U[i][k] = a[i][k];
2114                 }
2115             }
2116
2117             if (k < nrt) {
2118                 e[k] = 0;
2119                 for (i = k + 1; i < n; i++) {
2120                     e[k] = hypotenuse(e[k], e[i]);
2121                 }
2122                 if (e[k] !== 0) {
2123                     if (e[k + 1] < 0) {
2124                         e[k] = 0 - e[k];
2125                     }
2126                     for (i = k + 1; i < n; i++) {
2127                         e[i] /= e[k];
2128                     }
2129                     e[k + 1] += 1;
2130                 }
2131                 e[k] = -e[k];
2132                 if ((k + 1 < m) && (e[k] !== 0)) {
2133                     for (i = k + 1; i < m; i++) {
2134                         work[i] = 0;
2135                     }
2136                     for (j = k + 1; j < n; j++) {
2137                         for (i = k + 1; i < m; i++) {
2138                             work[i] += e[j] * a[i][j];
2139                         }
2140                     }
2141                     for (j = k + 1; j < n; j++) {
2142                         t = -e[j] / e[k + 1];
2143                         for (i = k + 1; i < m; i++) {
2144                             a[i][j] += t * work[i];
2145                         }
2146                     }
2147                 }
2148                 if (wantv) {
2149                     for (i = k + 1; i < n; i++) {
2150                         V[i][k] = e[i];
2151                     }
2152                 }
2153             }
2154         }
2155
2156         p = Math.min(n, m + 1);
2157         if (nct < n) {
2158             s[nct] = a[nct][nct];
2159         }
2160         if (m < p) {
2161             s[p - 1] = 0;
2162         }
2163         if (nrt + 1 < p) {
2164             e[nrt] = a[nrt][p - 1];
2165         }
2166         e[p - 1] = 0;
2167
2168         if (wantu) {
2169             for (j = nct; j < nu; j++) {
2170                 for (i = 0; i < m; i++) {
2171                     U[i][j] = 0;
2172                 }
2173                 U[j][j] = 1;
2174             }
2175             for (k = nct - 1; k >= 0; k--) {
2176                 if (s[k] !== 0) {
2177                     for (j = k + 1; j < nu; j++) {
2178                         t = 0;
2179                         for (i = k; i < m; i++) {
2180                             t += U[i][k] * U[i][j];
2181                         }
2182                         t = -t / U[k][k];
2183                         for (i = k; i < m; i++) {
2184                             U[i][j] += t * U[i][k];
2185                         }
2186                     }
2187                     for (i = k; i < m; i++) {
2188                         U[i][k] = -U[i][k];
2189                     }
2190                     U[k][k] = 1 + U[k][k];
2191                     for (i = 0; i < k - 1; i++) {
2192                         U[i][k] = 0;
2193                     }
2194                 } else {
2195                     for (i = 0; i < m; i++) {
2196                         U[i][k] = 0;
2197                     }
2198                     U[k][k] = 1;
2199                 }
2200             }
2201         }
2202
2203         if (wantv) {
2204             for (k = n - 1; k >= 0; k--) {
2205                 if ((k < nrt) && (e[k] !== 0)) {
2206                     for (j = k + 1; j < n; j++) {
2207                         t = 0;
2208                         for (i = k + 1; i < n; i++) {
2209                             t += V[i][k] * V[i][j];
2210                         }
2211                         t = -t / V[k + 1][k];
2212                         for (i = k + 1; i < n; i++) {
2213                             V[i][j] += t * V[i][k];
2214                         }
2215                     }
2216                 }
2217                 for (i = 0; i < n; i++) {
2218                     V[i][k] = 0;
2219                 }
2220                 V[k][k] = 1;
2221             }
2222         }
2223
2224         var pp = p - 1,
2225             iter = 0,
2226             eps = Math.pow(2, -52);
2227         while (p > 0) {
2228             for (k = p - 2; k >= -1; k--) {
2229                 if (k === -1) {
2230                     break;
2231                 }
2232                 if (Math.abs(e[k]) <= eps * (Math.abs(s[k]) + Math.abs(s[k + 1]))) {
2233                     e[k] = 0;
2234                     break;
2235                 }
2236             }
2237             if (k === p - 2) {
2238                 kase = 4;
2239             } else {
2240                 for (ks = p - 1; ks >= k; ks--) {
2241                     if (ks === k) {
2242                         break;
2243                     }
2244                     t = (ks !== p ? Math.abs(e[ks]) : 0) + (ks !== k + 1 ? Math.abs(e[ks - 1]) : 0);
2245                     if (Math.abs(s[ks]) <= eps * t) {
2246                         s[ks] = 0;
2247                         break;
2248                     }
2249                 }
2250                 if (ks === k) {
2251                     kase = 3;
2252                 } else if (ks === p - 1) {
2253                     kase = 1;
2254                 } else {
2255                     kase = 2;
2256                     k = ks;
2257                 }
2258             }
2259
2260             k++;
2261
2262             switch (kase) {
2263                 case 1: {
2264                     f = e[p - 2];
2265                     e[p - 2] = 0;
2266                     for (j = p - 2; j >= k; j--) {
2267                         t = hypotenuse(s[j], f);
2268                         cs = s[j] / t;
2269                         sn = f / t;
2270                         s[j] = t;
2271                         if (j !== k) {
2272                             f = -sn * e[j - 1];
2273                             e[j - 1] = cs * e[j - 1];
2274                         }
2275                         if (wantv) {
2276                             for (i = 0; i < n; i++) {
2277                                 t = cs * V[i][j] + sn * V[i][p - 1];
2278                                 V[i][p - 1] = -sn * V[i][j] + cs * V[i][p - 1];
2279                                 V[i][j] = t;
2280                             }
2281                         }
2282                     }
2283                     break;
2284                 }
2285                 case 2 : {
2286                     f = e[k - 1];
2287                     e[k - 1] = 0;
2288                     for (j = k; j < p; j++) {
2289                         t = hypotenuse(s[j], f);
2290                         cs = s[j] / t;
2291                         sn = f / t;
2292                         s[j] = t;
2293                         f = -sn * e[j];
2294                         e[j] = cs * e[j];
2295                         if (wantu) {
2296                             for (i = 0; i < m; i++) {
2297                                 t = cs * U[i][j] + sn * U[i][k - 1];
2298                                 U[i][k - 1] = -sn * U[i][j] + cs * U[i][k - 1];
2299                                 U[i][j] = t;
2300                             }
2301                         }
2302                     }
2303                     break;
2304                 }
2305                 case 3 : {
2306                     scale = Math.max(Math.max(Math.max(Math.max(Math.abs(s[p - 1]), Math.abs(s[p - 2])), Math.abs(e[p - 2])), Math.abs(s[k])), Math.abs(e[k]));
2307                     sp = s[p - 1] / scale;
2308                     spm1 = s[p - 2] / scale;
2309                     epm1 = e[p - 2] / scale;
2310                     sk = s[k] / scale;
2311                     ek = e[k] / scale;
2312                     b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2;
2313                     c = (sp * epm1) * (sp * epm1);
2314                     shift = 0;
2315                     if ((b !== 0) || (c !== 0)) {
2316                         shift = Math.sqrt(b * b + c);
2317                         if (b < 0) {
2318                             shift = -shift;
2319                         }
2320                         shift = c / (b + shift);
2321                     }
2322                     f = (sk + sp) * (sk - sp) + shift;
2323                     g = sk * ek;
2324                     for (j = k; j < p - 1; j++) {
2325                         t = hypotenuse(f, g);
2326                         cs = f / t;
2327                         sn = g / t;
2328                         if (j !== k) {
2329                             e[j - 1] = t;
2330                         }
2331                         f = cs * s[j] + sn * e[j];
2332                         e[j] = cs * e[j] - sn * s[j];
2333                         g = sn * s[j + 1];
2334                         s[j + 1] = cs * s[j + 1];
2335                         if (wantv) {
2336                             for (i = 0; i < n; i++) {
2337                                 t = cs * V[i][j] + sn * V[i][j + 1];
2338                                 V[i][j + 1] = -sn * V[i][j] + cs * V[i][j + 1];
2339                                 V[i][j] = t;
2340                             }
2341                         }
2342                         t = hypotenuse(f, g);
2343                         cs = f / t;
2344                         sn = g / t;
2345                         s[j] = t;
2346                         f = cs * e[j] + sn * s[j + 1];
2347                         s[j + 1] = -sn * e[j] + cs * s[j + 1];
2348                         g = sn * e[j + 1];
2349                         e[j + 1] = cs * e[j + 1];
2350                         if (wantu && (j < m - 1)) {
2351                             for (i = 0; i < m; i++) {
2352                                 t = cs * U[i][j] + sn * U[i][j + 1];
2353                                 U[i][j + 1] = -sn * U[i][j] + cs * U[i][j + 1];
2354                                 U[i][j] = t;
2355                             }
2356                         }
2357                     }
2358                     e[p - 2] = f;
2359                     iter = iter + 1;
2360                     break;
2361                 }
2362                 case 4: {
2363                     if (s[k] <= 0) {
2364                         s[k] = (s[k] < 0 ? -s[k] : 0);
2365                         if (wantv) {
2366                             for (i = 0; i <= pp; i++) {
2367                                 V[i][k] = -V[i][k];
2368                             }
2369                         }
2370                     }
2371                     while (k < pp) {
2372                         if (s[k] >= s[k + 1]) {
2373                             break;
2374                         }
2375                         t = s[k];
2376                         s[k] = s[k + 1];
2377                         s[k + 1] = t;
2378                         if (wantv && (k < n - 1)) {
2379                             for (i = 0; i < n; i++) {
2380                                 t = V[i][k + 1];
2381                                 V[i][k + 1] = V[i][k];
2382                                 V[i][k] = t;
2383                             }
2384                         }
2385                         if (wantu && (k < m - 1)) {
2386                             for (i = 0; i < m; i++) {
2387                                 t = U[i][k + 1];
2388                                 U[i][k + 1] = U[i][k];
2389                                 U[i][k] = t;
2390                             }
2391                         }
2392                         k++;
2393                     }
2394                     iter = 0;
2395                     p--;
2396                     break;
2397                 }
2398                 // no default
2399             }
2400         }
2401
2402         if (swapped) {
2403             var tmp = V;
2404             V = U;
2405             U = tmp;
2406         }
2407
2408         this.m = m;
2409         this.n = n;
2410         this.s = s;
2411         this.U = U;
2412         this.V = V;
2413     }
2414
2415     SingularValueDecomposition.prototype = {
2416         get condition() {
2417             return this.s[0] / this.s[Math.min(this.m, this.n) - 1];
2418         },
2419         get norm2() {
2420             return this.s[0];
2421         },
2422         get rank() {
2423             var eps = Math.pow(2, -52),
2424                 tol = Math.max(this.m, this.n) * this.s[0] * eps,
2425                 r = 0,
2426                 s = this.s;
2427             for (var i = 0, ii = s.length; i < ii; i++) {
2428                 if (s[i] > tol) {
2429                     r++;
2430                 }
2431             }
2432             return r;
2433         },
2434         get diagonal() {
2435             return this.s;
2436         },
2437         // https://github.com/accord-net/framework/blob/development/Sources/Accord.Math/Decompositions/SingularValueDecomposition.cs
2438         get threshold() {
2439             return (Math.pow(2, -52) / 2) * Math.max(this.m, this.n) * this.s[0];
2440         },
2441         get leftSingularVectors() {
2442             if (!Matrix.Matrix.isMatrix(this.U)) {
2443                 this.U = new Matrix.Matrix(this.U);
2444             }
2445             return this.U;
2446         },
2447         get rightSingularVectors() {
2448             if (!Matrix.Matrix.isMatrix(this.V)) {
2449                 this.V = new Matrix.Matrix(this.V);
2450             }
2451             return this.V;
2452         },
2453         get diagonalMatrix() {
2454             return Matrix.Matrix.diag(this.s);
2455         },
2456         solve: function (value) {
2457
2458             var Y = value,
2459                 e = this.threshold,
2460                 scols = this.s.length,
2461                 Ls = Matrix.Matrix.zeros(scols, scols),
2462                 i;
2463
2464             for (i = 0; i < scols; i++) {
2465                 if (Math.abs(this.s[i]) <= e) {
2466                     Ls[i][i] = 0;
2467                 } else {
2468                     Ls[i][i] = 1 / this.s[i];
2469                 }
2470             }
2471
2472             var U = this.U;
2473             var V = this.rightSingularVectors;
2474
2475             var VL = V.mmul(Ls),
2476                 vrows = V.rows,
2477                 urows = U.length,
2478                 VLU = Matrix.Matrix.zeros(vrows, urows),
2479                 j, k, sum;
2480
2481             for (i = 0; i < vrows; i++) {
2482                 for (j = 0; j < urows; j++) {
2483                     sum = 0;
2484                     for (k = 0; k < scols; k++) {
2485                         sum += VL[i][k] * U[j][k];
2486                     }
2487                     VLU[i][j] = sum;
2488                 }
2489             }
2490
2491             return VLU.mmul(Y);
2492         },
2493         solveForDiagonal: function (value) {
2494             return this.solve(Matrix.Matrix.diag(value));
2495         },
2496         inverse: function () {
2497             var V = this.V;
2498             var e = this.threshold,
2499                 vrows = V.length,
2500                 vcols = V[0].length,
2501                 X = new Matrix.Matrix(vrows, this.s.length),
2502                 i, j;
2503
2504             for (i = 0; i < vrows; i++) {
2505                 for (j = 0; j < vcols; j++) {
2506                     if (Math.abs(this.s[j]) > e) {
2507                         X[i][j] = V[i][j] / this.s[j];
2508                     } else {
2509                         X[i][j] = 0;
2510                     }
2511                 }
2512             }
2513
2514             var U = this.U;
2515
2516             var urows = U.length,
2517                 ucols = U[0].length,
2518                 Y = new Matrix.Matrix(vrows, urows),
2519                 k, sum;
2520
2521             for (i = 0; i < vrows; i++) {
2522                 for (j = 0; j < urows; j++) {
2523                     sum = 0;
2524                     for (k = 0; k < ucols; k++) {
2525                         sum += X[i][k] * U[j][k];
2526                     }
2527                     Y[i][j] = sum;
2528                 }
2529             }
2530
2531             return Y;
2532         }
2533     };
2534
2535     MLMatrixDCSVD = SingularValueDecomposition;
2536 }
2537
2538 // ml-matrix src/abstractMatrix.js
2539 let MLMatrixAbstractMatrix;
2540 {
2541     let LuDecomposition = MLMatrixDCLU;
2542     let SvDecomposition = MLMatrixDCSVD;
2543     let arrayUtils = MLArrayUtils;
2544     let util = MLMatrixUtil;
2545
2546     MLMatrixAbstractMatrix = function abstractMatrix(superCtor) {
2547         if (superCtor === undefined) superCtor = Object;
2548
2549         /**
2550          * Real matrix
2551          * @class Matrix
2552          * @param {number|Array|Matrix} nRows - Number of rows of the new matrix,
2553          * 2D array containing the data or Matrix instance to clone
2554          * @param {number} [nColumns] - Number of columns of the new matrix
2555          */
2556         class Matrix extends superCtor {
2557             static get [Symbol.species]() {
2558                 return this;
2559             }
2560
2561             /**
2562              * Constructs a Matrix with the chosen dimensions from a 1D array
2563              * @param {number} newRows - Number of rows
2564              * @param {number} newColumns - Number of columns
2565              * @param {Array} newData - A 1D array containing data for the matrix
2566              * @return {Matrix} - The new matrix
2567              */
2568             static from1DArray(newRows, newColumns, newData) {
2569                 var length = newRows * newColumns;
2570                 if (length !== newData.length) {
2571                     throw new RangeError('Data length does not match given dimensions');
2572                 }
2573                 var newMatrix = new this(newRows, newColumns);
2574                 for (var row = 0; row < newRows; row++) {
2575                     for (var column = 0; column < newColumns; column++) {
2576                         newMatrix.set(row, column, newData[row * newColumns + column]);
2577                     }
2578                 }
2579                 return newMatrix;
2580             }
2581
2582             /**
2583              * Creates a row vector, a matrix with only one row.
2584              * @param {Array} newData - A 1D array containing data for the vector
2585              * @return {Matrix} - The new matrix
2586              */
2587             static rowVector(newData) {
2588                 var vector = new this(1, newData.length);
2589                 for (var i = 0; i < newData.length; i++) {
2590                     vector.set(0, i, newData[i]);
2591                 }
2592                 return vector;
2593             }
2594
2595             /**
2596              * Creates a column vector, a matrix with only one column.
2597              * @param {Array} newData - A 1D array containing data for the vector
2598              * @return {Matrix} - The new matrix
2599              */
2600             static columnVector(newData) {
2601                 var vector = new this(newData.length, 1);
2602                 for (var i = 0; i < newData.length; i++) {
2603                     vector.set(i, 0, newData[i]);
2604                 }
2605                 return vector;
2606             }
2607
2608             /**
2609              * Creates an empty matrix with the given dimensions. Values will be undefined. Same as using new Matrix(rows, columns).
2610              * @param {number} rows - Number of rows
2611              * @param {number} columns - Number of columns
2612              * @return {Matrix} - The new matrix
2613              */
2614             static empty(rows, columns) {
2615                 return new this(rows, columns);
2616             }
2617
2618             /**
2619              * Creates a matrix with the given dimensions. Values will be set to zero.
2620              * @param {number} rows - Number of rows
2621              * @param {number} columns - Number of columns
2622              * @return {Matrix} - The new matrix
2623              */
2624             static zeros(rows, columns) {
2625                 return this.empty(rows, columns).fill(0);
2626             }
2627
2628             /**
2629              * Creates a matrix with the given dimensions. Values will be set to one.
2630              * @param {number} rows - Number of rows
2631              * @param {number} columns - Number of columns
2632              * @return {Matrix} - The new matrix
2633              */
2634             static ones(rows, columns) {
2635                 return this.empty(rows, columns).fill(1);
2636             }
2637
2638             /**
2639              * Creates a matrix with the given dimensions. Values will be randomly set.
2640              * @param {number} rows - Number of rows
2641              * @param {number} columns - Number of columns
2642              * @param {function} [rng=Math.random] - Random number generator
2643              * @return {Matrix} The new matrix
2644              */
2645             static rand(rows, columns, rng) {
2646                 if (rng === undefined) rng = Math.random;
2647                 var matrix = this.empty(rows, columns);
2648                 for (var i = 0; i < rows; i++) {
2649                     for (var j = 0; j < columns; j++) {
2650                         matrix.set(i, j, rng());
2651                     }
2652                 }
2653                 return matrix;
2654             }
2655
2656             /**
2657              * Creates a matrix with the given dimensions. Values will be random integers.
2658              * @param {number} rows - Number of rows
2659              * @param {number} columns - Number of columns
2660              * @param {number} [maxValue=1000] - Maximum value
2661              * @param {function} [rng=Math.random] - Random number generator
2662              * @return {Matrix} The new matrix
2663              */
2664             static randInt(rows, columns, maxValue, rng) {
2665                 if (maxValue === undefined) maxValue = 1000;
2666                 if (rng === undefined) rng = Math.random;
2667                 var matrix = this.empty(rows, columns);
2668                 for (var i = 0; i < rows; i++) {
2669                     for (var j = 0; j < columns; j++) {
2670                         var value = Math.floor(rng() * maxValue);
2671                         matrix.set(i, j, value);
2672                     }
2673                 }
2674                 return matrix;
2675             }
2676
2677             /**
2678              * Creates an identity matrix with the given dimension. Values of the diagonal will be 1 and others will be 0.
2679              * @param {number} rows - Number of rows
2680              * @param {number} [columns=rows] - Number of columns
2681              * @param {number} [value=1] - Value to fill the diagonal with
2682              * @return {Matrix} - The new identity matrix
2683              */
2684             static eye(rows, columns, value) {
2685                 if (columns === undefined) columns = rows;
2686                 if (value === undefined) value = 1;
2687                 var min = Math.min(rows, columns);
2688                 var matrix = this.zeros(rows, columns);
2689                 for (var i = 0; i < min; i++) {
2690                     matrix.set(i, i, value);
2691                 }
2692                 return matrix;
2693             }
2694
2695             /**
2696              * Creates a diagonal matrix based on the given array.
2697              * @param {Array} data - Array containing the data for the diagonal
2698              * @param {number} [rows] - Number of rows (Default: data.length)
2699              * @param {number} [columns] - Number of columns (Default: rows)
2700              * @return {Matrix} - The new diagonal matrix
2701              */
2702             static diag(data, rows, columns) {
2703                 var l = data.length;
2704                 if (rows === undefined) rows = l;
2705                 if (columns === undefined) columns = rows;
2706                 var min = Math.min(l, rows, columns);
2707                 var matrix = this.zeros(rows, columns);
2708                 for (var i = 0; i < min; i++) {
2709                     matrix.set(i, i, data[i]);
2710                 }
2711                 return matrix;
2712             }
2713
2714             /**
2715              * Returns a matrix whose elements are the minimum between matrix1 and matrix2
2716              * @param {Matrix} matrix1
2717              * @param {Matrix} matrix2
2718              * @return {Matrix}
2719              */
2720             static min(matrix1, matrix2) {
2721                 matrix1 = this.checkMatrix(matrix1);
2722                 matrix2 = this.checkMatrix(matrix2);
2723                 var rows = matrix1.rows;
2724                 var columns = matrix1.columns;
2725                 var result = new this(rows, columns);
2726                 for (var i = 0; i < rows; i++) {
2727                     for (var j = 0; j < columns; j++) {
2728                         result.set(i, j, Math.min(matrix1.get(i, j), matrix2.get(i, j)));
2729                     }
2730                 }
2731                 return result;
2732             }
2733
2734             /**
2735              * Returns a matrix whose elements are the maximum between matrix1 and matrix2
2736              * @param {Matrix} matrix1
2737              * @param {Matrix} matrix2
2738              * @return {Matrix}
2739              */
2740             static max(matrix1, matrix2) {
2741                 matrix1 = this.checkMatrix(matrix1);
2742                 matrix2 = this.checkMatrix(matrix2);
2743                 var rows = matrix1.rows;
2744                 var columns = matrix1.columns;
2745                 var result = new this(rows, columns);
2746                 for (var i = 0; i < rows; i++) {
2747                     for (var j = 0; j < columns; j++) {
2748                         result.set(i, j, Math.max(matrix1.get(i, j), matrix2.get(i, j)));
2749                     }
2750                 }
2751                 return result;
2752             }
2753
2754             /**
2755              * Check that the provided value is a Matrix and tries to instantiate one if not
2756              * @param {*} value - The value to check
2757              * @return {Matrix}
2758              */
2759             static checkMatrix(value) {
2760                 return Matrix.isMatrix(value) ? value : new this(value);
2761             }
2762
2763             /**
2764              * Returns true if the argument is a Matrix, false otherwise
2765              * @param {*} value - The value to check
2766              * @return {boolean}
2767              */
2768             static isMatrix(value) {
2769                 return (value != null) && (value.klass === 'Matrix');
2770             }
2771
2772             /**
2773              * @prop {number} size - The number of elements in the matrix.
2774              */
2775             get size() {
2776                 return this.rows * this.columns;
2777             }
2778
2779             /**
2780              * Applies a callback for each element of the matrix. The function is called in the matrix (this) context.
2781              * @param {function} callback - Function that will be called with two parameters : i (row) and j (column)
2782              * @return {Matrix} this
2783              */
2784             apply(callback) {
2785                 if (typeof callback !== 'function') {
2786                     throw new TypeError('callback must be a function');
2787                 }
2788                 var ii = this.rows;
2789                 var jj = this.columns;
2790                 for (var i = 0; i < ii; i++) {
2791                     for (var j = 0; j < jj; j++) {
2792                         callback.call(this, i, j);
2793                     }
2794                 }
2795                 return this;
2796             }
2797
2798             /**
2799              * Returns a new 1D array filled row by row with the matrix values
2800              * @return {Array}
2801              */
2802             to1DArray() {
2803                 var array = new Array(this.size);
2804                 for (var i = 0; i < this.rows; i++) {
2805                     for (var j = 0; j < this.columns; j++) {
2806                         array[i * this.columns + j] = this.get(i, j);
2807                     }
2808                 }
2809                 return array;
2810             }
2811
2812             /**
2813              * Returns a 2D array containing a copy of the data
2814              * @return {Array}
2815              */
2816             to2DArray() {
2817                 var copy = new Array(this.rows);
2818                 for (var i = 0; i < this.rows; i++) {
2819                     copy[i] = new Array(this.columns);
2820                     for (var j = 0; j < this.columns; j++) {
2821                         copy[i][j] = this.get(i, j);
2822                     }
2823                 }
2824                 return copy;
2825             }
2826
2827             /**
2828              * @return {boolean} true if the matrix has one row
2829              */
2830             isRowVector() {
2831                 return this.rows === 1;
2832             }
2833
2834             /**
2835              * @return {boolean} true if the matrix has one column
2836              */
2837             isColumnVector() {
2838                 return this.columns === 1;
2839             }
2840
2841             /**
2842              * @return {boolean} true if the matrix has one row or one column
2843              */
2844             isVector() {
2845                 return (this.rows === 1) || (this.columns === 1);
2846             }
2847
2848             /**
2849              * @return {boolean} true if the matrix has the same number of rows and columns
2850              */
2851             isSquare() {
2852                 return this.rows === this.columns;
2853             }
2854
2855             /**
2856              * @return {boolean} true if the matrix is square and has the same values on both sides of the diagonal
2857              */
2858             isSymmetric() {
2859                 if (this.isSquare()) {
2860                     for (var i = 0; i < this.rows; i++) {
2861                         for (var j = 0; j <= i; j++) {
2862                             if (this.get(i, j) !== this.get(j, i)) {
2863                                 return false;
2864                             }
2865                         }
2866                     }
2867                     return true;
2868                 }
2869                 return false;
2870             }
2871
2872             /**
2873              * Sets a given element of the matrix. mat.set(3,4,1) is equivalent to mat[3][4]=1
2874              * @abstract
2875              * @param {number} rowIndex - Index of the row
2876              * @param {number} columnIndex - Index of the column
2877              * @param {number} value - The new value for the element
2878              * @return {Matrix} this
2879              */
2880             set(rowIndex, columnIndex, value) { // eslint-disable-line no-unused-vars
2881                 throw new Error('set method is unimplemented');
2882             }
2883
2884             /**
2885              * Returns the given element of the matrix. mat.get(3,4) is equivalent to matrix[3][4]
2886              * @abstract
2887              * @param {number} rowIndex - Index of the row
2888              * @param {number} columnIndex - Index of the column
2889              * @return {number}
2890              */
2891             get(rowIndex, columnIndex) { // eslint-disable-line no-unused-vars
2892                 throw new Error('get method is unimplemented');
2893             }
2894
2895             /**
2896              * Creates a new matrix that is a repetition of the current matrix. New matrix has rowRep times the number of
2897              * rows of the matrix, and colRep times the number of columns of the matrix
2898              * @param {number} rowRep - Number of times the rows should be repeated
2899              * @param {number} colRep - Number of times the columns should be re
2900              * @return {Matrix}
2901              * @example
2902              * var matrix = new Matrix([[1,2]]);
2903              * matrix.repeat(2); // [[1,2],[1,2]]
2904              */
2905             repeat(rowRep, colRep) {
2906                 rowRep = rowRep || 1;
2907                 colRep = colRep || 1;
2908                 var matrix = new this.constructor[Symbol.species](this.rows * rowRep, this.columns * colRep);
2909                 for (var i = 0; i < rowRep; i++) {
2910                     for (var j = 0; j < colRep; j++) {
2911                         matrix.setSubMatrix(this, this.rows * i, this.columns * j);
2912                     }
2913                 }
2914                 return matrix;
2915             }
2916
2917             /**
2918              * Fills the matrix with a given value. All elements will be set to this value.
2919              * @param {number} value - New value
2920              * @return {Matrix} this
2921              */
2922             fill(value) {
2923                 for (var i = 0; i < this.rows; i++) {
2924                     for (var j = 0; j < this.columns; j++) {
2925                         this.set(i, j, value);
2926                     }
2927                 }
2928                 return this;
2929             }
2930
2931             /**
2932              * Negates the matrix. All elements will be multiplied by (-1)
2933              * @return {Matrix} this
2934              */
2935             neg() {
2936                 return this.mulS(-1);
2937             }
2938
2939             /**
2940              * Returns a new array from the given row index
2941              * @param {number} index - Row index
2942              * @return {Array}
2943              */
2944             getRow(index) {
2945                 util.checkRowIndex(this, index);
2946                 var row = new Array(this.columns);
2947                 for (var i = 0; i < this.columns; i++) {
2948                     row[i] = this.get(index, i);
2949                 }
2950                 return row;
2951             }
2952
2953             /**
2954              * Returns a new row vector from the given row index
2955              * @param {number} index - Row index
2956              * @return {Matrix}
2957              */
2958             getRowVector(index) {
2959                 return this.constructor.rowVector(this.getRow(index));
2960             }
2961
2962             /**
2963              * Sets a row at the given index
2964              * @param {number} index - Row index
2965              * @param {Array|Matrix} array - Array or vector
2966              * @return {Matrix} this
2967              */
2968             setRow(index, array) {
2969                 util.checkRowIndex(this, index);
2970                 array = util.checkRowVector(this, array);
2971                 for (var i = 0; i < this.columns; i++) {
2972                     this.set(index, i, array[i]);
2973                 }
2974                 return this;
2975             }
2976
2977             /**
2978              * Swaps two rows
2979              * @param {number} row1 - First row index
2980              * @param {number} row2 - Second row index
2981              * @return {Matrix} this
2982              */
2983             swapRows(row1, row2) {
2984                 util.checkRowIndex(this, row1);
2985                 util.checkRowIndex(this, row2);
2986                 for (var i = 0; i < this.columns; i++) {
2987                     var temp = this.get(row1, i);
2988                     this.set(row1, i, this.get(row2, i));
2989                     this.set(row2, i, temp);
2990                 }
2991                 return this;
2992             }
2993
2994             /**
2995              * Returns a new array from the given column index
2996              * @param {number} index - Column index
2997              * @return {Array}
2998              */
2999             getColumn(index) {
3000                 util.checkColumnIndex(this, index);
3001                 var column = new Array(this.rows);
3002                 for (var i = 0; i < this.rows; i++) {
3003                     column[i] = this.get(i, index);
3004                 }
3005                 return column;
3006             }
3007
3008             /**
3009              * Returns a new column vector from the given column index
3010              * @param {number} index - Column index
3011              * @return {Matrix}
3012              */
3013             getColumnVector(index) {
3014                 return this.constructor.columnVector(this.getColumn(index));
3015             }
3016
3017             /**
3018              * Sets a column at the given index
3019              * @param {number} index - Column index
3020              * @param {Array|Matrix} array - Array or vector
3021              * @return {Matrix} this
3022              */
3023             setColumn(index, array) {
3024                 util.checkColumnIndex(this, index);
3025                 array = util.checkColumnVector(this, array);
3026                 for (var i = 0; i < this.rows; i++) {
3027                     this.set(i, index, array[i]);
3028                 }
3029                 return this;
3030             }
3031
3032             /**
3033              * Swaps two columns
3034              * @param {number} column1 - First column index
3035              * @param {number} column2 - Second column index
3036              * @return {Matrix} this
3037              */
3038             swapColumns(column1, column2) {
3039                 util.checkColumnIndex(this, column1);
3040                 util.checkColumnIndex(this, column2);
3041                 for (var i = 0; i < this.rows; i++) {
3042                     var temp = this.get(i, column1);
3043                     this.set(i, column1, this.get(i, column2));
3044                     this.set(i, column2, temp);
3045                 }
3046                 return this;
3047             }
3048
3049             /**
3050              * Adds the values of a vector to each row
3051              * @param {Array|Matrix} vector - Array or vector
3052              * @return {Matrix} this
3053              */
3054             addRowVector(vector) {
3055                 vector = util.checkRowVector(this, vector);
3056                 for (var i = 0; i < this.rows; i++) {
3057                     for (var j = 0; j < this.columns; j++) {
3058                         this.set(i, j, this.get(i, j) + vector[j]);
3059                     }
3060                 }
3061                 return this;
3062             }
3063
3064             /**
3065              * Subtracts the values of a vector from each row
3066              * @param {Array|Matrix} vector - Array or vector
3067              * @return {Matrix} this
3068              */
3069             subRowVector(vector) {
3070                 vector = util.checkRowVector(this, vector);
3071                 for (var i = 0; i < this.rows; i++) {
3072                     for (var j = 0; j < this.columns; j++) {
3073                         this.set(i, j, this.get(i, j) - vector[j]);
3074                     }
3075                 }
3076                 return this;
3077             }
3078
3079             /**
3080              * Multiplies the values of a vector with each row
3081              * @param {Array|Matrix} vector - Array or vector
3082              * @return {Matrix} this
3083              */