From 70d5c41f3dabb3baa3862f938d559c692909a9e0 Mon Sep 17 00:00:00 2001 From: "Dakota St. Laurent" Date: Thu, 12 Feb 2015 00:16:08 -0500 Subject: [PATCH 1/2] fix #134 by adding helper functions for matrix, row vector, and column vector transposes; add helper functions for mat-mat, mat-vec and vec-mat multiplication --- lib/numbers/matrix.js | 500 ++++++++++++++++++++------------- test/matrix.test.js | 639 ++++++++++++++++++++++++++++-------------- 2 files changed, 739 insertions(+), 400 deletions(-) diff --git a/lib/numbers/matrix.js b/lib/numbers/matrix.js index 16d0d10..d438f32 100644 --- a/lib/numbers/matrix.js +++ b/lib/numbers/matrix.js @@ -21,7 +21,7 @@ var matrix = exports; var ERROR_MATRIX_NOT_SQUARE = 'Matrix must be square.', - ERROR_VECTOR_NOT_2D = 'Only two dimensional operations are supported at this time.'; + ERROR_VECTOR_NOT_2D = 'Only two dimensional operations are supported at this time.'; /** * Check to see if a point is 2D. Used in all 2D vector functions. @@ -53,7 +53,7 @@ matrix.deepCopy = function(arr) { for (var i = 0; i < arr.length; i++) { result[i] = arr[i].slice(); } - + return result; }; @@ -61,7 +61,7 @@ matrix.deepCopy = function(arr) { * Return true if matrix is square, false otherwise. * * @param {Array} arr - * @return {Boolean} + * @return {Boolean} */ matrix.isSquare = function(arr) { if (!Array.isArray(arr)) { @@ -85,14 +85,14 @@ matrix.isSquare = function(arr) { * @param {Array} matrix B. * @return {Array} summed matrix. */ -matrix.addition = function (arrA, arrB) { +matrix.addition = function(arrA, arrB) { if (arrA.length !== arrB.length || arrA[0].length !== arrB[0].length) { - throw new Error('Matrix mismatch'); + throw new Error('Dimension mismatch'); } var result = new Array(arrA.length), - i; - + i; + if (!arrA[0].length) { // The arrays are vectors. for (i = 0; i < arrA.length; i++) { @@ -100,11 +100,11 @@ matrix.addition = function (arrA, arrB) { } } else { for (i = 0; i < arrA.length; i++) { - result[i] = new Array(arrA[i].length); - - for (var j = 0; j < arrA[i].length; j++) { - result[i][j] = arrA[i][j] + arrB[i][j]; - } + result[i] = new Array(arrA[i].length); + + for (var j = 0; j < arrA[i].length; j++) { + result[i][j] = arrA[i][j] + arrB[i][j]; + } } } @@ -118,14 +118,14 @@ matrix.addition = function (arrA, arrB) { * @param {Array} matrix B. * @return {Array} subtracted matrix. */ -matrix.subtraction = function (arrA, arrB) { +matrix.subtraction = function(arrA, arrB) { if (arrA.length !== arrB.length || arrA[0].length !== arrB[0].length) { - throw new Error("Matrix mismatch"); + throw new Error("Dimension mismatch"); } var result = new Array(arrA.length), - i; - + i; + if (!arrA[0].length) { // The arrays are vectors. for (i = 0; i < arrA.length; i++) { @@ -133,11 +133,11 @@ matrix.subtraction = function (arrA, arrB) { } } else { for (i = 0; i < arrA.length; i++) { - result[i] = new Array(arrA[i].length); - - for (var j = 0; j < arrA[i].length; j++) { - result[i][j] = arrA[i][j] - arrB[i][j]; - } + result[i] = new Array(arrA[i].length); + + for (var j = 0; j < arrA[i].length; j++) { + result[i][j] = arrA[i][j] - arrB[i][j]; + } } } @@ -151,7 +151,7 @@ matrix.subtraction = function (arrA, arrB) { * @param {Number} scalar. * @return {Array} updated matrix. */ -matrix.scalar = function (arr, val) { +matrix.scalar = function(arr, val) { for (var i = 0; i < arr.length; i++) { for (var j = 0; j < arr[i].length; j++) { arr[i][j] = val * arr[i][j]; @@ -161,18 +161,12 @@ matrix.scalar = function (arr, val) { return arr; }; -/** - * Transpose a matrix. - * - * @param {Array} matrix. - * @return {Array} transposed matrix. - */ -matrix.transpose = function (arr) { +matrix.transposeMatrix = function(arr) { var result = new Array(arr[0].length); - + for (var i = 0; i < arr[0].length; i++) { result[i] = new Array(arr.length); - + for (var j = 0; j < arr.length; j++) { result[i][j] = arr[j][i]; } @@ -181,16 +175,62 @@ matrix.transpose = function (arr) { return result; }; +/** + * Transpose a row vector. + * + * @param {Array} row vector. + * @return {Array} transposed row vector (column vector). + */ +matrix.transposeRowVector = function(arr) { + var result = new Array(arr.length); + for (var i = 0; i < arr.length; i++) { + result[i] = [arr[i]]; + } + return result; +}; + +/** + * Transpose a column vector. + * + * @param {Array} column vector. + * @return {Array} transposed column vector (row vector). + */ +matrix.transposeColumnVector = function(arr) { + var result = new Array(arr.length); + for (var i = 0; i < arr.length; i++) { + result[i] = arr[i][0]; + } + return result; +}; + +/** + * Transpose a matrix. + * + * @param {Array} matrix. + * @return {Array} transposed matrix. + */ +matrix.transpose = function(arr) { + if (arr[0].length > 1) { + return matrix.transposeMatrix(arr); + } else if (arr[0].length) { + return matrix.transposeColumnVector(arr); + } else { + return matrix.transposeRowVector(arr); + } + + return result; +}; + /** * Create an identity matrix of dimension n x n. * * @param {Number} dimension of the identity array to be returned. * @return {Array} n x n identity matrix. */ -matrix.identity = function (n) { +matrix.identity = function(n) { var result = new Array(n); - - for (var i = 0; i < n ; i++) { + + for (var i = 0; i < n; i++) { result[i] = new Array(n); for (var j = 0; j < n; j++) { result[i][j] = (i === j) ? 1 : 0; @@ -207,7 +247,7 @@ matrix.identity = function (n) { * @param {Array} vector. * @return {Array} dot product. */ -matrix.dotproduct = function (vectorA, vectorB) { +matrix.dotproduct = function(vectorA, vectorB) { if (vectorA.length !== vectorB.length) { throw new Error("Vector mismatch"); } @@ -220,44 +260,114 @@ matrix.dotproduct = function (vectorA, vectorB) { }; /** - * Multiply two matrices. They must abide by standard matching. + * Perform vector-matrix multiplication. + * + * e.g. A x B = (m x n) x (n x m), where n, m are integers who define + * the dimensions of vector A, matrix B. + * + * @param {Array} vector. + * @param {Array} matrix. + * @return {Array} result. + */ +matrix.multiplyVecMat = function(vec, mat) { + if (vec.length !== mat.length) { + throw new Error("Dimension mismatch"); + } + + var result = new Array(mat[0].length); + + var mat_T = matrix.transposeMatrix(mat); + + for (var i = 0; i < result.length; i++) { + result[i] = matrix.dotproduct(vec, mat_T[i]); + } + return result; +}; + +/** + * Perform matrix-vector multiplication. + * + * e.g. A x B = (m x n) x (n x m), where n, m are integers who define + * the dimensions of matrix A, vector B. + * + * @param {Array} matrix. + * @param {Array} vector. + * @return {Array} result. + */ +matrix.multiplyMatVec = function(mat, vec) { + if (mat[0].length !== vec.length) { + throw new Error("Dimension mismatch"); + } + + var result = new Array(mat.length); + + var vec_T = matrix.transposeColumnVector(vec); + + for (var i = 0; i < result.length; i++) { + result[i] = [matrix.dotproduct(mat[i], vec_T)]; + } + return result; +}; + +/** + * Perform matrix-matrix multiplication. * * e.g. A x B = (m x n) x (n x m), where n, m are integers who define * the dimensions of matrices A, B. * * @param {Array} matrix. * @param {Array} matrix. - * @return {Array} result of multiplied matrices. + * @return {Array} result. */ -matrix.multiply = function (arrA, arrB) { +matrix.multiplyMatMat = function(arrA, arrB) { if (arrA[0].length !== arrB.length) { - throw new Error("Matrix mismatch"); + throw new Error("Dimension mismatch"); } var result = new Array(arrA.length); - + for (var x = 0; x < arrA.length; x++) { result[x] = new Array(arrB[0].length); } - var arrB_T = matrix.transpose(arrB); - + var arrB_T = matrix.transposeMatrix(arrB); + for (var i = 0; i < result.length; i++) { for (var j = 0; j < result[i].length; j++) { - result[i][j] = matrix.dotproduct(arrA[i],arrB_T[j]); + result[i][j] = matrix.dotproduct(arrA[i], arrB_T[j]); } } return result; }; +/** + * Perform matrix-matrix, matrix-vector or vector-matrix multiplication. + * + * e.g. A x B = (m x n) x (n x m), where n, m are integers who define + * the dimensions of matrices/vectors A, B. + * + * @param {Array} matrix / vector. + * @param {Array} matrix / vector. + * @return {Array} result. + */ +matrix.multiply = function(arrA, arrB) { + if (arrA[0].length > 1 && arrB[0].length > 1) { + return matrix.multiplyMatMat(arrA, arrB); + } else if (arrA[0].length > 1) { + return matrix.multiplyMatVec(arrA, arrB); + } else { + return matrix.multiplyVecMat(arrA, arrB); + } +}; + /** * Evaluate determinate of matrix. Expect speed - * degradation for matrices over 4x4. + * degradation for matrices over 4x4. * * @param {Array} matrix. * @return {Number} determinant. */ -matrix.determinant = function (m) { +matrix.determinant = function(m) { var numRow = m.length; var numCol = m[0].length; var det = 0; @@ -278,7 +388,7 @@ matrix.determinant = function (m) { diagLeft = m[0][col]; diagRight = m[0][col]; - for( row=1; row < numRow; row++ ) { + for (row = 1; row < numRow; row++) { diagRight *= m[row][(((col + row) % numCol) + numCol) % numCol]; diagLeft *= m[row][(((col - row) % numCol) + numCol) % numCol]; } @@ -322,7 +432,7 @@ matrix.lupDecomposition = function(arr) { this.getL = function(a) { var m = a[0].length; var L = matrix.identity(m); - + for (var i = 0; i < m; i++) { for (var j = 0; j < m; j++) { if (i > j) { @@ -330,14 +440,14 @@ matrix.lupDecomposition = function(arr) { } } } - + return L; }; this.getU = function(a) { var m = a[0].length; var U = matrix.identity(m); - + for (var i = 0; i < m; i++) { for (var j = 0; j < m; j++) { if (i <= j) { @@ -345,7 +455,7 @@ matrix.lupDecomposition = function(arr) { } } } - + return U; }; @@ -358,11 +468,11 @@ matrix.lupDecomposition = function(arr) { for (i = 0; i < size; i++) { currentRow = LU[i]; - var minIndex = Math.min(i,j); + var minIndex = Math.min(i, j); var s = 0; - + for (var k = 0; k < minIndex; k++) { - s += currentRow[k]*currentColumn[k]; + s += currentRow[k] * currentColumn[k]; } currentRow[j] = currentColumn[i] -= s; @@ -375,7 +485,7 @@ matrix.lupDecomposition = function(arr) { pivot = i; } } - + if (pivot != j) { LU = matrix.rowSwitch(LU, pivot, j); P = matrix.rowSwitch(P, pivot, j); @@ -387,7 +497,7 @@ matrix.lupDecomposition = function(arr) { } } } - + return [this.getL(LU), this.getU(LU), P]; }; @@ -399,7 +509,7 @@ matrix.lupDecomposition = function(arr) { * @param {String} direction - clockwise or counterclockwise. * @return {Array} vector. */ -matrix.rotate = function (point, degree, direction) { +matrix.rotate = function(point, degree, direction) { matrix._check2DVector(point); var negate = direction === 'clockwise' ? -1 : 1; @@ -421,7 +531,7 @@ matrix.rotate = function (point, degree, direction) { * @param {Number} sy. * @return {Array} vector. */ -matrix.scale = function (point, sx, sy) { +matrix.scale = function(point, sx, sy) { matrix._check2DVector(point); var transformation = [ @@ -440,7 +550,7 @@ matrix.scale = function (point, sx, sy) { * @param {String} direction - xaxis or yaxis. * @return {Array} vector. */ -matrix.shear = function (point, k, direction) { +matrix.shear = function(point, k, direction) { matrix._check2DVector(point); var xplaceholder = direction === 'xaxis' ? k : 0; @@ -462,12 +572,12 @@ matrix.shear = function (point, k, direction) { * @param {Number} ty. * @return {Array} vector. */ -matrix.affine = function (point, tx, ty) { +matrix.affine = function(point, tx, ty) { matrix._check2DVector(point); var transformation = [ [1, 0, tx], [0, 1, ty], - [0, 0, 1 ] + [0, 0, 1] ]; var newpoint = [ @@ -477,7 +587,7 @@ matrix.affine = function (point, tx, ty) { ]; var transformed = matrix.multiply(transformation, newpoint); - + return [ [transformed[0][0]], [transformed[1][0]] @@ -485,22 +595,22 @@ matrix.affine = function (point, tx, ty) { }; /** - * Scales a row of a matrix by a factor and returns the updated matrix. + * Scales a row of a matrix by a factor and returns the updated matrix. * Used in row reduction functions. - * + * * @param {Array} matrix. * @param {Number} row. * @param {Number} scale. */ -matrix.rowScale = function (m, row, scale) { +matrix.rowScale = function(m, row, scale) { var result = new Array(m.length); - + for (var i = 0; i < m.length; i++) { result[i] = new Array(m[i].length); - + for (var j = 0; j < m[i].length; j++) { if (i === row) { - result[i][j] = scale * m[i][j]; + result[i][j] = scale * m[i][j]; } else { result[i][j] = m[i][j]; } @@ -511,22 +621,22 @@ matrix.rowScale = function (m, row, scale) { }; /** - * Swaps two rows of a matrix and returns the updated matrix. + * Swaps two rows of a matrix and returns the updated matrix. * Used in row reduction functions. - * + * * @param {Array} matrix. * @param {Number} row1. * @param {Number} row2. */ -matrix.rowSwitch = function (m, row1, row2) { +matrix.rowSwitch = function(m, row1, row2) { var result = new Array(m.length); - + for (var i = 0; i < m.length; i++) { result[i] = new Array(m[i].length); - + for (var j = 0; j < m[i].length; j++) { if (i === row1) { - result[i][j] = m[row2][j]; + result[i][j] = m[row2][j]; } else if (i === row2) { result[i][j] = m[row1][j]; } else { @@ -539,19 +649,19 @@ matrix.rowSwitch = function (m, row1, row2) { /** * Adds a multiple of one row to another row - * in a matrix and returns the updated matrix. + * in a matrix and returns the updated matrix. * Used in row reduction functions. - * + * * @param {Array} matrix. * @param {Number} row1. * @param {Number} row2. */ -matrix.rowAddMultiple = function (m, from, to, scale){ +matrix.rowAddMultiple = function(m, from, to, scale) { var result = new Array(m.length); - + for (var i = 0; i < m.length; i++) { result[i] = new Array(m[i].length); - + for (var j = 0; j < m[i].length; j++) { if (i === to) { result[to][j] = m[to][j] + scale * m[from][j]; @@ -586,7 +696,7 @@ matrix.GaussJordanEliminate = function(m, epsilon) { var maxrow = y; y2 = y; while (++y2 < h) { - if(Math.abs(m[y2][y]) > Math.abs(m[maxrow][y])) + if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y])) maxrow = y2; } var tmp = m[y]; @@ -594,7 +704,7 @@ matrix.GaussJordanEliminate = function(m, epsilon) { m[maxrow] = tmp; // Singular - if(Math.abs(m[y][y]) <= eps) { + if (Math.abs(m[y][y]) <= eps) { return m; } @@ -617,7 +727,7 @@ matrix.GaussJordanEliminate = function(m, epsilon) { while (++y2 < y) { x = w; while (--x >= y) { - m[y2][x] -= m[y][x] * m[y2][y] / c; + m[y2][x] -= m[y][x] * m[y2][y] / c; } } m[y][y] /= c; @@ -655,11 +765,11 @@ matrix.inverse = function(m) { } var n = m.length, - identity = matrix.identity(n), - i; + identity = matrix.identity(n), + i; // AI - for(i=0; i= M[0].length) { throw new Error('The specified column must be between 0 and the number of columns - 1.'); } - for (var i=0; i= L.length) { throw new Error('The desired order of the rows must start at 0 and end at the number of rows - 1.'); - } else { + } else { result.push(M[L[i]]); } } @@ -734,13 +844,13 @@ matrix.reorderCols = function(M, L) { } else if (L.length !== M[0].length) { throw new Error('The reordered matrix must have the same number of columns as the original matrix.'); } - for (var i=0; i= L.length) { throw new Error('The desired order of the columns must start at 0 and end at the number of columns - 1.'); } else { - result.push(matrix.getCol(M, L[i]) ); + result.push(matrix.getCol(M, L[i])); } } return matrix.transpose(result); @@ -753,11 +863,11 @@ matrix.reorderCols = function(M, L) { * @return {Array} reversed matrix */ matrix.reverseRows = function(M) { - var L = []; - for (var i=M.length-1; i>-1; i--) { - L.push(i); - } - return matrix.reorderRows(M,L); + var L = []; + for (var i = M.length - 1; i > -1; i--) { + L.push(i); + } + return matrix.reorderRows(M, L); }; /** @@ -767,11 +877,11 @@ matrix.reverseRows = function(M) { * @return {Array} reversed matrix */ matrix.reverseCols = function(M) { - var L = []; - for (var i=M.length-1; i>-1; i--) { - L.push(i); - } - return matrix.reorderCols(M,L); + var L = []; + for (var i = M.length - 1; i > -1; i--) { + L.push(i); + } + return matrix.reorderCols(M, L); }; /** @@ -781,16 +891,16 @@ matrix.reverseCols = function(M) { * @param {Int} number of columns * @return {Array} matrix */ -matrix.zeros = function(n,m) { +matrix.zeros = function(n, m) { var M = new Array(n); if (n < 1 || m < 1) { throw new Error('The matrix dimensions must be positive integers.'); } n = Math.ceil(n); m = Math.ceil(m); - for (var i=0; i ans) { ans = term; @@ -962,7 +1082,7 @@ matrix.vectorNorm = function(v,p) { case -Infinity: ans = Infinity; - for (i=0; i Date: Thu, 12 Feb 2015 00:33:38 -0500 Subject: [PATCH 2/2] change beautifier to use 2 spaces and to put spaces after function keyword; run format (apparently for the first time); add .jshintrc; update public js --- .jshintrc | 87 +++ gulpfile.js | 14 +- lib/numbers/basic.js | 199 +++---- lib/numbers/calculus.js | 53 +- lib/numbers/complex.js | 46 +- lib/numbers/dsp.js | 23 +- lib/numbers/generators.js | 8 +- lib/numbers/matrix.js | 296 +++++----- lib/numbers/prime.js | 71 +-- lib/numbers/random.js | 41 +- lib/numbers/statistic.js | 44 +- src/numbers.js | 1113 +++++++++++++++++++++---------------- src/numbers.min.js | 2 +- test/basic.test.js | 750 ++++++++++++------------- test/calculus.test.js | 12 +- test/complex.test.js | 40 +- test/dsp.test.js | 13 +- test/generators.test.js | 4 +- test/matrix.test.js | 116 ++-- test/prime.test.js | 78 +-- test/random.test.js | 55 +- test/statistic.test.js | 38 +- test/testing.js | 28 +- 23 files changed, 1714 insertions(+), 1417 deletions(-) create mode 100644 .jshintrc mode change 100755 => 100644 src/numbers.js mode change 100755 => 100644 src/numbers.min.js diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..6101dcb --- /dev/null +++ b/.jshintrc @@ -0,0 +1,87 @@ +{ + // JSHint Default Configuration File (as on JSHint website) + // See http://jshint.com/docs/ for more details + + "maxerr" : 50, // {int} Maximum error before stopping + + // Enforcing + "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) + "camelcase" : false, // true: Identifiers must be in camelCase + "curly" : false, // true: Require {} for every new block or scope + "eqeqeq" : true, // true: Require triple equals (===) for comparison + "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() + "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc. + "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` + "indent" : 2, // {int} Number of spaces to use for indentation + "latedef" : false, // true: Require variables/functions to be defined before being used + "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()` + "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` + "noempty" : true, // true: Prohibit use of empty blocks + "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters. + "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) + "plusplus" : false, // true: Prohibit use of `++` & `--` + "quotmark" : false, // Quotation mark consistency: + // false : do nothing (default) + // true : ensure whatever is used is consistent + // "single" : require single quotes + // "double" : require double quotes + "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) + "unused" : true, // true: Require all defined variables be used + "strict" : false, // true: Requires all functions run in ES5 Strict Mode + "maxparams" : false, // {int} Max number of formal params allowed per function + "maxdepth" : false, // {int} Max depth of nested blocks (within functions) + "maxstatements" : false, // {int} Max number statements per function + "maxcomplexity" : false, // {int} Max cyclomatic complexity per function + "maxlen" : false, // {int} Max number of characters per line + + // Relaxing + "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) + "boss" : false, // true: Tolerate assignments where comparisons would be expected + "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. + "eqnull" : false, // true: Tolerate use of `== null` + "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) + "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) + "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) + // (ex: `for each`, multiple try/catch, function expression…) + "evil" : false, // true: Tolerate use of `eval` and `new Function()` + "expr" : false, // true: Tolerate `ExpressionStatement` as Programs + "funcscope" : false, // true: Tolerate defining variables inside control statements + "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') + "iterator" : false, // true: Tolerate using the `__iterator__` property + "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block + "laxbreak" : false, // true: Tolerate possibly unsafe line breakings + "laxcomma" : false, // true: Tolerate comma-first style coding + "loopfunc" : false, // true: Tolerate functions being defined in loops + "multistr" : false, // true: Tolerate multi-line strings + "noyield" : false, // true: Tolerate generator functions with no yield statement in them. + "notypeof" : false, // true: Tolerate invalid typeof operator values + "proto" : false, // true: Tolerate using the `__proto__` property + "scripturl" : false, // true: Tolerate script-targeted URLs + "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` + "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation + "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` + "validthis" : false, // true: Tolerate using this in a non-constructor function + + // Environments + "browser" : true, // Web Browser (window, document, etc) + "browserify" : false, // Browserify (node.js code in the browser) + "couch" : false, // CouchDB + "devel" : true, // Development/debugging (alert, confirm, etc) + "dojo" : false, // Dojo Toolkit + "jasmine" : false, // Jasmine + "jquery" : false, // jQuery + "mocha" : true, // Mocha + "mootools" : false, // MooTools + "node" : true, // Node.js + "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) + "prototypejs" : false, // Prototype and Scriptaculous + "qunit" : false, // QUnit + "rhino" : false, // Rhino + "shelljs" : false, // ShellJS + "worker" : false, // Web Workers + "wsh" : false, // Windows Scripting Host + "yui" : false, // Yahoo User Interface + + // Custom Globals + "globals" : {} // additional predefined global variables +} diff --git a/gulpfile.js b/gulpfile.js index d996c24..b091c25 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -31,13 +31,23 @@ gulp.task("default", [ "build" ]); gulp.task("format:lib", function(){ return gulp.src( ["./lib/**/*.js"], { base : "./lib"} ) - .pipe(prettify()) + .pipe(prettify({ + js: { + indentSize: 2, + space_after_anon_function: true + } + })) .pipe(gulp.dest("./lib")); }); gulp.task("format:test", function(){ return gulp.src( ["./test/*.js"], { base : "./"} ) - .pipe(prettify()) + .pipe(prettify({ + js: { + indentSize: 2, + space_after_anon_function: true + } + })) .pipe(gulp.dest("./")); }); diff --git a/lib/numbers/basic.js b/lib/numbers/basic.js index aef90f6..4827804 100644 --- a/lib/numbers/basic.js +++ b/lib/numbers/basic.js @@ -29,8 +29,8 @@ var basic = exports; basic.sum = function (arr) { if (Object.prototype.toString.call(arr) === '[object Array]') { var total = 0; - for (var i = 0 ; i < arr.length ; i++) { - if (typeof(arr[i]) === 'number') { + for (var i = 0; i < arr.length; i++) { + if (typeof (arr[i]) === 'number') { total = total + arr[i]; } else { throw new Error('All elements in array must be numbers'); @@ -53,11 +53,11 @@ basic.sum = function (arr) { basic.subtraction = function (arr) { if (Object.prototype.toString.call(arr) === '[object Array]') { var total = arr[0]; - if (typeof(total) !== 'number') { + if (typeof (total) !== 'number') { throw new Error('All elements in array must be numbers'); } for (var i = 1, length = arr.length; i < length; i++) { - if (typeof(arr[i]) === 'number') { + if (typeof (arr[i]) === 'number') { total -= arr[i]; } else { throw new Error('All elements in array must be numbers'); @@ -78,11 +78,11 @@ basic.subtraction = function (arr) { basic.product = function (arr) { if (Object.prototype.toString.call(arr) === '[object Array]') { var total = arr[0]; - if (typeof(total) !== 'number') { + if (typeof (total) !== 'number') { throw new Error('All elements in array must be numbers'); } for (var i = 1, length = arr.length; i < length; i++) { - if (typeof(arr[i]) === 'number') { + if (typeof (arr[i]) === 'number') { total = total * arr[i]; } else { throw new Error('All elements in array must be numbers'); @@ -101,12 +101,12 @@ basic.product = function (arr) { * @return {Number} square of number */ basic.square = function (num) { - if (typeof(num) !== 'number') { + if (typeof (num) !== 'number') { throw new Error('Input must be a number.'); } else { - return num * num; + return num * num; } - + }; /** @@ -120,8 +120,8 @@ basic.binomial = function (n, k) { var arr = []; - function _binomial (n, k) { - if (typeof(n) !== 'number' && typeof(k) !== 'number') { + function _binomial(n, k) { + if (typeof (n) !== 'number' && typeof (k) !== 'number') { throw new Error('Input must be a number.'); } if (n >= 0 && k === 0) return 1; @@ -142,11 +142,12 @@ basic.binomial = function (n, k) { * @param {Number} integer. * @return {Number} result. */ -basic.factorial = function (num){ - if(typeof(num) !== 'number') throw new Error("Input must be a number."); - if(num < 0) throw new Error("Input must not be negative."); - var i = 2, o = 1; - +basic.factorial = function (num) { + if (typeof (num) !== 'number') throw new Error("Input must be a number."); + if (num < 0) throw new Error("Input must not be negative."); + var i = 2, + o = 1; + while (i <= num) { o *= i++; } @@ -156,7 +157,7 @@ basic.factorial = function (num){ /** * Calculate the greastest common divisor amongst two integers. - * + * * @param {Number} number A. * @param {Number} number B. * @return {Number} greatest common divisor for integers A, B. @@ -205,18 +206,19 @@ basic.lcm = function (num1, num2) { * @return {Array} random elements. */ basic.random = function (arr, quant, allowDuplicates) { - if (arr.length === 0){ + if (arr.length === 0) { throw new Error('Empty array'); - } else if (quant > arr.length && !allowDuplicates){ + } else if (quant > arr.length && !allowDuplicates) { throw new Error('Quantity requested exceeds size of array'); } - + if (allowDuplicates === true) { - var result = [], i; + var result = [], + i; for (i = 0; i < quant; i++) { result[i] = arr[Math.floor(Math.random() * arr.length)]; } - return result; + return result; } else { return basic.shuffle(arr).slice(0, quant); } @@ -229,7 +231,8 @@ basic.random = function (arr, quant, allowDuplicates) { * @return {Array} shuffled array. */ basic.shuffle = function (array) { - var m = array.length, t, i; + var m = array.length, + t, i; while (m) { i = Math.floor(Math.random() * m--); @@ -252,14 +255,15 @@ basic.max = function (arr) { if (!Array.isArray(arr)) { throw new Error("Input must be of type Array"); } - var max = -Infinity, val; + var max = -Infinity, + val; for (var i = 0, len = arr.length; i < len; i++) { val = +arr[i]; if (max < val) { max = val; } // Math.max() returns NaN if one of the elements is not a number. - if( val !== val ){ + if (val !== val) { return NaN; } } @@ -276,14 +280,15 @@ basic.min = function (arr) { if (!Array.isArray(arr)) { throw new Error("Input must be of type Array"); } - var min = +Infinity, val; + var min = +Infinity, + val; for (var i = 0, len = arr.length; i < len; i++) { val = +arr[i]; if (val < min) { min = val; } // Math.min() returns NaN if one of the elements is not a number. - if( val !== val ){ + if (val !== val) { return NaN; } } @@ -299,7 +304,8 @@ basic.min = function (arr) { * @return {Array} An array containing numbers within the range. */ basic.range = function (start, stop, step) { - var array, i = 0, len; + var array, i = 0, + len; if (arguments.length <= 1) { stop = start || 0; @@ -325,43 +331,43 @@ basic.range = function (start, stop, step) { }; /** - * Determine if the number is an integer. - * - * @param {Number} the number - * @return {Boolean} true for int, false for not int. - */ + * Determine if the number is an integer. + * + * @param {Number} the number + * @return {Boolean} true for int, false for not int. + */ basic.isInt = function (n) { return n % 1 === 0; }; /** - * Calculate the divisor and modulus of two integers. - * - * @param {Number} int a. - * @param {Number} int b. - * @return {Array} [div, mod]. - */ + * Calculate the divisor and modulus of two integers. + * + * @param {Number} int a. + * @param {Number} int b. + * @return {Array} [div, mod]. + */ basic.divMod = function (a, b) { - if(b <= 0) throw new Error("b cannot be zero. Undefined."); + if (b <= 0) throw new Error("b cannot be zero. Undefined."); if (!basic.isInt(a) || !basic.isInt(b)) throw new Error("A or B are not integers."); return [Math.floor(a / b), a % b]; }; /** - * Calculate: - * if b >= 1: a^b mod m. - * if b = -1: modInverse(a, m). - * if b < 1: finds a modular rth root of a such that b = 1/r. - * - * @param {Number} Number a. - * @param {Number} Number b. - * @param {Number} Modulo m. - * @return {Number} see the above documentation for return values. - */ + * Calculate: + * if b >= 1: a^b mod m. + * if b = -1: modInverse(a, m). + * if b < 1: finds a modular rth root of a such that b = 1/r. + * + * @param {Number} Number a. + * @param {Number} Number b. + * @param {Number} Modulo m. + * @return {Number} see the above documentation for return values. + */ basic.powerMod = function (a, b, m) { - if(typeof(a) !== 'number' || typeof(b) !== 'number' || typeof(m) !== 'number') throw new Error("Inputs must be numbers."); + if (typeof (a) !== 'number' || typeof (b) !== 'number' || typeof (m) !== 'number') throw new Error("Inputs must be numbers."); // If b < -1 should be a small number, this method should work for now. - if (b < -1) return Math.pow(a, b) % m; + if (b < -1) return Math.pow(a, b) % m; if (b === 0) return 1 % m; if (b >= 1) { var result = 1; @@ -369,7 +375,7 @@ basic.powerMod = function (a, b, m) { if ((b % 2) === 1) { result = (result * a) % m; } - + a = (a * a) % m; b = b >> 1; } @@ -378,7 +384,7 @@ basic.powerMod = function (a, b, m) { if (b === -1) return basic.modInverse(a, m); if (b < 1) { - return basic.powerMod(a, Math.pow(b, -1), m); + return basic.powerMod(a, Math.pow(b, -1), m); } }; @@ -405,20 +411,20 @@ basic.egcd = function (a, b) { throw new Error("Can only operate on integers"); } var signX = (a < 0) ? -1 : 1, - signY = (b < 0) ? -1 : 1, - x = 0, - y = 1, - oldX = 1, - oldY = 0, - q, r, m, n; - a = Math.abs(a); - b = Math.abs(b); - - while(a !== 0){ - q = Math.floor(b/a); + signY = (b < 0) ? -1 : 1, + x = 0, + y = 1, + oldX = 1, + oldY = 0, + q, r, m, n; + a = Math.abs(a); + b = Math.abs(b); + + while (a !== 0) { + q = Math.floor(b / a); r = b % a; - m = x - oldX*q; - n = y - oldY*q; + m = x - oldX * q; + n = y - oldY * q; b = a; a = r; x = oldX; @@ -426,18 +432,18 @@ basic.egcd = function (a, b) { oldX = m; oldY = n; } - return [b, signX*x, signY*y]; + return [b, signX * x, signY * y]; }; /** - * Calculate the modular inverse of a number. - * - * @param {Number} Number a. - * @param {Number} Modulo m. - * @return {Number} if true, return number, else throw error. - */ + * Calculate the modular inverse of a number. + * + * @param {Number} Number a. + * @param {Number} Modulo m. + * @return {Number} if true, return number, else throw error. + */ basic.modInverse = function (a, m) { var r = basic.egcd(a, m); - if (r[0] != 1) throw new Error('No modular inverse exists'); + if (r[0] !== 1) throw new Error('No modular inverse exists'); return r[1] % m; }; @@ -449,8 +455,8 @@ basic.modInverse = function (a, m) { * @param {Number} second number. * @param {Number} epsilon. */ -basic.numbersEqual = function(first, second, epsilon) { - if(typeof(first) !== 'number' || typeof(second) !== 'number' || typeof(epsilon) !== 'number') throw new Error("First and Second must be numbers."); +basic.numbersEqual = function (first, second, epsilon) { + if (typeof (first) !== 'number' || typeof (second) !== 'number' || typeof (epsilon) !== 'number') throw new Error("First and Second must be numbers."); return (first - second) < epsilon && (first - second) > -epsilon; }; @@ -463,13 +469,18 @@ basic.numbersEqual = function(first, second, epsilon) { * @param {Number} Steps to fall * @returns {Number} Result */ -basic.fallingFactorial = function(n, k) { - var i = (n-k+1), r = 1; - - if(n<0) { throw new Error("n cannot be negative."); } - if(k>n) { throw new Error("k cannot be greater than n."); } - - while(i <= n) { +basic.fallingFactorial = function (n, k) { + var i = (n - k + 1), + r = 1; + + if (n < 0) { + throw new Error("n cannot be negative."); + } + if (k > n) { + throw new Error("k cannot be greater than n."); + } + + while (i <= n) { r *= i++; } @@ -484,14 +495,14 @@ basic.fallingFactorial = function(n, k) { * @return {Number} number of ordered variations */ -basic.permutation = function(n, k) { - if (n <= 0) { - throw new Error("n cannot be less than or equal to 0."); - } - if (n < k) { - throw new Error("k cannot be greater than k."); - } - var binomial = basic.binomial(n, k); - var permutation = binomial * basic.factorial(k); - return permutation; +basic.permutation = function (n, k) { + if (n <= 0) { + throw new Error("n cannot be less than or equal to 0."); + } + if (n < k) { + throw new Error("k cannot be greater than k."); + } + var binomial = basic.binomial(n, k); + var permutation = binomial * basic.factorial(k); + return permutation; }; diff --git a/lib/numbers/calculus.js b/lib/numbers/calculus.js index bfaa60f..8aca561 100644 --- a/lib/numbers/calculus.js +++ b/lib/numbers/calculus.js @@ -44,7 +44,7 @@ calculus.pointDiff = function (func, point) { * @param {Number} point to initiate evaluation. * @param {Number} point to complete evaluation. * @param {Number} quantity of divisions. - * @param {Function} (Optional) Function that returns which value + * @param {Function} (Optional) Function that returns which value * to sample on each interval; if none is provided, left endpoints * will be used. * @return {Number} result. @@ -53,7 +53,7 @@ calculus.Riemann = function (func, start, finish, n, sampler) { var inc = (finish - start) / n; var totalHeight = 0; var i; - + if (typeof sampler === 'function') { for (i = start; i < finish; i += inc) { totalHeight += func(sampler(i, i + inc)); @@ -63,7 +63,7 @@ calculus.Riemann = function (func, start, finish, n, sampler) { totalHeight += func(i); } } - + return totalHeight * inc; }; @@ -76,7 +76,7 @@ calculus.Riemann = function (func, start, finish, n, sampler) { * @param {Number} point to complete evaluation. * @return {Number} evaluation. */ -function SimpsonDef (func, a, b) { +function SimpsonDef(func, a, b) { var c = (a + b) / 2; var d = Math.abs(b - a) / 6; return d * (func(a) + 4 * func(c) + func(b)); @@ -94,11 +94,11 @@ function SimpsonDef (func, a, b) { * @param {Number} Error bound (epsilon). * @return {Number} recursive evaluation of left and right side. */ -function SimpsonRecursive (func, a, b, whole, eps) { +function SimpsonRecursive(func, a, b, whole, eps) { var c = a + b; var left = SimpsonDef(func, a, c); var right = SimpsonDef(func, c, b); - + if (Math.abs(left + right - whole) <= 15 * eps) { return left + right + (left + right - whole) / 15; } else { @@ -112,7 +112,7 @@ function SimpsonRecursive (func, a, b, whole, eps) { * @param {Function} math function to be evaluated. * @param {Number} point to initiate evaluation. * @param {Number} point to complete evaluation. - * @param {Number} Optional error bound (epsilon); + * @param {Number} Optional error bound (epsilon); * global error bound will be used as a fallback. * @return {Number} area underneath curve. */ @@ -162,17 +162,16 @@ calculus.StirlingGamma = function (num) { calculus.LanczosGamma = function (num) { var p = [ 0.99999999999980993, 676.5203681218851, -1259.1392167224028, - 771.32342877765313, -176.61502916214059, 12.507343278686905, - -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7 + 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7 ]; var i; var g = 7; - if(num < 0.5) return Math.PI / (Math.sin(Math.PI * num) * calculus.LanczosGamma(1 - num)); + if (num < 0.5) return Math.PI / (Math.sin(Math.PI * num) * calculus.LanczosGamma(1 - num)); num -= 1; - + var a = p[0]; var t = num + g + 0.5; @@ -185,9 +184,9 @@ calculus.LanczosGamma = function (num) { /** - * Calculate the integral of f(x1,x2,...) over intervals + * Calculate the integral of f(x1,x2,...) over intervals * [a1,b1], [a2,b2], ..., using the montecarlo method: - * + * * integral of f(x,y) = (1/N)*(b2-a2)*(b1-a1)*sum(f) * * where N = number of points for f to be evaluated at. @@ -199,7 +198,7 @@ calculus.LanczosGamma = function (num) { * @param {Array(s)} intervals * @return {Number} approximation to integral */ -calculus.MonteCarlo = function(func, N) { +calculus.MonteCarlo = function (func, N) { //takes an arbitrary number of arguments after N //all of the arguments must be arrays which are intervals if (arguments.length < 2) { @@ -209,23 +208,27 @@ calculus.MonteCarlo = function(func, N) { } var L = []; N = Math.ceil(N); - for (var i=2; i 0) { @@ -38,7 +38,7 @@ generate.fibonacci = function (n) { n = Math.floor(n / 2); bits.push(bit); } - + return bits.reverse(); }; @@ -47,7 +47,7 @@ generate.fibonacci = function (n) { var c = 1; var system = bitSystem(n); var temp; - + for (var i = 0; i < system.length; i++) { var bit = system[i]; if (bit) { @@ -75,7 +75,7 @@ generate.fibonacci = function (n) { */ generate.collatz = function (n, result) { result.push(n); - + if (n === 1) { return; } else if (n % 2 === 0) { diff --git a/lib/numbers/matrix.js b/lib/numbers/matrix.js index d438f32..6bdeadd 100644 --- a/lib/numbers/matrix.js +++ b/lib/numbers/matrix.js @@ -30,7 +30,7 @@ var ERROR_MATRIX_NOT_SQUARE = 'Matrix must be square.', * @param {Array} point in question. * @return {undefined} nothing is returned. */ -matrix._check2DVector = function(point) { +matrix._check2DVector = function (point) { if (point.length !== 2) { throw new Error(ERROR_VECTOR_NOT_2D); } @@ -42,7 +42,7 @@ matrix._check2DVector = function(point) { * @param {Array} matrix to copy. * @return {Array} copied matrix. */ -matrix.deepCopy = function(arr) { +matrix.deepCopy = function (arr) { if (!Array.isArray(arr)) { throw new Error('Input must be a matrix.'); } else if (arr[0][0] === undefined) { @@ -63,7 +63,7 @@ matrix.deepCopy = function(arr) { * @param {Array} arr * @return {Boolean} */ -matrix.isSquare = function(arr) { +matrix.isSquare = function (arr) { if (!Array.isArray(arr)) { throw new Error('Input must be a matrix.'); } else if (arr[0][0] === undefined) { @@ -85,7 +85,7 @@ matrix.isSquare = function(arr) { * @param {Array} matrix B. * @return {Array} summed matrix. */ -matrix.addition = function(arrA, arrB) { +matrix.addition = function (arrA, arrB) { if (arrA.length !== arrB.length || arrA[0].length !== arrB[0].length) { throw new Error('Dimension mismatch'); } @@ -118,7 +118,7 @@ matrix.addition = function(arrA, arrB) { * @param {Array} matrix B. * @return {Array} subtracted matrix. */ -matrix.subtraction = function(arrA, arrB) { +matrix.subtraction = function (arrA, arrB) { if (arrA.length !== arrB.length || arrA[0].length !== arrB[0].length) { throw new Error("Dimension mismatch"); } @@ -151,7 +151,7 @@ matrix.subtraction = function(arrA, arrB) { * @param {Number} scalar. * @return {Array} updated matrix. */ -matrix.scalar = function(arr, val) { +matrix.scalar = function (arr, val) { for (var i = 0; i < arr.length; i++) { for (var j = 0; j < arr[i].length; j++) { arr[i][j] = val * arr[i][j]; @@ -161,7 +161,7 @@ matrix.scalar = function(arr, val) { return arr; }; -matrix.transposeMatrix = function(arr) { +matrix.transposeMatrix = function (arr) { var result = new Array(arr[0].length); for (var i = 0; i < arr[0].length; i++) { @@ -181,7 +181,7 @@ matrix.transposeMatrix = function(arr) { * @param {Array} row vector. * @return {Array} transposed row vector (column vector). */ -matrix.transposeRowVector = function(arr) { +matrix.transposeRowVector = function (arr) { var result = new Array(arr.length); for (var i = 0; i < arr.length; i++) { result[i] = [arr[i]]; @@ -195,7 +195,7 @@ matrix.transposeRowVector = function(arr) { * @param {Array} column vector. * @return {Array} transposed column vector (row vector). */ -matrix.transposeColumnVector = function(arr) { +matrix.transposeColumnVector = function (arr) { var result = new Array(arr.length); for (var i = 0; i < arr.length; i++) { result[i] = arr[i][0]; @@ -209,7 +209,7 @@ matrix.transposeColumnVector = function(arr) { * @param {Array} matrix. * @return {Array} transposed matrix. */ -matrix.transpose = function(arr) { +matrix.transpose = function (arr) { if (arr[0].length > 1) { return matrix.transposeMatrix(arr); } else if (arr[0].length) { @@ -217,8 +217,6 @@ matrix.transpose = function(arr) { } else { return matrix.transposeRowVector(arr); } - - return result; }; /** @@ -227,7 +225,7 @@ matrix.transpose = function(arr) { * @param {Number} dimension of the identity array to be returned. * @return {Array} n x n identity matrix. */ -matrix.identity = function(n) { +matrix.identity = function (n) { var result = new Array(n); for (var i = 0; i < n; i++) { @@ -247,7 +245,7 @@ matrix.identity = function(n) { * @param {Array} vector. * @return {Array} dot product. */ -matrix.dotproduct = function(vectorA, vectorB) { +matrix.dotproduct = function (vectorA, vectorB) { if (vectorA.length !== vectorB.length) { throw new Error("Vector mismatch"); } @@ -269,7 +267,7 @@ matrix.dotproduct = function(vectorA, vectorB) { * @param {Array} matrix. * @return {Array} result. */ -matrix.multiplyVecMat = function(vec, mat) { +matrix.multiplyVecMat = function (vec, mat) { if (vec.length !== mat.length) { throw new Error("Dimension mismatch"); } @@ -294,7 +292,7 @@ matrix.multiplyVecMat = function(vec, mat) { * @param {Array} vector. * @return {Array} result. */ -matrix.multiplyMatVec = function(mat, vec) { +matrix.multiplyMatVec = function (mat, vec) { if (mat[0].length !== vec.length) { throw new Error("Dimension mismatch"); } @@ -319,7 +317,7 @@ matrix.multiplyMatVec = function(mat, vec) { * @param {Array} matrix. * @return {Array} result. */ -matrix.multiplyMatMat = function(arrA, arrB) { +matrix.multiplyMatMat = function (arrA, arrB) { if (arrA[0].length !== arrB.length) { throw new Error("Dimension mismatch"); } @@ -350,7 +348,7 @@ matrix.multiplyMatMat = function(arrA, arrB) { * @param {Array} matrix / vector. * @return {Array} result. */ -matrix.multiply = function(arrA, arrB) { +matrix.multiply = function (arrA, arrB) { if (arrA[0].length > 1 && arrB[0].length > 1) { return matrix.multiplyMatMat(arrA, arrB); } else if (arrA[0].length > 1) { @@ -367,7 +365,7 @@ matrix.multiply = function(arrA, arrB) { * @param {Array} matrix. * @return {Number} determinant. */ -matrix.determinant = function(m) { +matrix.determinant = function (m) { var numRow = m.length; var numCol = m[0].length; var det = 0; @@ -417,7 +415,7 @@ matrix.determinant = function(m) { * @param {Array} arr * @return {Array} array of matrices [L, U, P] */ -matrix.lupDecomposition = function(arr) { +matrix.lupDecomposition = function (arr) { if (!matrix.isSquare(arr)) { throw new Error(ERROR_MATRIX_NOT_SQUARE); } @@ -429,7 +427,7 @@ matrix.lupDecomposition = function(arr) { var currentRow; var currentColumn = new Array(size); - this.getL = function(a) { + this.getL = function (a) { var m = a[0].length; var L = matrix.identity(m); @@ -444,7 +442,7 @@ matrix.lupDecomposition = function(arr) { return L; }; - this.getU = function(a) { + this.getU = function (a) { var m = a[0].length; var U = matrix.identity(m); @@ -486,7 +484,7 @@ matrix.lupDecomposition = function(arr) { } } - if (pivot != j) { + if (pivot !== j) { LU = matrix.rowSwitch(LU, pivot, j); P = matrix.rowSwitch(P, pivot, j); } @@ -509,7 +507,7 @@ matrix.lupDecomposition = function(arr) { * @param {String} direction - clockwise or counterclockwise. * @return {Array} vector. */ -matrix.rotate = function(point, degree, direction) { +matrix.rotate = function (point, degree, direction) { matrix._check2DVector(point); var negate = direction === 'clockwise' ? -1 : 1; @@ -531,7 +529,7 @@ matrix.rotate = function(point, degree, direction) { * @param {Number} sy. * @return {Array} vector. */ -matrix.scale = function(point, sx, sy) { +matrix.scale = function (point, sx, sy) { matrix._check2DVector(point); var transformation = [ @@ -550,7 +548,7 @@ matrix.scale = function(point, sx, sy) { * @param {String} direction - xaxis or yaxis. * @return {Array} vector. */ -matrix.shear = function(point, k, direction) { +matrix.shear = function (point, k, direction) { matrix._check2DVector(point); var xplaceholder = direction === 'xaxis' ? k : 0; @@ -572,7 +570,7 @@ matrix.shear = function(point, k, direction) { * @param {Number} ty. * @return {Array} vector. */ -matrix.affine = function(point, tx, ty) { +matrix.affine = function (point, tx, ty) { matrix._check2DVector(point); var transformation = [ [1, 0, tx], @@ -602,7 +600,7 @@ matrix.affine = function(point, tx, ty) { * @param {Number} row. * @param {Number} scale. */ -matrix.rowScale = function(m, row, scale) { +matrix.rowScale = function (m, row, scale) { var result = new Array(m.length); for (var i = 0; i < m.length; i++) { @@ -628,7 +626,7 @@ matrix.rowScale = function(m, row, scale) { * @param {Number} row1. * @param {Number} row2. */ -matrix.rowSwitch = function(m, row1, row2) { +matrix.rowSwitch = function (m, row1, row2) { var result = new Array(m.length); for (var i = 0; i < m.length; i++) { @@ -656,7 +654,7 @@ matrix.rowSwitch = function(m, row1, row2) { * @param {Number} row1. * @param {Number} row2. */ -matrix.rowAddMultiple = function(m, from, to, scale) { +matrix.rowAddMultiple = function (m, from, to, scale) { var result = new Array(m.length); for (var i = 0; i < m.length; i++) { @@ -681,10 +679,10 @@ matrix.rowAddMultiple = function(m, from, to, scale) { * @param {Number} epsilon. * @return {Array} RREF matrix. */ -matrix.GaussJordanEliminate = function(m, epsilon) { +matrix.GaussJordanEliminate = function (m, epsilon) { // Translated from: // http://elonen.iki.fi/code/misc-notes/python-gaussj/index.html - var eps = (typeof epsilon == 'undefined') ? 1e-10 : epsilon; + var eps = (typeof epsilon === 'undefined') ? 1e-10 : epsilon; var h = m.length; var w = m[0].length; @@ -749,7 +747,7 @@ matrix.GaussJordanEliminate = function(m, epsilon) { * @param {Number} epsilon. * @return {Array} RREF matrix. */ -matrix.rowReduce = function(m, epsilon) { +matrix.rowReduce = function (m, epsilon) { return matrix.GaussJordanEliminate(m, epsilon); }; @@ -759,7 +757,7 @@ matrix.rowReduce = function(m, epsilon) { * @param {Array} matrix. * @return {Array} inverted matrix. */ -matrix.inverse = function(m) { +matrix.inverse = function (m) { if (!matrix.isSquare(m)) { throw new Error(ERROR_MATRIX_NOT_SQUARE); } @@ -791,7 +789,7 @@ matrix.inverse = function(m) { * @param {Int} column number * @return {Array} column */ -matrix.getCol = function(M, n) { +matrix.getCol = function (M, n) { var result = new Array(M.length); if (n < 0) { throw new Error('The specified column must be a positive integer.'); @@ -811,7 +809,7 @@ matrix.getCol = function(M, n) { * @param {Array} desired re-ordering * @return {Array} reordered matrix */ -matrix.reorderRows = function(M, L) { +matrix.reorderRows = function (M, L) { var result = []; if (L === undefined) { throw new Error('A reordering array must be entered.'); @@ -837,7 +835,7 @@ matrix.reorderRows = function(M, L) { * @param {Array} desired re-ordering * @return {Array} reordered matrix */ -matrix.reorderCols = function(M, L) { +matrix.reorderCols = function (M, L) { var result = []; if (L === undefined) { throw new Error('Please enter a desired reordering array.'); @@ -862,7 +860,7 @@ matrix.reorderCols = function(M, L) { * @param {Array} matrix * @return {Array} reversed matrix */ -matrix.reverseRows = function(M) { +matrix.reverseRows = function (M) { var L = []; for (var i = M.length - 1; i > -1; i--) { L.push(i); @@ -876,7 +874,7 @@ matrix.reverseRows = function(M) { * @param {Array} matrix * @return {Array} reversed matrix */ -matrix.reverseCols = function(M) { +matrix.reverseCols = function (M) { var L = []; for (var i = M.length - 1; i > -1; i--) { L.push(i); @@ -891,7 +889,7 @@ matrix.reverseCols = function(M) { * @param {Int} number of columns * @return {Array} matrix */ -matrix.zeros = function(n, m) { +matrix.zeros = function (n, m) { var M = new Array(n); if (n < 1 || m < 1) { throw new Error('The matrix dimensions must be positive integers.'); @@ -918,7 +916,7 @@ matrix.zeros = function(n, m) { * @param {String} direction (V,H) * @return {Array} zigzag matrix. */ -matrix.zigzag = function(n, point, dir) { +matrix.zigzag = function (n, point, dir) { if (n <= 1) { throw new Error('Matrix size must be at least 2x2.'); } @@ -927,7 +925,7 @@ matrix.zigzag = function(n, point, dir) { //create one kind of permutation - all other permutations can be //created from this particular permutation through transformations - var BRH = function(M) { //starting at bottom right, moving horizontally + var BRH = function (M) { //starting at bottom right, moving horizontally var jump = false, tl = n * n, br = 1, @@ -998,31 +996,31 @@ matrix.zigzag = function(n, point, dir) { return M; }; - var BRV = function(M) { //starting at bottom right, moving vertically + var BRV = function (M) { //starting at bottom right, moving vertically return matrix.transpose(BRH(M)); }; - var BLH = function(M) { //starting at bottom left, moving horizontally + var BLH = function (M) { //starting at bottom left, moving horizontally return matrix.reverseCols(BRH(M)); }; - var BLV = function(M) { //starting at bottom left, moving vertically + var BLV = function (M) { //starting at bottom left, moving vertically return matrix.reverseRows(TLV(BLH(M))); }; - var TRH = function(M) { //starting at top right, moving horizontally + var TRH = function (M) { //starting at top right, moving horizontally return matrix.reverseRows(BRH(M)); }; - var TRV = function(M) { //starting at top right, moving vertically + var TRV = function (M) { //starting at top right, moving vertically return matrix.reverseRows(BRV(M)); }; - var TLH = function(M) { //starting at top left, moving horizontally + var TLH = function (M) { //starting at top left, moving horizontally return matrix.reverseCols(matrix.reverseRows(BRH(M))); }; - var TLV = function(M) { //starting at top left, moving vertically + var TLV = function (M) { //starting at top left, moving vertically return matrix.transpose(TLH(M)); }; @@ -1056,7 +1054,7 @@ matrix.zigzag = function(n, point, dir) { * @param {Number} the value of p (norm order) * @return {Number} the p-norm of v */ -matrix.vectorNorm = function(v, p) { +matrix.vectorNorm = function (v, p) { // calculate the p'th norm of a vector v if (!(Array.isArray(v)) || (v.length === 0)) { throw new Error('Vector must be an array of at least length 1.'); @@ -1071,31 +1069,31 @@ matrix.vectorNorm = function(v, p) { switch (p) { - case Infinity: - for (i = 0; i < n; i++) { - term = Math.abs(v[i]); - if (term > ans) { - ans = term; - } + case Infinity: + for (i = 0; i < n; i++) { + term = Math.abs(v[i]); + if (term > ans) { + ans = term; } - break; - - case -Infinity: - ans = Infinity; - for (i = 0; i < n; i++) { - term = Math.abs(v[i]); - if (term < ans) { - ans = term; - } + } + break; + + case -Infinity: + ans = Infinity; + for (i = 0; i < n; i++) { + term = Math.abs(v[i]); + if (term < ans) { + ans = term; } - break; + } + break; - default: - for (i = 0; i < n; i++) { - ans += Math.pow(Math.abs(v[i]), p); - } - ans = Math.pow(ans, 1 / p); - break; + default: + for (i = 0; i < n; i++) { + ans += Math.pow(Math.abs(v[i]), p); + } + ans = Math.pow(ans, 1 / p); + break; } return ans; @@ -1115,7 +1113,7 @@ matrix.vectorNorm = function(v, p) { * @param {Number} the value of p (norm order) * @return {Number} the p-norm of M */ -matrix.matrixNorm = function(M, p) { +matrix.matrixNorm = function (M, p) { if (!(Array.isArray(M)) || (M.length === 0) || !Array.isArray(M[0])) { throw new Error('Matrix must be an array of at least length 1.'); } else if ((typeof p !== 'undefined') && (typeof p !== 'number') && (p !== null)) { @@ -1131,93 +1129,93 @@ matrix.matrixNorm = function(M, p) { switch (p) { // the largest value when absolute-ing and summing each row - case Infinity: - for (i = 0; i < m; i++) { - term = 0; + case Infinity: + for (i = 0; i < m; i++) { + term = 0; - for (j = 0; j < n; j++) { - term += Math.abs(M[i][j]); - } - - if (term > ans) { - ans = term; - } + for (j = 0; j < n; j++) { + term += Math.abs(M[i][j]); } - break; - // the smallest value when absolute-ing and summing each row - case -Infinity: - ans = Infinity; - for (i = 0; i < m; i++) { - term = 0; + if (term > ans) { + ans = term; + } + } + break; - for (j = 0; j < n; j++) { - term += Math.abs(M[i][j]); - } + // the smallest value when absolute-ing and summing each row + case -Infinity: + ans = Infinity; + for (i = 0; i < m; i++) { + term = 0; - if (term < ans) { - ans = term; - } + for (j = 0; j < n; j++) { + term += Math.abs(M[i][j]); } - break; - // the largest value when absolute-ing and summing each column - case 1: - for (i = 0; i < n; i++) { - term = 0; + if (term < ans) { + ans = term; + } + } + break; - for (j = 0; j < m; j++) { - term += Math.abs(M[j][i]); - } + // the largest value when absolute-ing and summing each column + case 1: + for (i = 0; i < n; i++) { + term = 0; - if (term > ans) { - ans = term; - } + for (j = 0; j < m; j++) { + term += Math.abs(M[j][i]); } - break; - // the smallest value when absolute-ing and summing each column - case -1: - ans = Infinity; - for (i = 0; i < n; i++) { - term = 0; + if (term > ans) { + ans = term; + } + } + break; - for (j = 0; j < m; j++) { - term += Math.abs(M[j][i]); - } + // the smallest value when absolute-ing and summing each column + case -1: + ans = Infinity; + for (i = 0; i < n; i++) { + term = 0; - if (term < ans) { - ans = term; - } + for (j = 0; j < m; j++) { + term += Math.abs(M[j][i]); } - break; - // the Frobenius norm - case null: - for (i = 0; i < m; i++) { - for (j = 0; j < n; j++) { - ans += Math.pow(M[i][j], 2); - } + if (term < ans) { + ans = term; } - ans = Math.pow(ans, 0.5); - break; - - // largest singular value - case 2: - throw new Error("Singular values are not yet supported in numbers.js."); - - // smallest singular value - case -2: - throw new Error("Singular values are not yet supported in numbers.js."); + } + break; - // entry-wise norm; analogous to that of the entry-wise vector norm. - default: - for (i = 0; i < m; i++) { - for (j = 0; j < n; j++) { - ans += Math.pow(Math.abs(M[i][j]), p); - } + // the Frobenius norm + case null: + for (i = 0; i < m; i++) { + for (j = 0; j < n; j++) { + ans += Math.pow(M[i][j], 2); } - ans = Math.pow(ans, 1 / p); + } + ans = Math.pow(ans, 0.5); + break; + + // largest singular value + case 2: + throw new Error("Singular values are not yet supported in numbers.js."); + + // smallest singular value + case -2: + throw new Error("Singular values are not yet supported in numbers.js."); + + // entry-wise norm; analogous to that of the entry-wise vector norm. + default: + for (i = 0; i < m; i++) { + for (j = 0; j < n; j++) { + ans += Math.pow(Math.abs(M[i][j]), p); + } + } + ans = Math.pow(ans, 1 / p); } @@ -1231,7 +1229,7 @@ matrix.matrixNorm = function(M, p) { * @param {Number} upper bandwidth * @return {Boolean} true if upper bandwidth is q; false otherwise */ -matrix.isUpperBand = function(M, q) { +matrix.isUpperBand = function (M, q) { if (!Array.isArray(M) || !Array.isArray(M[0]) || M.length < 2) { throw new Error('Matrix must be an array of at least dimension 2.'); } else if (typeof q !== 'number' || q < 0 || (q % 1) !== 0) { @@ -1258,7 +1256,7 @@ matrix.isUpperBand = function(M, q) { * @param {Number} lower bandwidth * @return {Boolean} true if lower bandwidth is p; false otherwise */ -matrix.isLowerBand = function(M, p) { +matrix.isLowerBand = function (M, p) { if (!Array.isArray(M) || !Array.isArray(M[0]) || M.length < 2) { throw new Error('Matrix must be an array of at least dimension 2.'); } else if (typeof p !== 'number' || p < 0 || (p % 1) !== 0) { @@ -1287,7 +1285,7 @@ matrix.isLowerBand = function(M, p) { * @param {Int} index of element to ignore. * @return {Number} sum. */ -var sumNondiagonalElements = function(arr, i) { +var sumNondiagonalElements = function (arr, i) { var sum = 0, j; @@ -1306,7 +1304,7 @@ var sumNondiagonalElements = function(arr, i) { * @param {Array} matrix * @return {Boolean} true if so, false otherwise. */ -matrix.isRowDD = function(M) { +matrix.isRowDD = function (M) { var n = M.length; if (!matrix.isSquare(M)) { throw new Error(ERROR_MATRIX_NOT_SQUARE); @@ -1330,7 +1328,7 @@ matrix.isRowDD = function(M) { * @param {Array} matrix * @return {Boolean} true if so, false otherwise. */ -matrix.isStrictlyRowDD = function(M) { +matrix.isStrictlyRowDD = function (M) { if (!matrix.isSquare(M)) { throw new Error(ERROR_MATRIX_NOT_SQUARE); } @@ -1355,7 +1353,7 @@ matrix.isStrictlyRowDD = function(M) { * @param {Array} matrix * @return {Boolean} true if so, false otherwise. */ -matrix.isColumnDD = function(M) { +matrix.isColumnDD = function (M) { if (!matrix.isSquare) { throw new Error(ERROR_MATRIX_NOT_SQUARE); } @@ -1380,7 +1378,7 @@ matrix.isColumnDD = function(M) { * @param {Array} matrix * @return {Boolean} true if so, false otherwise. */ -matrix.isStrictlyColumnDD = function(M) { +matrix.isStrictlyColumnDD = function (M) { if (!matrix.isSquare(M)) { throw new Error(ERROR_MATRIX_NOT_SQUARE); } diff --git a/lib/numbers/prime.js b/lib/numbers/prime.js index 8034256..5a1762d 100644 --- a/lib/numbers/prime.js +++ b/lib/numbers/prime.js @@ -22,28 +22,28 @@ var basic = require('./basic'); var prime = exports; /** - * Determine if number is prime. + * Determine if number is prime. * Adopted from http://www.javascripter.net/faq/numberisprime.htm * * @param {Number} number to evaluate. * @return {Boolean} return true if value is prime. false otherwise. */ prime.simple = function (n) { - if (isNaN(n) || !isFinite(n) || n % 1 || n < 2) { - return false; - } - if (n % 2 === 0){ - return (n === 2); - } - if (n % 3 === 0){ - return (n === 3); - } - for (var i = 5, m = Math.sqrt(n); i <= m; i += 6) { - if ((n % i === 0) || (n % (i + 2) === 0)){ - return false; - } + if (isNaN(n) || !isFinite(n) || n % 1 || n < 2) { + return false; + } + if (n % 2 === 0) { + return (n === 2); + } + if (n % 3 === 0) { + return (n === 3); + } + for (var i = 5, m = Math.sqrt(n); i <= m; i += 6) { + if ((n % i === 0) || (n % (i + 2) === 0)) { + return false; } - return true; + } + return true; }; /** * Returns the prime factors of a number. @@ -61,15 +61,17 @@ prime.factorization = function (num) { var x; var sqrt = Math.sqrt; var doLoop = 1 < num && isFinite(num); - + while (doLoop) { root = sqrt(num); x = 2; if (num % x) { x = 3; - while ((num % x) && ((x += 2) < root)) {} + while ((num % x) && ((x += 2) < root)) { + continue; + } } - + x = (root < x) ? num : x; factors.push(x); doLoop = (x !== num); @@ -80,14 +82,14 @@ prime.factorization = function (num) { }; /** - * Determine if a number is prime in Polynomial time, using a randomized algorithm. + * Determine if a number is prime in Polynomial time, using a randomized algorithm. * http://en.wikipedia.org/wiki/Miller-Rabin_primality_test * * @param {Number} number to Evaluate. * @param {Number} number to Determine accuracy rate (number of trials) default value = 20. * @return {Boolean} return true if value is prime. false otherwise. */ -prime.millerRabin = function(n, k) { +prime.millerRabin = function (n, k) { if (arguments.length === 1) k = 20; if (n === 2) return true; if (!basic.isInt(n) || n <= 1 || n % 2 === 0) return false; @@ -108,11 +110,11 @@ prime.millerRabin = function(n, k) { var tryComposite = function (a) { if (basic.powerMod(a, d, n) === 1) return false; - - for (var i = 0; i < s; i ++) { + + for (var i = 0; i < s; i++) { if (basic.powerMod(a, Math.pow(2, i) * d, n) === n - 1) return false; } - + return true; }; @@ -129,15 +131,15 @@ prime.millerRabin = function(n, k) { * * @param {Number} upper limit of test n. * @return {Array} list of values that are prime up to n. - */ + */ prime.sieve = function (n) { if (n < 2) return []; var result = [2]; for (var i = 3; i <= n; i++) { var notMultiple = false; - - for (var j in result) { - notMultiple = notMultiple || (0 === i % result[j]); + + for (var j in result) { + notMultiple = notMultiple || (0 === i % result[j]); } if (!notMultiple) { @@ -168,7 +170,7 @@ prime.coprime = function (a, b) { * @param {Number} value in question * @return {Array|Boolean} [m, k] if it is a perfect power, false otherwise */ -prime.getPerfectPower = function(n) { +prime.getPerfectPower = function (n) { var test = prime.getPrimePower(n); if (test && test[1] > 1) return test; return false; @@ -181,24 +183,25 @@ prime.getPerfectPower = function(n) { * @param {Number} value in question * @return {Array|Boolean} if it is a prime power, return [prime, power]. */ -prime.getPrimePower = function(n) { +prime.getPrimePower = function (n) { if (n < 2) return false; - if (prime.millerRabin(n)) return [n, 1]; + if (prime.millerRabin(n)) return [n, 1]; if (n % 2 === 0) return [2, n.toString(2).length - 1]; var factors = prime.factorization(n); if (!factors) return false; - + var len = factors.length; - + for (var i = 0; i < len; i++) { - var t = 0, p = 0; + var t = 0, + p = 0; while (t <= n) { t = Math.pow(factors[i], p); if (t / n === 1) return [factors[i], p]; - p++; + p++; } } diff --git a/lib/numbers/random.js b/lib/numbers/random.js index 3ada61c..598145c 100644 --- a/lib/numbers/random.js +++ b/lib/numbers/random.js @@ -1,4 +1,3 @@ -var basic = require('./basic'); var random = exports; // random number generator. @@ -9,8 +8,8 @@ var rGen = Math.random; * * @param {Function} Random number generator */ -random.setGenerator = function(fn){ - if(typeof fn !== "function"){ +random.setGenerator = function (fn) { + if (typeof fn !== "function") { throw new Error("Must pass a function"); } rGen = fn; @@ -28,7 +27,7 @@ random.sample = function (lower, upper, n) { var sample = []; sample.length = n; - for (var i=0; i 1); - var c = Math.sqrt(-2 * Math.log(s)/s), - x = u * c, - y = v * c; + var c = Math.sqrt(-2 * Math.log(s) / s), + x = u * c, + y = v * c; x = mu + x * sigma; y = mu + y * sigma; return [x, y]; @@ -73,7 +72,7 @@ random.boxMullerTransform = function(mu, sigma) { * @param {Number} number to subtract * @return {Number} random number along an irwin hall distribution. */ -random.irwinHall = function(n, sub) { +random.irwinHall = function (n, sub) { if (arguments.length === 1) sub = 0; var sum = 0; for (var i = 0; i < n; i++) sum += rGen(); @@ -89,12 +88,12 @@ random.irwinHall = function(n, sub) { * @param {Number} random minimum value (default is 0) * @return {Number} random number along an bates distribution. */ -random.bates = function(n, b, a) { +random.bates = function (n, b, a) { if (arguments.length <= 2) a = 0; if (arguments.length === 1) b = 1; var sum = 0; - for (var i = 0; i < n; i++) sum += (b - a)*rGen() + a; - return sum/n; + for (var i = 0; i < n; i++) sum += (b - a) * rGen() + a; + return sum / n; }; random.distribution = {}; @@ -107,7 +106,7 @@ random.distribution = {}; * @param {Number} sigma or standard deviation * @return {Array} array of size n of a normal distribution */ -random.distribution.normal = function(n, mu, sigma) { +random.distribution.normal = function (n, mu, sigma) { if (arguments.length <= 2) sigma = 1; if (arguments.length === 1) mu = 0; @@ -122,11 +121,11 @@ random.distribution.normal = function(n, mu, sigma) { * @param {Number} sigma or standard deviation * @return {Array} array of size n of a log normal distribution */ -random.distribution.logNormal = function(n, mu, sigma) { +random.distribution.logNormal = function (n, mu, sigma) { if (arguments.length <= 2) sigma = 1; if (arguments.length === 1) mu = 0; - var exponential = function(x) { + var exponential = function (x) { return Math.exp(x); }; @@ -144,7 +143,7 @@ random.distribution.logNormal = function(n, mu, sigma) { * @param {Number} determine if the distribution will be polar coordinates. * @return {Array} array of size n of a normal distribution */ -random.distribution.boxMuller = function(n, mu, sigma, rc) { +random.distribution.boxMuller = function (n, mu, sigma, rc) { if (arguments.length <= 3) rc = false; if (arguments.length <= 2) sigma = 1; if (arguments.length === 1) mu = 0; @@ -167,7 +166,7 @@ random.distribution.boxMuller = function(n, mu, sigma, rc) { * @param {Number} irwinHall subtraction value (default is 0) * @return {Array} irwin hall distribution from [a, b] */ -random.distribution.irwinHall = function(n, m, sub) { +random.distribution.irwinHall = function (n, m, sub) { if (arguments.length <= 2) sub = 0; if (arguments.length === 1) m = n; var results = new Array(n); @@ -187,7 +186,7 @@ random.distribution.irwinHall = function(n, m, sub) { * @param {Number} length of array * @return {Array} an array of an approximate normal distribution from [-6, 6] of length n. */ -random.distribution.irwinHallNormal = function(n) { +random.distribution.irwinHallNormal = function (n) { return random.distribution.irwinHall(n, 12, 6); }; @@ -200,7 +199,7 @@ random.distribution.irwinHallNormal = function(n) { * @param {Number} minimum bound a (default is 0) * @return {Array} bates distribution from [a, b] */ -random.distribution.bates = function(n, b, a) { +random.distribution.bates = function (n, b, a) { if (arguments.length <= 2) a = 0; if (arguments.length === 1) b = n; diff --git a/lib/numbers/statistic.js b/lib/numbers/statistic.js index a1ee411..e2fcc93 100644 --- a/lib/numbers/statistic.js +++ b/lib/numbers/statistic.js @@ -91,7 +91,9 @@ statistic.quantile = function (arr, k, q) { if (k === q) return Math.max.apply(null, arr); sorted = arr.slice(0); - sorted.sort(function (a, b) { return a - b; }); + sorted.sort(function (a, b) { + return a - b; + }); count = sorted.length; index = count * k / q; @@ -106,7 +108,7 @@ statistic.quantile = function (arr, k, q) { * * @return {Object} summary statistics. */ -statistic.report = function(array) { +statistic.report = function (array) { return { mean: statistic.mean(array), firstQuartile: statistic.quantile(array, 1, 4), @@ -128,7 +130,7 @@ statistic.standardDev = function (arr) { var squaredArr = []; for (var i = 0; i < arr.length; i++) { - squaredArr[i] = Math.pow((arr[i] - mean),2); + squaredArr[i] = Math.pow((arr[i] - mean), 2); } return Math.sqrt((1 / count) * basic.sum(squaredArr)); @@ -141,7 +143,7 @@ statistic.standardDev = function (arr) { * @return {Number} correlation. */ statistic.correlation = function (arrX, arrY) { - if (arrX.length == arrY.length) { + if (arrX.length === arrY.length) { var covarXY = statistic.covariance(arrX, arrY); var stdDevX = statistic.standardDev(arrX); var stdDevY = statistic.standardDev(arrY); @@ -160,7 +162,7 @@ statistic.correlation = function (arrX, arrY) { * @return {Number} A number between 0 and 1.0 that represents how well the regression line fits the data. */ statistic.rSquared = function (source, regression) { - var residualSumOfSquares = basic.sum(source.map(function (d,i) { + var residualSumOfSquares = basic.sum(source.map(function (d, i) { return basic.square(d - regression[i]); })); @@ -179,22 +181,26 @@ statistic.rSquared = function (source, regression) { */ statistic.exponentialRegression = function (arrY) { var n = arrY.length; - var arrX = basic.range(1,n); + var arrX = basic.range(1, n); var xSum = basic.sum(arrX); - var ySum = basic.sum(arrY); - var yMean = statistic.mean(arrY); - var yLog = arrY.map(function (d) { return Math.log(d); }); - var xSquared = arrX.map(function (d) { return d * d; }); + var yLog = arrY.map(function (d) { + return Math.log(d); + }); + var xSquared = arrX.map(function (d) { + return d * d; + }); var xSquaredSum = basic.sum(xSquared); var yLogSum = basic.sum(yLog); - var xyLog = arrX.map(function (d, i) { return d * yLog[i]; }); + var xyLog = arrX.map(function (d, i) { + return d * yLog[i]; + }); var xyLogSum = basic.sum(xyLog); var a = (yLogSum * xSquaredSum - xSum * xyLogSum) / (n * xSquaredSum - (xSum * xSum)); var b = (n * xyLogSum - xSum * yLogSum) / (n * xSquaredSum - (xSum * xSum)); - var fn = function(x) { + var fn = function (x) { if (typeof x === 'number') { return Math.exp(a) * Math.exp(b * x); } else { @@ -220,14 +226,18 @@ statistic.linearRegression = function (arrX, arrY) { var n = arrX.length; var xSum = basic.sum(arrX); var ySum = basic.sum(arrY); - var xySum = basic.sum(arrX.map(function (d, i) { return d * arrY[i]; })); - var xSquaredSum = basic.sum(arrX.map(function (d) { return d * d; })); + var xySum = basic.sum(arrX.map(function (d, i) { + return d * arrY[i]; + })); + var xSquaredSum = basic.sum(arrX.map(function (d) { + return d * d; + })); var xMean = statistic.mean(arrX); var yMean = statistic.mean(arrY); var b = (xySum - 1 / n * xSum * ySum) / (xSquaredSum - 1 / n * (xSum * xSum)); var a = yMean - b * xMean; - return function(x) { + return function (x) { if (typeof x === 'number') { return a + b * x; } else { @@ -245,8 +255,8 @@ statistic.linearRegression = function (arrX, arrY) { * @param {Array} set 2 of values. * @return {Number} covariance. */ - statistic.covariance = function (set1, set2) { - if (set1.length == set2.length) { +statistic.covariance = function (set1, set2) { + if (set1.length === set2.length) { var n = set1.length; var total = 0; var sum1 = basic.sum(set1); diff --git a/src/numbers.js b/src/numbers.js old mode 100755 new mode 100644 index 47ede7e..f9cd5a9 --- a/src/numbers.js +++ b/src/numbers.js @@ -81,8 +81,8 @@ var basic = exports; basic.sum = function (arr) { if (Object.prototype.toString.call(arr) === '[object Array]') { var total = 0; - for (var i = 0 ; i < arr.length ; i++) { - if (typeof(arr[i]) === 'number') { + for (var i = 0; i < arr.length; i++) { + if (typeof (arr[i]) === 'number') { total = total + arr[i]; } else { throw new Error('All elements in array must be numbers'); @@ -105,11 +105,11 @@ basic.sum = function (arr) { basic.subtraction = function (arr) { if (Object.prototype.toString.call(arr) === '[object Array]') { var total = arr[0]; - if (typeof(total) !== 'number') { + if (typeof (total) !== 'number') { throw new Error('All elements in array must be numbers'); } for (var i = 1, length = arr.length; i < length; i++) { - if (typeof(arr[i]) === 'number') { + if (typeof (arr[i]) === 'number') { total -= arr[i]; } else { throw new Error('All elements in array must be numbers'); @@ -130,11 +130,11 @@ basic.subtraction = function (arr) { basic.product = function (arr) { if (Object.prototype.toString.call(arr) === '[object Array]') { var total = arr[0]; - if (typeof(total) !== 'number') { + if (typeof (total) !== 'number') { throw new Error('All elements in array must be numbers'); } for (var i = 1, length = arr.length; i < length; i++) { - if (typeof(arr[i]) === 'number') { + if (typeof (arr[i]) === 'number') { total = total * arr[i]; } else { throw new Error('All elements in array must be numbers'); @@ -153,12 +153,12 @@ basic.product = function (arr) { * @return {Number} square of number */ basic.square = function (num) { - if (typeof(num) !== 'number') { + if (typeof (num) !== 'number') { throw new Error('Input must be a number.'); } else { - return num * num; + return num * num; } - + }; /** @@ -172,7 +172,10 @@ basic.binomial = function (n, k) { var arr = []; - function _binomial (n, k) { + function _binomial(n, k) { + if (typeof (n) !== 'number' && typeof (k) !== 'number') { + throw new Error('Input must be a number.'); + } if (n >= 0 && k === 0) return 1; if (n === 0 && k > 0) return 0; if (arr[n] && arr[n][k] > 0) return arr[n][k]; @@ -191,9 +194,12 @@ basic.binomial = function (n, k) { * @param {Number} integer. * @return {Number} result. */ -basic.factorial = function (num){ - var i = 2, o = 1; - +basic.factorial = function (num) { + if (typeof (num) !== 'number') throw new Error("Input must be a number."); + if (num < 0) throw new Error("Input must not be negative."); + var i = 2, + o = 1; + while (i <= num) { o *= i++; } @@ -203,7 +209,7 @@ basic.factorial = function (num){ /** * Calculate the greastest common divisor amongst two integers. - * + * * @param {Number} number A. * @param {Number} number B. * @return {Number} greatest common divisor for integers A, B. @@ -252,18 +258,19 @@ basic.lcm = function (num1, num2) { * @return {Array} random elements. */ basic.random = function (arr, quant, allowDuplicates) { - if (arr.length === 0){ + if (arr.length === 0) { throw new Error('Empty array'); - } else if (quant > arr.length && !allowDuplicates){ + } else if (quant > arr.length && !allowDuplicates) { throw new Error('Quantity requested exceeds size of array'); } - + if (allowDuplicates === true) { - var result = [], i; + var result = [], + i; for (i = 0; i < quant; i++) { result[i] = arr[Math.floor(Math.random() * arr.length)]; } - return result; + return result; } else { return basic.shuffle(arr).slice(0, quant); } @@ -276,7 +283,8 @@ basic.random = function (arr, quant, allowDuplicates) { * @return {Array} shuffled array. */ basic.shuffle = function (array) { - var m = array.length, t, i; + var m = array.length, + t, i; while (m) { i = Math.floor(Math.random() * m--); @@ -299,14 +307,15 @@ basic.max = function (arr) { if (!Array.isArray(arr)) { throw new Error("Input must be of type Array"); } - var max = -Infinity, val; + var max = -Infinity, + val; for (var i = 0, len = arr.length; i < len; i++) { val = +arr[i]; if (max < val) { max = val; } // Math.max() returns NaN if one of the elements is not a number. - if( val !== val ){ + if (val !== val) { return NaN; } } @@ -323,14 +332,15 @@ basic.min = function (arr) { if (!Array.isArray(arr)) { throw new Error("Input must be of type Array"); } - var min = +Infinity, val; + var min = +Infinity, + val; for (var i = 0, len = arr.length; i < len; i++) { val = +arr[i]; if (val < min) { min = val; } // Math.min() returns NaN if one of the elements is not a number. - if( val !== val ){ + if (val !== val) { return NaN; } } @@ -346,7 +356,8 @@ basic.min = function (arr) { * @return {Array} An array containing numbers within the range. */ basic.range = function (start, stop, step) { - var array, i = 0, len; + var array, i = 0, + len; if (arguments.length <= 1) { stop = start || 0; @@ -372,41 +383,43 @@ basic.range = function (start, stop, step) { }; /** - * Determine if the number is an integer. - * - * @param {Number} the number - * @return {Boolean} true for int, false for not int. - */ + * Determine if the number is an integer. + * + * @param {Number} the number + * @return {Boolean} true for int, false for not int. + */ basic.isInt = function (n) { return n % 1 === 0; }; /** - * Calculate the divisor and modulus of two integers. - * - * @param {Number} int a. - * @param {Number} int b. - * @return {Array} [div, mod]. - */ + * Calculate the divisor and modulus of two integers. + * + * @param {Number} int a. + * @param {Number} int b. + * @return {Array} [div, mod]. + */ basic.divMod = function (a, b) { - if (!basic.isInt(a) || !basic.isInt(b)) return false; + if (b <= 0) throw new Error("b cannot be zero. Undefined."); + if (!basic.isInt(a) || !basic.isInt(b)) throw new Error("A or B are not integers."); return [Math.floor(a / b), a % b]; }; /** - * Calculate: - * if b >= 1: a^b mod m. - * if b = -1: modInverse(a, m). - * if b < 1: finds a modular rth root of a such that b = 1/r. - * - * @param {Number} Number a. - * @param {Number} Number b. - * @param {Number} Modulo m. - * @return {Number} see the above documentation for return values. - */ + * Calculate: + * if b >= 1: a^b mod m. + * if b = -1: modInverse(a, m). + * if b < 1: finds a modular rth root of a such that b = 1/r. + * + * @param {Number} Number a. + * @param {Number} Number b. + * @param {Number} Modulo m. + * @return {Number} see the above documentation for return values. + */ basic.powerMod = function (a, b, m) { + if (typeof (a) !== 'number' || typeof (b) !== 'number' || typeof (m) !== 'number') throw new Error("Inputs must be numbers."); // If b < -1 should be a small number, this method should work for now. - if (b < -1) return Math.pow(a, b) % m; + if (b < -1) return Math.pow(a, b) % m; if (b === 0) return 1 % m; if (b >= 1) { var result = 1; @@ -414,7 +427,7 @@ basic.powerMod = function (a, b, m) { if ((b % 2) === 1) { result = (result * a) % m; } - + a = (a * a) % m; b = b >> 1; } @@ -423,7 +436,7 @@ basic.powerMod = function (a, b, m) { if (b === -1) return basic.modInverse(a, m); if (b < 1) { - return basic.powerMod(a, Math.pow(b, -1), m); + return basic.powerMod(a, Math.pow(b, -1), m); } }; @@ -450,20 +463,20 @@ basic.egcd = function (a, b) { throw new Error("Can only operate on integers"); } var signX = (a < 0) ? -1 : 1, - signY = (b < 0) ? -1 : 1, - x = 0, - y = 1, - oldX = 1, - oldY = 0, - q, r, m, n; - a = Math.abs(a); - b = Math.abs(b); - - while(a !== 0){ - q = Math.floor(b/a); + signY = (b < 0) ? -1 : 1, + x = 0, + y = 1, + oldX = 1, + oldY = 0, + q, r, m, n; + a = Math.abs(a); + b = Math.abs(b); + + while (a !== 0) { + q = Math.floor(b / a); r = b % a; - m = x - oldX*q; - n = y - oldY*q; + m = x - oldX * q; + n = y - oldY * q; b = a; a = r; x = oldX; @@ -471,18 +484,18 @@ basic.egcd = function (a, b) { oldX = m; oldY = n; } - return [b, signX*x, signY*y]; + return [b, signX * x, signY * y]; }; /** - * Calculate the modular inverse of a number. - * - * @param {Number} Number a. - * @param {Number} Modulo m. - * @return {Number} if true, return number, else throw error. - */ + * Calculate the modular inverse of a number. + * + * @param {Number} Number a. + * @param {Number} Modulo m. + * @return {Number} if true, return number, else throw error. + */ basic.modInverse = function (a, m) { var r = basic.egcd(a, m); - if (r[0] != 1) throw new Error('No modular inverse exists'); + if (r[0] !== 1) throw new Error('No modular inverse exists'); return r[1] % m; }; @@ -494,7 +507,8 @@ basic.modInverse = function (a, m) { * @param {Number} second number. * @param {Number} epsilon. */ -basic.numbersEqual = function(first, second, epsilon) { +basic.numbersEqual = function (first, second, epsilon) { + if (typeof (first) !== 'number' || typeof (second) !== 'number' || typeof (epsilon) !== 'number') throw new Error("First and Second must be numbers."); return (first - second) < epsilon && (first - second) > -epsilon; }; @@ -507,19 +521,44 @@ basic.numbersEqual = function(first, second, epsilon) { * @param {Number} Steps to fall * @returns {Number} Result */ -basic.fallingFactorial = function(n, k) { - var i = (n-k+1), r = 1; - - if(n<0) { throw new Error("n cannot be negative"); } - if(k>n) { return 0; } - - while(i <= n) { +basic.fallingFactorial = function (n, k) { + var i = (n - k + 1), + r = 1; + + if (n < 0) { + throw new Error("n cannot be negative."); + } + if (k > n) { + throw new Error("k cannot be greater than n."); + } + + while (i <= n) { r *= i++; } return r; }; +/** + * Calculate the permutation (n choose k) + * + * @param {Number} available choices + * @param {Number} number chosen + * @return {Number} number of ordered variations + */ + +basic.permutation = function (n, k) { + if (n <= 0) { + throw new Error("n cannot be less than or equal to 0."); + } + if (n < k) { + throw new Error("k cannot be greater than k."); + } + var binomial = basic.binomial(n, k); + var permutation = binomial * basic.factorial(k); + return permutation; +}; + },{}],4:[function(require,module,exports){ /** * calculus.js @@ -567,7 +606,7 @@ calculus.pointDiff = function (func, point) { * @param {Number} point to initiate evaluation. * @param {Number} point to complete evaluation. * @param {Number} quantity of divisions. - * @param {Function} (Optional) Function that returns which value + * @param {Function} (Optional) Function that returns which value * to sample on each interval; if none is provided, left endpoints * will be used. * @return {Number} result. @@ -576,7 +615,7 @@ calculus.Riemann = function (func, start, finish, n, sampler) { var inc = (finish - start) / n; var totalHeight = 0; var i; - + if (typeof sampler === 'function') { for (i = start; i < finish; i += inc) { totalHeight += func(sampler(i, i + inc)); @@ -586,7 +625,7 @@ calculus.Riemann = function (func, start, finish, n, sampler) { totalHeight += func(i); } } - + return totalHeight * inc; }; @@ -599,7 +638,7 @@ calculus.Riemann = function (func, start, finish, n, sampler) { * @param {Number} point to complete evaluation. * @return {Number} evaluation. */ -function SimpsonDef (func, a, b) { +function SimpsonDef(func, a, b) { var c = (a + b) / 2; var d = Math.abs(b - a) / 6; return d * (func(a) + 4 * func(c) + func(b)); @@ -617,11 +656,11 @@ function SimpsonDef (func, a, b) { * @param {Number} Error bound (epsilon). * @return {Number} recursive evaluation of left and right side. */ -function SimpsonRecursive (func, a, b, whole, eps) { +function SimpsonRecursive(func, a, b, whole, eps) { var c = a + b; var left = SimpsonDef(func, a, c); var right = SimpsonDef(func, c, b); - + if (Math.abs(left + right - whole) <= 15 * eps) { return left + right + (left + right - whole) / 15; } else { @@ -635,7 +674,7 @@ function SimpsonRecursive (func, a, b, whole, eps) { * @param {Function} math function to be evaluated. * @param {Number} point to initiate evaluation. * @param {Number} point to complete evaluation. - * @param {Number} Optional error bound (epsilon); + * @param {Number} Optional error bound (epsilon); * global error bound will be used as a fallback. * @return {Number} area underneath curve. */ @@ -685,17 +724,16 @@ calculus.StirlingGamma = function (num) { calculus.LanczosGamma = function (num) { var p = [ 0.99999999999980993, 676.5203681218851, -1259.1392167224028, - 771.32342877765313, -176.61502916214059, 12.507343278686905, - -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7 + 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7 ]; var i; var g = 7; - if(num < 0.5) return Math.PI / (Math.sin(Math.PI * num) * calculus.LanczosGamma(1 - num)); + if (num < 0.5) return Math.PI / (Math.sin(Math.PI * num) * calculus.LanczosGamma(1 - num)); num -= 1; - + var a = p[0]; var t = num + g + 0.5; @@ -708,9 +746,9 @@ calculus.LanczosGamma = function (num) { /** - * Calculate the integral of f(x1,x2,...) over intervals + * Calculate the integral of f(x1,x2,...) over intervals * [a1,b1], [a2,b2], ..., using the montecarlo method: - * + * * integral of f(x,y) = (1/N)*(b2-a2)*(b1-a1)*sum(f) * * where N = number of points for f to be evaluated at. @@ -722,7 +760,7 @@ calculus.LanczosGamma = function (num) { * @param {Array(s)} intervals * @return {Number} approximation to integral */ -calculus.MonteCarlo = function(func, N) { +calculus.MonteCarlo = function (func, N) { //takes an arbitrary number of arguments after N //all of the arguments must be arrays which are intervals if (arguments.length < 2) { @@ -732,26 +770,31 @@ calculus.MonteCarlo = function(func, N) { } var L = []; N = Math.ceil(N); - for (var i=2; i 0) { @@ -1075,7 +1119,7 @@ generate.fibonacci = function (n) { n = Math.floor(n / 2); bits.push(bit); } - + return bits.reverse(); }; @@ -1084,7 +1128,7 @@ generate.fibonacci = function (n) { var c = 1; var system = bitSystem(n); var temp; - + for (var i = 0; i < system.length; i++) { var bit = system[i]; if (bit) { @@ -1112,7 +1156,7 @@ generate.fibonacci = function (n) { */ generate.collatz = function (n, result) { result.push(n); - + if (n === 1) { return; } else if (n % 2 === 0) { @@ -1146,7 +1190,7 @@ generate.collatz = function (n, result) { var matrix = exports; var ERROR_MATRIX_NOT_SQUARE = 'Matrix must be square.', - ERROR_VECTOR_NOT_2D = 'Only two dimensional operations are supported at this time.'; + ERROR_VECTOR_NOT_2D = 'Only two dimensional operations are supported at this time.'; /** * Check to see if a point is 2D. Used in all 2D vector functions. @@ -1155,7 +1199,7 @@ var ERROR_MATRIX_NOT_SQUARE = 'Matrix must be square.', * @param {Array} point in question. * @return {undefined} nothing is returned. */ -matrix._check2DVector = function(point) { +matrix._check2DVector = function (point) { if (point.length !== 2) { throw new Error(ERROR_VECTOR_NOT_2D); } @@ -1167,7 +1211,7 @@ matrix._check2DVector = function(point) { * @param {Array} matrix to copy. * @return {Array} copied matrix. */ -matrix.deepCopy = function(arr) { +matrix.deepCopy = function (arr) { if (!Array.isArray(arr)) { throw new Error('Input must be a matrix.'); } else if (arr[0][0] === undefined) { @@ -1178,7 +1222,7 @@ matrix.deepCopy = function(arr) { for (var i = 0; i < arr.length; i++) { result[i] = arr[i].slice(); } - + return result; }; @@ -1186,9 +1230,9 @@ matrix.deepCopy = function(arr) { * Return true if matrix is square, false otherwise. * * @param {Array} arr - * @return {Boolean} + * @return {Boolean} */ -matrix.isSquare = function(arr) { +matrix.isSquare = function (arr) { if (!Array.isArray(arr)) { throw new Error('Input must be a matrix.'); } else if (arr[0][0] === undefined) { @@ -1212,12 +1256,12 @@ matrix.isSquare = function(arr) { */ matrix.addition = function (arrA, arrB) { if (arrA.length !== arrB.length || arrA[0].length !== arrB[0].length) { - throw new Error('Matrix mismatch'); + throw new Error('Dimension mismatch'); } var result = new Array(arrA.length), - i; - + i; + if (!arrA[0].length) { // The arrays are vectors. for (i = 0; i < arrA.length; i++) { @@ -1225,11 +1269,11 @@ matrix.addition = function (arrA, arrB) { } } else { for (i = 0; i < arrA.length; i++) { - result[i] = new Array(arrA[i].length); - - for (var j = 0; j < arrA[i].length; j++) { - result[i][j] = arrA[i][j] + arrB[i][j]; - } + result[i] = new Array(arrA[i].length); + + for (var j = 0; j < arrA[i].length; j++) { + result[i][j] = arrA[i][j] + arrB[i][j]; + } } } @@ -1245,12 +1289,12 @@ matrix.addition = function (arrA, arrB) { */ matrix.subtraction = function (arrA, arrB) { if (arrA.length !== arrB.length || arrA[0].length !== arrB[0].length) { - throw new Error("Matrix mismatch"); + throw new Error("Dimension mismatch"); } var result = new Array(arrA.length), - i; - + i; + if (!arrA[0].length) { // The arrays are vectors. for (i = 0; i < arrA.length; i++) { @@ -1258,11 +1302,11 @@ matrix.subtraction = function (arrA, arrB) { } } else { for (i = 0; i < arrA.length; i++) { - result[i] = new Array(arrA[i].length); - - for (var j = 0; j < arrA[i].length; j++) { - result[i][j] = arrA[i][j] - arrB[i][j]; - } + result[i] = new Array(arrA[i].length); + + for (var j = 0; j < arrA[i].length; j++) { + result[i][j] = arrA[i][j] - arrB[i][j]; + } } } @@ -1286,18 +1330,12 @@ matrix.scalar = function (arr, val) { return arr; }; -/** - * Transpose a matrix. - * - * @param {Array} matrix. - * @return {Array} transposed matrix. - */ -matrix.transpose = function (arr) { +matrix.transposeMatrix = function (arr) { var result = new Array(arr[0].length); - + for (var i = 0; i < arr[0].length; i++) { result[i] = new Array(arr.length); - + for (var j = 0; j < arr.length; j++) { result[i][j] = arr[j][i]; } @@ -1306,6 +1344,50 @@ matrix.transpose = function (arr) { return result; }; +/** + * Transpose a row vector. + * + * @param {Array} row vector. + * @return {Array} transposed row vector (column vector). + */ +matrix.transposeRowVector = function (arr) { + var result = new Array(arr.length); + for (var i = 0; i < arr.length; i++) { + result[i] = [arr[i]]; + } + return result; +}; + +/** + * Transpose a column vector. + * + * @param {Array} column vector. + * @return {Array} transposed column vector (row vector). + */ +matrix.transposeColumnVector = function (arr) { + var result = new Array(arr.length); + for (var i = 0; i < arr.length; i++) { + result[i] = arr[i][0]; + } + return result; +}; + +/** + * Transpose a matrix. + * + * @param {Array} matrix. + * @return {Array} transposed matrix. + */ +matrix.transpose = function (arr) { + if (arr[0].length > 1) { + return matrix.transposeMatrix(arr); + } else if (arr[0].length) { + return matrix.transposeColumnVector(arr); + } else { + return matrix.transposeRowVector(arr); + } +}; + /** * Create an identity matrix of dimension n x n. * @@ -1314,8 +1396,8 @@ matrix.transpose = function (arr) { */ matrix.identity = function (n) { var result = new Array(n); - - for (var i = 0; i < n ; i++) { + + for (var i = 0; i < n; i++) { result[i] = new Array(n); for (var j = 0; j < n; j++) { result[i][j] = (i === j) ? 1 : 0; @@ -1345,39 +1427,109 @@ matrix.dotproduct = function (vectorA, vectorB) { }; /** - * Multiply two matrices. They must abide by standard matching. + * Perform vector-matrix multiplication. + * + * e.g. A x B = (m x n) x (n x m), where n, m are integers who define + * the dimensions of vector A, matrix B. + * + * @param {Array} vector. + * @param {Array} matrix. + * @return {Array} result. + */ +matrix.multiplyVecMat = function (vec, mat) { + if (vec.length !== mat.length) { + throw new Error("Dimension mismatch"); + } + + var result = new Array(mat[0].length); + + var mat_T = matrix.transposeMatrix(mat); + + for (var i = 0; i < result.length; i++) { + result[i] = matrix.dotproduct(vec, mat_T[i]); + } + return result; +}; + +/** + * Perform matrix-vector multiplication. + * + * e.g. A x B = (m x n) x (n x m), where n, m are integers who define + * the dimensions of matrix A, vector B. + * + * @param {Array} matrix. + * @param {Array} vector. + * @return {Array} result. + */ +matrix.multiplyMatVec = function (mat, vec) { + if (mat[0].length !== vec.length) { + throw new Error("Dimension mismatch"); + } + + var result = new Array(mat.length); + + var vec_T = matrix.transposeColumnVector(vec); + + for (var i = 0; i < result.length; i++) { + result[i] = [matrix.dotproduct(mat[i], vec_T)]; + } + return result; +}; + +/** + * Perform matrix-matrix multiplication. * * e.g. A x B = (m x n) x (n x m), where n, m are integers who define * the dimensions of matrices A, B. * * @param {Array} matrix. * @param {Array} matrix. - * @return {Array} result of multiplied matrices. + * @return {Array} result. */ -matrix.multiply = function (arrA, arrB) { +matrix.multiplyMatMat = function (arrA, arrB) { if (arrA[0].length !== arrB.length) { - throw new Error("Matrix mismatch"); + throw new Error("Dimension mismatch"); } var result = new Array(arrA.length); - + for (var x = 0; x < arrA.length; x++) { result[x] = new Array(arrB[0].length); } - var arrB_T = matrix.transpose(arrB); - + var arrB_T = matrix.transposeMatrix(arrB); + for (var i = 0; i < result.length; i++) { for (var j = 0; j < result[i].length; j++) { - result[i][j] = matrix.dotproduct(arrA[i],arrB_T[j]); + result[i][j] = matrix.dotproduct(arrA[i], arrB_T[j]); } } return result; }; +/** + * Perform matrix-matrix, matrix-vector or vector-matrix multiplication. + * + * e.g. A x B = (m x n) x (n x m), where n, m are integers who define + * the dimensions of matrices/vectors A, B. + * + * @param {Array} matrix / vector. + * @param {Array} matrix / vector. + * @return {Array} result. + */ +matrix.multiply = function (arrA, arrB) { + if (arrA[0].length > 1 && arrB[0].length > 1) { + return matrix.multiplyMatMat(arrA, arrB); + } else if (arrA[0].length > 1) { + return matrix.multiplyMatVec(arrA, arrB); + } else { + return matrix.multiplyVecMat(arrA, arrB); + } +}; + /** * Evaluate determinate of matrix. Expect speed - * degradation for matrices over 4x4. + * degradation for matrices over 4x4. * * @param {Array} matrix. * @return {Number} determinant. @@ -1403,7 +1555,7 @@ matrix.determinant = function (m) { diagLeft = m[0][col]; diagRight = m[0][col]; - for( row=1; row < numRow; row++ ) { + for (row = 1; row < numRow; row++) { diagRight *= m[row][(((col + row) % numCol) + numCol) % numCol]; diagLeft *= m[row][(((col - row) % numCol) + numCol) % numCol]; } @@ -1432,7 +1584,7 @@ matrix.determinant = function (m) { * @param {Array} arr * @return {Array} array of matrices [L, U, P] */ -matrix.lupDecomposition = function(arr) { +matrix.lupDecomposition = function (arr) { if (!matrix.isSquare(arr)) { throw new Error(ERROR_MATRIX_NOT_SQUARE); } @@ -1444,10 +1596,10 @@ matrix.lupDecomposition = function(arr) { var currentRow; var currentColumn = new Array(size); - this.getL = function(a) { + this.getL = function (a) { var m = a[0].length; var L = matrix.identity(m); - + for (var i = 0; i < m; i++) { for (var j = 0; j < m; j++) { if (i > j) { @@ -1455,14 +1607,14 @@ matrix.lupDecomposition = function(arr) { } } } - + return L; }; - this.getU = function(a) { + this.getU = function (a) { var m = a[0].length; var U = matrix.identity(m); - + for (var i = 0; i < m; i++) { for (var j = 0; j < m; j++) { if (i <= j) { @@ -1470,7 +1622,7 @@ matrix.lupDecomposition = function(arr) { } } } - + return U; }; @@ -1483,11 +1635,11 @@ matrix.lupDecomposition = function(arr) { for (i = 0; i < size; i++) { currentRow = LU[i]; - var minIndex = Math.min(i,j); + var minIndex = Math.min(i, j); var s = 0; - + for (var k = 0; k < minIndex; k++) { - s += currentRow[k]*currentColumn[k]; + s += currentRow[k] * currentColumn[k]; } currentRow[j] = currentColumn[i] -= s; @@ -1500,8 +1652,8 @@ matrix.lupDecomposition = function(arr) { pivot = i; } } - - if (pivot != j) { + + if (pivot !== j) { LU = matrix.rowSwitch(LU, pivot, j); P = matrix.rowSwitch(P, pivot, j); } @@ -1512,7 +1664,7 @@ matrix.lupDecomposition = function(arr) { } } } - + return [this.getL(LU), this.getU(LU), P]; }; @@ -1592,7 +1744,7 @@ matrix.affine = function (point, tx, ty) { var transformation = [ [1, 0, tx], [0, 1, ty], - [0, 0, 1 ] + [0, 0, 1] ]; var newpoint = [ @@ -1602,7 +1754,7 @@ matrix.affine = function (point, tx, ty) { ]; var transformed = matrix.multiply(transformation, newpoint); - + return [ [transformed[0][0]], [transformed[1][0]] @@ -1610,22 +1762,22 @@ matrix.affine = function (point, tx, ty) { }; /** - * Scales a row of a matrix by a factor and returns the updated matrix. + * Scales a row of a matrix by a factor and returns the updated matrix. * Used in row reduction functions. - * + * * @param {Array} matrix. * @param {Number} row. * @param {Number} scale. */ matrix.rowScale = function (m, row, scale) { var result = new Array(m.length); - + for (var i = 0; i < m.length; i++) { result[i] = new Array(m[i].length); - + for (var j = 0; j < m[i].length; j++) { if (i === row) { - result[i][j] = scale * m[i][j]; + result[i][j] = scale * m[i][j]; } else { result[i][j] = m[i][j]; } @@ -1636,22 +1788,22 @@ matrix.rowScale = function (m, row, scale) { }; /** - * Swaps two rows of a matrix and returns the updated matrix. + * Swaps two rows of a matrix and returns the updated matrix. * Used in row reduction functions. - * + * * @param {Array} matrix. * @param {Number} row1. * @param {Number} row2. */ matrix.rowSwitch = function (m, row1, row2) { var result = new Array(m.length); - + for (var i = 0; i < m.length; i++) { result[i] = new Array(m[i].length); - + for (var j = 0; j < m[i].length; j++) { if (i === row1) { - result[i][j] = m[row2][j]; + result[i][j] = m[row2][j]; } else if (i === row2) { result[i][j] = m[row1][j]; } else { @@ -1664,19 +1816,19 @@ matrix.rowSwitch = function (m, row1, row2) { /** * Adds a multiple of one row to another row - * in a matrix and returns the updated matrix. + * in a matrix and returns the updated matrix. * Used in row reduction functions. - * + * * @param {Array} matrix. * @param {Number} row1. * @param {Number} row2. */ -matrix.rowAddMultiple = function (m, from, to, scale){ +matrix.rowAddMultiple = function (m, from, to, scale) { var result = new Array(m.length); - + for (var i = 0; i < m.length; i++) { result[i] = new Array(m[i].length); - + for (var j = 0; j < m[i].length; j++) { if (i === to) { result[to][j] = m[to][j] + scale * m[from][j]; @@ -1696,10 +1848,10 @@ matrix.rowAddMultiple = function (m, from, to, scale){ * @param {Number} epsilon. * @return {Array} RREF matrix. */ -matrix.GaussJordanEliminate = function(m, epsilon) { +matrix.GaussJordanEliminate = function (m, epsilon) { // Translated from: // http://elonen.iki.fi/code/misc-notes/python-gaussj/index.html - var eps = (typeof epsilon == 'undefined') ? 1e-10 : epsilon; + var eps = (typeof epsilon === 'undefined') ? 1e-10 : epsilon; var h = m.length; var w = m[0].length; @@ -1711,7 +1863,7 @@ matrix.GaussJordanEliminate = function(m, epsilon) { var maxrow = y; y2 = y; while (++y2 < h) { - if(Math.abs(m[y2][y]) > Math.abs(m[maxrow][y])) + if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y])) maxrow = y2; } var tmp = m[y]; @@ -1719,7 +1871,7 @@ matrix.GaussJordanEliminate = function(m, epsilon) { m[maxrow] = tmp; // Singular - if(Math.abs(m[y][y]) <= eps) { + if (Math.abs(m[y][y]) <= eps) { return m; } @@ -1742,7 +1894,7 @@ matrix.GaussJordanEliminate = function(m, epsilon) { while (++y2 < y) { x = w; while (--x >= y) { - m[y2][x] -= m[y][x] * m[y2][y] / c; + m[y2][x] -= m[y][x] * m[y2][y] / c; } } m[y][y] /= c; @@ -1764,7 +1916,7 @@ matrix.GaussJordanEliminate = function(m, epsilon) { * @param {Number} epsilon. * @return {Array} RREF matrix. */ -matrix.rowReduce = function(m, epsilon) { +matrix.rowReduce = function (m, epsilon) { return matrix.GaussJordanEliminate(m, epsilon); }; @@ -1774,17 +1926,17 @@ matrix.rowReduce = function(m, epsilon) { * @param {Array} matrix. * @return {Array} inverted matrix. */ -matrix.inverse = function(m) { +matrix.inverse = function (m) { if (!matrix.isSquare(m)) { throw new Error(ERROR_MATRIX_NOT_SQUARE); } var n = m.length, - identity = matrix.identity(n), - i; + identity = matrix.identity(n), + i; // AI - for(i=0; i= M[0].length) { throw new Error('The specified column must be between 0 and the number of columns - 1.'); } - for (var i=0; i= L.length) { throw new Error('The desired order of the rows must start at 0 and end at the number of rows - 1.'); - } else { + } else { result.push(M[L[i]]); } } @@ -1852,20 +2004,20 @@ matrix.reorderRows = function(M, L) { * @param {Array} desired re-ordering * @return {Array} reordered matrix */ -matrix.reorderCols = function(M, L) { +matrix.reorderCols = function (M, L) { var result = []; if (L === undefined) { throw new Error('Please enter a desired reordering array.'); } else if (L.length !== M[0].length) { throw new Error('The reordered matrix must have the same number of columns as the original matrix.'); } - for (var i=0; i= L.length) { throw new Error('The desired order of the columns must start at 0 and end at the number of columns - 1.'); } else { - result.push(matrix.getCol(M, L[i]) ); + result.push(matrix.getCol(M, L[i])); } } return matrix.transpose(result); @@ -1877,12 +2029,12 @@ matrix.reorderCols = function(M, L) { * @param {Array} matrix * @return {Array} reversed matrix */ -matrix.reverseRows = function(M) { - var L = []; - for (var i=M.length-1; i>-1; i--) { - L.push(i); - } - return matrix.reorderRows(M,L); +matrix.reverseRows = function (M) { + var L = []; + for (var i = M.length - 1; i > -1; i--) { + L.push(i); + } + return matrix.reorderRows(M, L); }; /** @@ -1891,12 +2043,12 @@ matrix.reverseRows = function(M) { * @param {Array} matrix * @return {Array} reversed matrix */ -matrix.reverseCols = function(M) { - var L = []; - for (var i=M.length-1; i>-1; i--) { - L.push(i); - } - return matrix.reorderCols(M,L); +matrix.reverseCols = function (M) { + var L = []; + for (var i = M.length - 1; i > -1; i--) { + L.push(i); + } + return matrix.reorderCols(M, L); }; /** @@ -1906,16 +2058,16 @@ matrix.reverseCols = function(M) { * @param {Int} number of columns * @return {Array} matrix */ -matrix.zeros = function(n,m) { +matrix.zeros = function (n, m) { var M = new Array(n); if (n < 1 || m < 1) { throw new Error('The matrix dimensions must be positive integers.'); } n = Math.ceil(n); m = Math.ceil(m); - for (var i=0; i ans) { - ans = term; - } + case Infinity: + for (i = 0; i < n; i++) { + term = Math.abs(v[i]); + if (term > ans) { + ans = term; } - break; + } + break; - case -Infinity: - ans = Infinity; - for (i=0; i ans) { - ans = term; - } + if (term > ans) { + ans = term; } - break; + } + break; // the smallest value when absolute-ing and summing each row - case -Infinity: - ans = Infinity; - for (i=0; i ans) { - ans = term; - } + if (term > ans) { + ans = term; } - break; + } + break; // the smallest value when absolute-ing and summing each column - case -1: - ans = Infinity; - for (i=0; i 1) return test; return false; @@ -2587,24 +2752,25 @@ prime.getPerfectPower = function(n) { * @param {Number} value in question * @return {Array|Boolean} if it is a prime power, return [prime, power]. */ -prime.getPrimePower = function(n) { +prime.getPrimePower = function (n) { if (n < 2) return false; - if (prime.millerRabin(n)) return [n, 1]; + if (prime.millerRabin(n)) return [n, 1]; if (n % 2 === 0) return [2, n.toString(2).length - 1]; var factors = prime.factorization(n); if (!factors) return false; - + var len = factors.length; - + for (var i = 0; i < len; i++) { - var t = 0, p = 0; + var t = 0, + p = 0; while (t <= n) { t = Math.pow(factors[i], p); if (t / n === 1) return [factors[i], p]; - p++; + p++; } } @@ -2612,7 +2778,6 @@ prime.getPrimePower = function(n) { }; },{"./basic":3}],10:[function(require,module,exports){ -var basic = require('./basic'); var random = exports; // random number generator. @@ -2623,8 +2788,8 @@ var rGen = Math.random; * * @param {Function} Random number generator */ -random.setGenerator = function(fn){ - if(typeof fn !== "function"){ +random.setGenerator = function (fn) { + if (typeof fn !== "function") { throw new Error("Must pass a function"); } rGen = fn; @@ -2642,7 +2807,7 @@ random.sample = function (lower, upper, n) { var sample = []; sample.length = n; - for (var i=0; i 1); - var c = Math.sqrt(-2 * Math.log(s)/s), - x = u * c, - y = v * c; + var c = Math.sqrt(-2 * Math.log(s) / s), + x = u * c, + y = v * c; x = mu + x * sigma; y = mu + y * sigma; return [x, y]; @@ -2687,7 +2852,7 @@ random.boxMullerTransform = function(mu, sigma) { * @param {Number} number to subtract * @return {Number} random number along an irwin hall distribution. */ -random.irwinHall = function(n, sub) { +random.irwinHall = function (n, sub) { if (arguments.length === 1) sub = 0; var sum = 0; for (var i = 0; i < n; i++) sum += rGen(); @@ -2703,12 +2868,12 @@ random.irwinHall = function(n, sub) { * @param {Number} random minimum value (default is 0) * @return {Number} random number along an bates distribution. */ -random.bates = function(n, b, a) { +random.bates = function (n, b, a) { if (arguments.length <= 2) a = 0; if (arguments.length === 1) b = 1; var sum = 0; - for (var i = 0; i < n; i++) sum += (b - a)*rGen() + a; - return sum/n; + for (var i = 0; i < n; i++) sum += (b - a) * rGen() + a; + return sum / n; }; random.distribution = {}; @@ -2721,7 +2886,7 @@ random.distribution = {}; * @param {Number} sigma or standard deviation * @return {Array} array of size n of a normal distribution */ -random.distribution.normal = function(n, mu, sigma) { +random.distribution.normal = function (n, mu, sigma) { if (arguments.length <= 2) sigma = 1; if (arguments.length === 1) mu = 0; @@ -2736,11 +2901,11 @@ random.distribution.normal = function(n, mu, sigma) { * @param {Number} sigma or standard deviation * @return {Array} array of size n of a log normal distribution */ -random.distribution.logNormal = function(n, mu, sigma) { +random.distribution.logNormal = function (n, mu, sigma) { if (arguments.length <= 2) sigma = 1; if (arguments.length === 1) mu = 0; - var exponential = function(x) { + var exponential = function (x) { return Math.exp(x); }; @@ -2758,7 +2923,7 @@ random.distribution.logNormal = function(n, mu, sigma) { * @param {Number} determine if the distribution will be polar coordinates. * @return {Array} array of size n of a normal distribution */ -random.distribution.boxMuller = function(n, mu, sigma, rc) { +random.distribution.boxMuller = function (n, mu, sigma, rc) { if (arguments.length <= 3) rc = false; if (arguments.length <= 2) sigma = 1; if (arguments.length === 1) mu = 0; @@ -2781,7 +2946,7 @@ random.distribution.boxMuller = function(n, mu, sigma, rc) { * @param {Number} irwinHall subtraction value (default is 0) * @return {Array} irwin hall distribution from [a, b] */ -random.distribution.irwinHall = function(n, m, sub) { +random.distribution.irwinHall = function (n, m, sub) { if (arguments.length <= 2) sub = 0; if (arguments.length === 1) m = n; var results = new Array(n); @@ -2801,7 +2966,7 @@ random.distribution.irwinHall = function(n, m, sub) { * @param {Number} length of array * @return {Array} an array of an approximate normal distribution from [-6, 6] of length n. */ -random.distribution.irwinHallNormal = function(n) { +random.distribution.irwinHallNormal = function (n) { return random.distribution.irwinHall(n, 12, 6); }; @@ -2814,7 +2979,7 @@ random.distribution.irwinHallNormal = function(n) { * @param {Number} minimum bound a (default is 0) * @return {Array} bates distribution from [a, b] */ -random.distribution.bates = function(n, b, a) { +random.distribution.bates = function (n, b, a) { if (arguments.length <= 2) a = 0; if (arguments.length === 1) b = n; @@ -2827,7 +2992,7 @@ random.distribution.bates = function(n, b, a) { return results; }; -},{"./basic":3}],11:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ /** * statistic.js * http://github.com/sjkaliski/numbers.js @@ -2921,7 +3086,9 @@ statistic.quantile = function (arr, k, q) { if (k === q) return Math.max.apply(null, arr); sorted = arr.slice(0); - sorted.sort(function (a, b) { return a - b; }); + sorted.sort(function (a, b) { + return a - b; + }); count = sorted.length; index = count * k / q; @@ -2936,7 +3103,7 @@ statistic.quantile = function (arr, k, q) { * * @return {Object} summary statistics. */ -statistic.report = function(array) { +statistic.report = function (array) { return { mean: statistic.mean(array), firstQuartile: statistic.quantile(array, 1, 4), @@ -2958,7 +3125,7 @@ statistic.standardDev = function (arr) { var squaredArr = []; for (var i = 0; i < arr.length; i++) { - squaredArr[i] = Math.pow((arr[i] - mean),2); + squaredArr[i] = Math.pow((arr[i] - mean), 2); } return Math.sqrt((1 / count) * basic.sum(squaredArr)); @@ -2971,7 +3138,7 @@ statistic.standardDev = function (arr) { * @return {Number} correlation. */ statistic.correlation = function (arrX, arrY) { - if (arrX.length == arrY.length) { + if (arrX.length === arrY.length) { var covarXY = statistic.covariance(arrX, arrY); var stdDevX = statistic.standardDev(arrX); var stdDevY = statistic.standardDev(arrY); @@ -2990,7 +3157,7 @@ statistic.correlation = function (arrX, arrY) { * @return {Number} A number between 0 and 1.0 that represents how well the regression line fits the data. */ statistic.rSquared = function (source, regression) { - var residualSumOfSquares = basic.sum(source.map(function (d,i) { + var residualSumOfSquares = basic.sum(source.map(function (d, i) { return basic.square(d - regression[i]); })); @@ -3009,22 +3176,26 @@ statistic.rSquared = function (source, regression) { */ statistic.exponentialRegression = function (arrY) { var n = arrY.length; - var arrX = basic.range(1,n); + var arrX = basic.range(1, n); var xSum = basic.sum(arrX); - var ySum = basic.sum(arrY); - var yMean = statistic.mean(arrY); - var yLog = arrY.map(function (d) { return Math.log(d); }); - var xSquared = arrX.map(function (d) { return d * d; }); + var yLog = arrY.map(function (d) { + return Math.log(d); + }); + var xSquared = arrX.map(function (d) { + return d * d; + }); var xSquaredSum = basic.sum(xSquared); var yLogSum = basic.sum(yLog); - var xyLog = arrX.map(function (d, i) { return d * yLog[i]; }); + var xyLog = arrX.map(function (d, i) { + return d * yLog[i]; + }); var xyLogSum = basic.sum(xyLog); var a = (yLogSum * xSquaredSum - xSum * xyLogSum) / (n * xSquaredSum - (xSum * xSum)); var b = (n * xyLogSum - xSum * yLogSum) / (n * xSquaredSum - (xSum * xSum)); - var fn = function(x) { + var fn = function (x) { if (typeof x === 'number') { return Math.exp(a) * Math.exp(b * x); } else { @@ -3050,14 +3221,18 @@ statistic.linearRegression = function (arrX, arrY) { var n = arrX.length; var xSum = basic.sum(arrX); var ySum = basic.sum(arrY); - var xySum = basic.sum(arrX.map(function (d, i) { return d * arrY[i]; })); - var xSquaredSum = basic.sum(arrX.map(function (d) { return d * d; })); + var xySum = basic.sum(arrX.map(function (d, i) { + return d * arrY[i]; + })); + var xSquaredSum = basic.sum(arrX.map(function (d) { + return d * d; + })); var xMean = statistic.mean(arrX); var yMean = statistic.mean(arrY); var b = (xySum - 1 / n * xSum * ySum) / (xSquaredSum - 1 / n * (xSum * xSum)); var a = yMean - b * xMean; - return function(x) { + return function (x) { if (typeof x === 'number') { return a + b * x; } else { @@ -3075,8 +3250,8 @@ statistic.linearRegression = function (arrX, arrY) { * @param {Array} set 2 of values. * @return {Number} covariance. */ - statistic.covariance = function (set1, set2) { - if (set1.length == set2.length) { +statistic.covariance = function (set1, set2) { + if (set1.length === set2.length) { var n = set1.length; var total = 0; var sum1 = basic.sum(set1); diff --git a/src/numbers.min.js b/src/numbers.min.js old mode 100755 new mode 100644 index 0aef159..5164b16 --- a/src/numbers.min.js +++ b/src/numbers.min.js @@ -1 +1 @@ -!function(r){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=r();else if("function"==typeof define&&define.amd)define([],r);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.numbers=r()}}(function(){return function r(t,e,n){function o(i,u){if(!e[i]){if(!t[i]){var f="function"==typeof require&&require;if(!u&&f)return f(i,!0);if(a)return a(i,!0);var s=new Error("Cannot find module '"+i+"'");throw s.code="MODULE_NOT_FOUND",s}var h=e[i]={exports:{}};t[i][0].call(h.exports,function(r){var e=t[i][1][r];return o(e?e:r)},h,h.exports,r,t,e,n)}return e[i].exports}for(var a="function"==typeof require&&require,i=0;ie;e++){if("number"!=typeof r[e])throw new Error("All elements in array must be numbers");t-=r[e]}return t}throw new Error("Input must be of type Array")},n.product=function(r){if("[object Array]"===Object.prototype.toString.call(r)){var t=r[0];if("number"!=typeof t)throw new Error("All elements in array must be numbers");for(var e=1,n=r.length;n>e;e++){if("number"!=typeof r[e])throw new Error("All elements in array must be numbers");t*=r[e]}return t}throw new Error("Input must be of type Array")},n.square=function(r){if("number"!=typeof r)throw new Error("Input must be a number.");return r*r},n.binomial=function(r,t){function e(r,t){return r>=0&&0===t?1:0===r&&t>0?0:n[r]&&n[r][t]>0?n[r][t]:(n[r]||(n[r]=[]),n[r][t]=e(r-1,t-1)+e(r-1,t),n[r][t])}var n=[];return e(r,t)},n.factorial=function(r){for(var t=2,e=1;r>=t;)e*=t++;return e},n.gcd=function(r,t){var e;if(r=+r,t=+t,r!==r||t!==t)return 0/0;if(1/0===r||r===-1/0||1/0===t||t===-1/0)return 1/0;if(r%1!==0||t%1!==0)throw new Error("Can only operate on integers");for(;t;)e=r%t,r=t,t=e;return r>0?r:-r},n.lcm=function(r,t){return Math.abs(r*t)/n.gcd(r,t)},n.random=function(r,t,e){if(0===r.length)throw new Error("Empty array");if(t>r.length&&!e)throw new Error("Quantity requested exceeds size of array");if(e===!0){var o,a=[];for(o=0;t>o;o++)a[o]=r[Math.floor(Math.random()*r.length)];return a}return n.shuffle(r).slice(0,t)},n.shuffle=function(r){for(var t,e,n=r.length;n;)e=Math.floor(Math.random()*n--),t=r[n],r[n]=r[e],r[e]=t;return r},n.max=function(r){if(!Array.isArray(r))throw new Error("Input must be of type Array");for(var t,e=-1/0,n=0,o=r.length;o>n;n++)if(t=+r[n],t>e&&(e=t),t!==t)return 0/0;return e},n.min=function(r){if(!Array.isArray(r))throw new Error("Input must be of type Array");for(var t,e=+1/0,n=0,o=r.length;o>n;n++)if(t=+r[n],e>t&&(e=t),t!==t)return 0/0;return e},n.range=function(r,t,e){var n,o,a=0;for(arguments.length<=1&&(t=r||0,r=0),e=e||1,r>t&&(e=0-Math.abs(e)),o=Math.max(Math.ceil((t-r)/e)+1,0),n=new Array(o);o>a;)n[a++]=r,r+=e;return n},n.isInt=function(r){return r%1===0},n.divMod=function(r,t){return n.isInt(r)&&n.isInt(t)?[Math.floor(r/t),r%t]:!1},n.powerMod=function(r,t,e){if(-1>t)return Math.pow(r,t)%e;if(0===t)return 1%e;if(t>=1){for(var o=1;t>0;)t%2===1&&(o=o*r%e),r=r*r%e,t>>=1;return o}return-1===t?n.modInverse(r,e):1>t?n.powerMod(r,Math.pow(t,-1),e):void 0},n.egcd=function(r,t){if(r=+r,t=+t,r!==r||t!==t)return[0/0,0/0,0/0];if(1/0===r||r===-1/0||1/0===t||t===-1/0)return[1/0,1/0,1/0];if(r%1!==0||t%1!==0)throw new Error("Can only operate on integers");var e,n,o,a,i=0>r?-1:1,u=0>t?-1:1,f=0,s=1,h=1,l=0;for(r=Math.abs(r),t=Math.abs(t);0!==r;)e=Math.floor(t/r),n=t%r,o=f-h*e,a=s-l*e,t=r,r=n,f=h,s=l,h=o,l=a;return[t,i*f,u*s]},n.modInverse=function(r,t){var e=n.egcd(r,t);if(1!=e[0])throw new Error("No modular inverse exists");return e[1]%t},n.numbersEqual=function(r,t,e){return e>r-t&&r-t>-e},n.fallingFactorial=function(r,t){var e=r-t+1,n=1;if(0>r)throw new Error("n cannot be negative");if(t>r)return 0;for(;r>=e;)n*=e++;return n}},{}],4:[function(r,t,e){function n(r,t,e){var n=(t+e)/2,o=Math.abs(e-t)/6;return o*(r(t)+4*r(n)+r(e))}function o(r,t,e,a,i){var u=t+e,f=n(r,t,u),s=n(r,u,e);return Math.abs(f+s-a)<=15*i?f+s+(f+s-a)/15:o(r,t,u,i/2,f)+o(r,u,e,i/2,s)}var a=r("../numbers"),i=e;i.pointDiff=function(r,t){var e=r(t-.001),n=r(t+.001);return(n-e)/.002},i.Riemann=function(r,t,e,n,o){var a,i=(e-t)/n,u=0;if("function"==typeof o)for(a=t;e>a;a+=i)u+=r(o(a,a+i));else for(a=t;e>a;a+=i)u+=r(a);return u*i},i.adaptiveSimpson=function(r,t,e,i){return i="undefined"==typeof i?a.EPSILON:i,o(r,t,e,n(r,t,e),i)},i.limit=function(r,t,e){if("left"===e)return r(t-1e-15);if("right"===e)return r(t+1e-15);if("middle"===e)return(i.limit(r,t,"left")+i.limit(r,t,"right"))/2;throw new Error("Approach not provided")},i.StirlingGamma=function(r){return Math.sqrt(2*Math.PI/r)*Math.pow(r/Math.E,r)},i.LanczosGamma=function(r){var t,e=[.9999999999998099,676.5203681218851,-1259.1392167224028,771.3234287776531,-176.6150291621406,12.507343278686905,-.13857109526572012,9984369578019572e-21,1.5056327351493116e-7],n=7;if(.5>r)return Math.PI/(Math.sin(Math.PI*r)*i.LanczosGamma(1-r));r-=1;var o=e[0],a=r+n+.5;for(t=1;t=t)throw new Error("Please use a positive integer for N.");var e=[];t=Math.ceil(t);for(var n=2;ne;e++){var n=(this.phase()+2*Math.PI*e)/r,a=Math.pow(this.magnitude(),1/r);t[e]=new o(a*Math.cos(n),a*Math.sin(n))}return t},o.prototype.sin=function(){var r=new o(Math.E,0),t=new o(0,1),e=new o(0,-1),n=r.complexPow(t.multiply(this)).subtract(r.complexPow(e.multiply(this)));return n.divide(new o(0,2))},o.prototype.cos=function(){var r=new o(Math.E,0),t=new o(0,1),e=new o(0,-1),n=r.complexPow(t.multiply(this)).add(r.complexPow(e.multiply(this)));return n.divide(new o(2,0))},o.prototype.tan=function(){return this.sin().divide(this.cos())},o.prototype.equals=function(r,t){return n.numbersEqual(this.re,r.re,t)&&n.numbersEqual(this.im,r.im,t)},t.exports=o},{"../numbers":2}],6:[function(r,t,e){var n=r("../numbers"),o=n.complex,a=e;a.segment=function(r,t,e){for(var n=[],o=t;o=t)return[new o(r[0],0)];if(Math.log(t)/Math.LN2%1!==0)throw new Error("Array length must be integer power of 2");for(var e=a.fft(a.segment(r,0,2)),n=a.fft(a.segment(r,1,2)),i=[],u=t/2,f=0;t>f;f++){var s=-2*Math.PI*f/t,h=new o(Math.cos(s),Math.sin(s));i[f]=u>f?e[f].add(h.multiply(n[f])):e[f-u].subtract(h.multiply(n[f-u]))}return i}},{"../numbers":2}],7:[function(r,t,e){var n=e;n.fibonacci=function(r){for(var t,e=function(r){for(var t,e=[];r>0;)t=2>r?r:r%2,r=Math.floor(r/2),e.push(t);return e.reverse()},n=1,o=0,a=1,i=e(r),u=0;ue;e++)if(r[e].length!==t)return!1;return!0},n.addition=function(r,t){if(r.length!==t.length||r[0].length!==t[0].length)throw new Error("Matrix mismatch");var e,n=new Array(r.length);if(r[0].length)for(e=0;ee;e++){t[e]=new Array(r);for(var n=0;r>n;n++)t[e][n]=e===n?1:0}return t},n.dotproduct=function(r,t){if(r.length!==t.length)throw new Error("Vector mismatch");for(var e=0,n=0;ne;e++){for(a=r[0][e],i=r[0][e],t=1;u>t;t++)i*=r[t][((e+t)%f+f)%f],a*=r[t][((e-t)%f+f)%f];s+=i-a}return s},n.lupDecomposition=function(r){if(!n.isSquare(r))throw new Error(o);var t,e=r.length,a=n.deepCopy(r),i=n.transpose(n.identity(e)),u=new Array(e);this.getL=function(r){for(var t=r[0].length,e=n.identity(t),o=0;t>o;o++)for(var a=0;t>a;a++)o>a&&(e[o][a]=r[o][a]);return e},this.getU=function(r){for(var t=r[0].length,e=n.identity(t),o=0;t>o;o++)for(var a=0;t>a;a++)a>=o&&(e[o][a]=r[o][a]);return e};for(var f=0;e>f;f++){var s;for(s=0;e>s;s++)u[s]=a[s][f];for(s=0;e>s;s++){t=a[s];for(var h=Math.min(s,f),l=0,c=0;h>c;c++)l+=t[c]*u[c];t[f]=u[s]-=l}var m=f;for(s=f+1;e>s;s++)Math.abs(u[s])>Math.abs(u[m])&&(m=s);if(m!=f&&(a=n.rowSwitch(a,m,f),i=n.rowSwitch(i,m,f)),e>f&&0!==a[f][f])for(s=f+1;e>s;s++)a[s][f]/=a[f][f]}return[this.getL(a),this.getU(a),i]},n.rotate=function(r,t,e){n._check2DVector(r);var o="clockwise"===e?-1:1,a=t*(Math.PI/180),i=[[Math.cos(a),-1*o*Math.sin(a)],[o*Math.sin(a),Math.cos(a)]];return n.multiply(i,r)},n.scale=function(r,t,e){n._check2DVector(r);var o=[[t,0],[0,e]];return n.multiply(o,r)},n.shear=function(r,t,e){n._check2DVector(r);var o="xaxis"===e?t:0,a="yaxis"===e?t:0,i=[[1,o],[a,1]];return n.multiply(i,r)},n.affine=function(r,t,e){n._check2DVector(r);var o=[[1,0,t],[0,1,e],[0,0,1]],a=[[r[0][0]],[r[1][0]],[1]],i=n.multiply(o,a);return[[i[0][0]],[i[1][0]]]},n.rowScale=function(r,t,e){for(var n=new Array(r.length),o=0;oMath.abs(r[s][f])&&(s=e);var h=r[f];if(r[f]=r[s],r[s]=h,Math.abs(r[f][f])<=a)return r;for(e=f;++e=0;){for(o=r[f][f],e=-1;++e=f;)r[e][n]-=r[f][n]*r[e][f]/o;for(r[f][f]/=o,n=i-1;++nt;t++)r[t]=r[t].concat(a[t]);for(r=n.GaussJordanEliminate(r),t=0;e>t;t++)r[t]=r[t].slice(e);return r},n.getCol=function(r,t){var e=new Array(r.length);if(0>t)throw new Error("The specified column must be a positive integer.");if(t>=r[0].length)throw new Error("The specified column must be between 0 and the number of columns - 1.");for(var n=0;n=t.length)throw new Error("The desired order of the rows must start at 0 and end at the number of rows - 1.");e.push(r[t[n]])}return e},n.reorderCols=function(r,t){var e=[];if(void 0===t)throw new Error("Please enter a desired reordering array.");if(t.length!==r[0].length)throw new Error("The reordered matrix must have the same number of columns as the original matrix.");for(var o=0;o=t.length)throw new Error("The desired order of the columns must start at 0 and end at the number of columns - 1.");e.push(n.getCol(r,t[o]))}return n.transpose(e)},n.reverseRows=function(r){for(var t=[],e=r.length-1;e>-1;e--)t.push(e);return n.reorderRows(r,t)},n.reverseCols=function(r){for(var t=[],e=r.length-1;e>-1;e--)t.push(e);return n.reorderCols(r,t)},n.zeros=function(r,t){var e=new Array(r);if(1>r||1>t)throw new Error("The matrix dimensions must be positive integers.");r=Math.ceil(r),t=Math.ceil(t);for(var n=0;r>n;n++){for(var o=new Array(t),a=0;t>a;a++)o[a]=0;e[n]=o}return e},n.zigzag=function(r,t,e){if(1>=r)throw new Error("Matrix size must be at least 2x2.");r=Math.ceil(r);var o=n.zeros(r,r),a=function(t){var e,n,o,a,i,u=!1,f=r*r,s=1,h=1;for(t[0][0]=f,t[r-1][r-1]=s,a=1;r>a;a++)u?(f-=4*h,s+=4*h,h++):(f--,s++),t[0][a]=f,t[r-1][r-1-a]=s,u=!u;var l=!0;for(a=1;r>a;a++){for(e=0,n=a,o=t[e][n],i=1;a+1>i;i++)l?o-=1:o+=1,e++,n--,t[e][n]=o;l=!l}for(l=r%2===0?!0:!1,a=1;r-1>a;a++){for(e=r-1,n=a,o=t[e][n],i=1;r-a>i;i++)l?o--:o++,e--,n++,t[e][n]=o;l=!l}return t},i=function(r){return n.transpose(a(r))},u=function(r){return n.reverseCols(a(r))},f=function(r){return n.reverseRows(c(u(r)))},s=function(r){return n.reverseRows(a(r))},h=function(r){return n.reverseRows(i(r))},l=function(r){return n.reverseCols(n.reverseRows(a(r)))},c=function(r){return n.transpose(l(r))};if("BR"===t&&"H"===e)return a(o);if("BR"===t&&"V"===e)return i(o);if("BL"===t&&"H"===e)return u(o);if("BL"===t&&"V"===e)return f(o);if("TR"===t&&"H"===e)return s(o);if("TR"===t&&"V"===e)return h(o);if("TL"===t&&"H"===e)return l(o);if("TL"===t&&"V"===e)return c(o);throw new Error("Enter the direction (V,H) and corner (BR,BL,TR,TL) correctly.")},n.vectorNorm=function(r,t){if(!Array.isArray(r)||0===r.length)throw new Error("Vector must be an array of at least length 1.");if("undefined"!=typeof t&&"number"!=typeof t)throw new Error("Norm order must be a number.");t="undefined"==typeof t?2:t;var e,n,o=r.length,a=0;switch(t){case 1/0:for(n=0;o>n;n++)e=Math.abs(r[n]),e>a&&(a=e);break;case-1/0:for(a=1/0,n=0;o>n;n++)e=Math.abs(r[n]),a>e&&(a=e);break;default:for(n=0;o>n;n++)a+=Math.pow(Math.abs(r[n]),t);a=Math.pow(a,1/t)}return a},n.matrixNorm=function(r,t){if(!Array.isArray(r)||0===r.length||!Array.isArray(r[0]))throw new Error("Matrix must be an array of at least length 1.");if("undefined"!=typeof t&&"number"!=typeof t&&null!==t)throw new Error("Norm order must be a number or null.");t="undefined"==typeof t?null:t;var e,n,o,a=r.length,i=r[0].length,u=0;switch(t){case 1/0:for(n=0;a>n;n++){for(e=0,o=0;i>o;o++)e+=Math.abs(r[n][o]);e>u&&(u=e)}break;case-1/0:for(u=1/0,n=0;a>n;n++){for(e=0,o=0;i>o;o++)e+=Math.abs(r[n][o]);u>e&&(u=e)}break;case 1:for(n=0;i>n;n++){for(e=0,o=0;a>o;o++)e+=Math.abs(r[o][n]);e>u&&(u=e)}break;case-1:for(u=1/0,n=0;i>n;n++){for(e=0,o=0;a>o;o++)e+=Math.abs(r[o][n]);u>e&&(u=e)}break;case null:for(n=0;a>n;n++)for(o=0;i>o;o++)u+=Math.pow(r[n][o],2);u=Math.pow(u,.5);break;case 2:throw new Error("Singular values are not yet supported in numbers.js.");case-2:throw new Error("Singular values are not yet supported in numbers.js.");default:for(n=0;a>n;n++)for(o=0;i>o;o++)u+=Math.pow(Math.abs(r[n][o]),t);u=Math.pow(u,1/t)}return u},n.isUpperBand=function(r,t){if(!Array.isArray(r)||!Array.isArray(r[0])||r.length<2)throw new Error("Matrix must be an array of at least dimension 2.");if("number"!=typeof t||0>t||t%1!==0)throw new Error("Upper bandwidth must be a nonzero integer.");for(var e=!0,n=r[0].length,o=0,a=t+1;n>a;a++){if(0!==r[o][a]){e=!1;break}o++}return e},n.isLowerBand=function(r,t){if(!Array.isArray(r)||!Array.isArray(r[0])||r.length<2)throw new Error("Matrix must be an array of at least dimension 2.");if("number"!=typeof t||0>t||t%1!==0)throw new Error("Lower bandwidth must be a nonzero integer.");for(var e=!0,n=r.length,o=0,a=t+1;n>a;a++){if(0!==r[a][o]){e=!1;break}o++}return e},sumNondiagonalElements=function(r,t){var e,n=0;for(e=0;t>e;e++)n+=Math.abs(r[e]);for(e=t+1;ee;e++){var a=r[e],i=a[e],u=sumNondiagonalElements(a,e);if(Math.abs(i)e;e++){var a=r[e],i=a[e],u=sumNondiagonalElements(a,e);if(Math.abs(i)<=u)return!1}return!0},n.isColumnDD=function(r){if(!n.isSquare)throw new Error(o);for(var t=r.length,e=0;t>e;e++){var a=n.getCol(r,e),i=a[e],u=sumNondiagonalElements(a,e);if(Math.abs(i)e;e++){var a=n.getCol(r,e),i=a[e],u=sumNondiagonalElements(a,e);if(Math.abs(i)<=u)return!1}return!0}},{}],9:[function(r,t,e){var n=r("./basic"),o=e;o.simple=function(r){if(isNaN(r)||!isFinite(r)||r%1||2>r)return!1;if(r%2===0)return 2===r;if(r%3===0)return 3===r;for(var t=5,e=Math.sqrt(r);e>=t;t+=6)if(r%t===0||r%(t+2)===0)return!1;return!0},o.factorization=function(r){r=Math.floor(r);for(var t,e,n=[],o=Math.sqrt,a=r>1&&isFinite(r);a;){if(t=o(r),e=2,r%e)for(e=3;r%e&&(e+=2)t?r:e,n.push(e),a=e!==r,r/=e}return n},o.millerRabin=function(r,t){if(1===arguments.length&&(t=20),2===r)return!0;if(!n.isInt(r)||1>=r||r%2===0)return!1;for(var e=0,o=r-1;;){var a=n.divMod(o,2),i=a[0],u=a[1];if(1===u)break;e+=1,o=i}for(var f=function(t){if(1===n.powerMod(t,o,r))return!1;for(var a=0;e>a;a++)if(n.powerMod(t,Math.pow(2,a)*o,r)===r-1)return!1;return!0},s=0;t>s;s++){var h=2+Math.floor(Math.random()*(r-2-2));if(f(h))return!1}return!0},o.sieve=function(r){if(2>r)return[];for(var t=[2],e=3;r>=e;e++){var n=!1;for(var o in t)n=n||0===e%t[o];n||t.push(e)}return t},o.coprime=function(r,t){return 1===n.gcd(r,t)},o.getPerfectPower=function(r){var t=o.getPrimePower(r);return t&&t[1]>1?t:!1},o.getPrimePower=function(r){if(2>r)return!1;if(o.millerRabin(r))return[r,1];if(r%2===0)return[2,r.toString(2).length-1];var t=o.factorization(r);if(!t)return!1;for(var e=t.length,n=0;e>n;n++)for(var a=0,i=0;r>=a;){if(a=Math.pow(t[n],i),a/r===1)return[t[n],i];i++}return!1}},{"./basic":3}],10:[function(r,t,e){var n=(r("./basic"),e),o=Math.random;n.setGenerator=function(r){if("function"!=typeof r)throw new Error("Must pass a function");o=r},n.sample=function(r,t,e){var n=[];n.length=e;for(var a=0;e>a;a++)n[a]=r+(t-r)*o();return n},n.boxMullerTransform=function(r,t){arguments.length<=1&&(t=1),0===arguments.length&&(r=0);var e,n=0,a=0;do n=2*o()-1,a=2*o()-1,e=n*n+a*a;while(0===e||e>1);var i=Math.sqrt(-2*Math.log(e)/e),u=n*i,f=a*i;return u=r+u*t,f=r+f*t,[u,f]},n.irwinHall=function(r,t){1===arguments.length&&(t=0);for(var e=0,n=0;r>n;n++)e+=o();return e-t},n.bates=function(r,t,e){arguments.length<=2&&(e=0),1===arguments.length&&(t=1);for(var n=0,a=0;r>a;a++)n+=(t-e)*o()+e;return n/r},n.distribution={},n.distribution.normal=function(r,t,e){return arguments.length<=2&&(e=1),1===arguments.length&&(t=0),n.distribution.boxMuller(r,t,e)},n.distribution.logNormal=function(r,t,e){arguments.length<=2&&(e=1),1===arguments.length&&(t=0);var o=function(r){return Math.exp(r)};return n.distribution.boxMuller(r,t,e).map(o)},n.distribution.boxMuller=function(r,t,e,o){arguments.length<=3&&(o=!1),arguments.length<=2&&(e=1),1===arguments.length&&(t=0);for(var a=[],i=0;r>i;i++){var u=n.boxMullerTransform(t,e);a.push(o?u:u[0])}return a},n.distribution.irwinHall=function(r,t,e){arguments.length<=2&&(e=0),1===arguments.length&&(t=r);for(var o=new Array(r),a=0;r>a;a++)o[a]=n.irwinHall(t,e);return o},n.distribution.irwinHallNormal=function(r){return n.distribution.irwinHall(r,12,6)},n.distribution.bates=function(r,t,e){arguments.length<=2&&(e=0),1===arguments.length&&(t=r);for(var o=new Array(r),a=0;r>a;a++)o[a]=n.bates(r,t,e);return o}},{"./basic":3}],11:[function(r,t,e){var n=r("./basic"),o=e;o.mean=function(r){var t=r.length,e=n.sum(r);return e/t},o.median=function(r){return o.quantile(r,1,2)},o.mode=function(r){for(var t={},e=0,n=r.length;n>e;e++)void 0===t[r[e]]?t[r[e]]=0:t[r[e]]++;var o;for(var a in t)t.hasOwnProperty(a)&&(void 0===o||t[a]>t[o])&&(o=a);return Number(o)},o.quantile=function(r,t,e){var n,o,a;return 0===t?Math.min.apply(null,r):t===e?Math.max.apply(null,r):(n=r.slice(0),n.sort(function(r,t){return r-t}),o=n.length,a=o*t/e,a%1===0?.5*n[a-1]+.5*n[a]:n[Math.floor(a)])},o.report=function(r){return{mean:o.mean(r),firstQuartile:o.quantile(r,1,4),median:o.median(r),thirdQuartile:o.quantile(r,3,4),standardDev:o.standardDev(r)}},o.standardDev=function(r){for(var t=r.length,e=o.mean(r),a=[],i=0;iu;u++)o+=r[u]*t[u];return(o-a*i/e)/e}throw new Error("Array mismatch")}},{"./basic":3}]},{},[1])(1)}); \ No newline at end of file +!function(r){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=r();else if("function"==typeof define&&define.amd)define([],r);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.numbers=r()}}(function(){return function r(t,e,n){function o(i,u){if(!e[i]){if(!t[i]){var f="function"==typeof require&&require;if(!u&&f)return f(i,!0);if(a)return a(i,!0);var s=new Error("Cannot find module '"+i+"'");throw s.code="MODULE_NOT_FOUND",s}var h=e[i]={exports:{}};t[i][0].call(h.exports,function(r){var e=t[i][1][r];return o(e?e:r)},h,h.exports,r,t,e,n)}return e[i].exports}for(var a="function"==typeof require&&require,i=0;ie;e++){if("number"!=typeof r[e])throw new Error("All elements in array must be numbers");t-=r[e]}return t}throw new Error("Input must be of type Array")},n.product=function(r){if("[object Array]"===Object.prototype.toString.call(r)){var t=r[0];if("number"!=typeof t)throw new Error("All elements in array must be numbers");for(var e=1,n=r.length;n>e;e++){if("number"!=typeof r[e])throw new Error("All elements in array must be numbers");t*=r[e]}return t}throw new Error("Input must be of type Array")},n.square=function(r){if("number"!=typeof r)throw new Error("Input must be a number.");return r*r},n.binomial=function(r,t){function e(r,t){if("number"!=typeof r&&"number"!=typeof t)throw new Error("Input must be a number.");return r>=0&&0===t?1:0===r&&t>0?0:n[r]&&n[r][t]>0?n[r][t]:(n[r]||(n[r]=[]),n[r][t]=e(r-1,t-1)+e(r-1,t),n[r][t])}var n=[];return e(r,t)},n.factorial=function(r){if("number"!=typeof r)throw new Error("Input must be a number.");if(0>r)throw new Error("Input must not be negative.");for(var t=2,e=1;r>=t;)e*=t++;return e},n.gcd=function(r,t){var e;if(r=+r,t=+t,r!==r||t!==t)return 0/0;if(1/0===r||r===-1/0||1/0===t||t===-1/0)return 1/0;if(r%1!==0||t%1!==0)throw new Error("Can only operate on integers");for(;t;)e=r%t,r=t,t=e;return r>0?r:-r},n.lcm=function(r,t){return Math.abs(r*t)/n.gcd(r,t)},n.random=function(r,t,e){if(0===r.length)throw new Error("Empty array");if(t>r.length&&!e)throw new Error("Quantity requested exceeds size of array");if(e===!0){var o,a=[];for(o=0;t>o;o++)a[o]=r[Math.floor(Math.random()*r.length)];return a}return n.shuffle(r).slice(0,t)},n.shuffle=function(r){for(var t,e,n=r.length;n;)e=Math.floor(Math.random()*n--),t=r[n],r[n]=r[e],r[e]=t;return r},n.max=function(r){if(!Array.isArray(r))throw new Error("Input must be of type Array");for(var t,e=-1/0,n=0,o=r.length;o>n;n++)if(t=+r[n],t>e&&(e=t),t!==t)return 0/0;return e},n.min=function(r){if(!Array.isArray(r))throw new Error("Input must be of type Array");for(var t,e=+1/0,n=0,o=r.length;o>n;n++)if(t=+r[n],e>t&&(e=t),t!==t)return 0/0;return e},n.range=function(r,t,e){var n,o,a=0;for(arguments.length<=1&&(t=r||0,r=0),e=e||1,r>t&&(e=0-Math.abs(e)),o=Math.max(Math.ceil((t-r)/e)+1,0),n=new Array(o);o>a;)n[a++]=r,r+=e;return n},n.isInt=function(r){return r%1===0},n.divMod=function(r,t){if(0>=t)throw new Error("b cannot be zero. Undefined.");if(!n.isInt(r)||!n.isInt(t))throw new Error("A or B are not integers.");return[Math.floor(r/t),r%t]},n.powerMod=function(r,t,e){if("number"!=typeof r||"number"!=typeof t||"number"!=typeof e)throw new Error("Inputs must be numbers.");if(-1>t)return Math.pow(r,t)%e;if(0===t)return 1%e;if(t>=1){for(var o=1;t>0;)t%2===1&&(o=o*r%e),r=r*r%e,t>>=1;return o}return-1===t?n.modInverse(r,e):1>t?n.powerMod(r,Math.pow(t,-1),e):void 0},n.egcd=function(r,t){if(r=+r,t=+t,r!==r||t!==t)return[0/0,0/0,0/0];if(1/0===r||r===-1/0||1/0===t||t===-1/0)return[1/0,1/0,1/0];if(r%1!==0||t%1!==0)throw new Error("Can only operate on integers");var e,n,o,a,i=0>r?-1:1,u=0>t?-1:1,f=0,s=1,h=1,l=0;for(r=Math.abs(r),t=Math.abs(t);0!==r;)e=Math.floor(t/r),n=t%r,o=f-h*e,a=s-l*e,t=r,r=n,f=h,s=l,h=o,l=a;return[t,i*f,u*s]},n.modInverse=function(r,t){var e=n.egcd(r,t);if(1!==e[0])throw new Error("No modular inverse exists");return e[1]%t},n.numbersEqual=function(r,t,e){if("number"!=typeof r||"number"!=typeof t||"number"!=typeof e)throw new Error("First and Second must be numbers.");return e>r-t&&r-t>-e},n.fallingFactorial=function(r,t){var e=r-t+1,n=1;if(0>r)throw new Error("n cannot be negative.");if(t>r)throw new Error("k cannot be greater than n.");for(;r>=e;)n*=e++;return n},n.permutation=function(r,t){if(0>=r)throw new Error("n cannot be less than or equal to 0.");if(t>r)throw new Error("k cannot be greater than k.");var e=n.binomial(r,t),o=e*n.factorial(t);return o}},{}],4:[function(r,t,e){function n(r,t,e){var n=(t+e)/2,o=Math.abs(e-t)/6;return o*(r(t)+4*r(n)+r(e))}function o(r,t,e,a,i){var u=t+e,f=n(r,t,u),s=n(r,u,e);return Math.abs(f+s-a)<=15*i?f+s+(f+s-a)/15:o(r,t,u,i/2,f)+o(r,u,e,i/2,s)}var a=r("../numbers"),i=e;i.pointDiff=function(r,t){var e=r(t-.001),n=r(t+.001);return(n-e)/.002},i.Riemann=function(r,t,e,n,o){var a,i=(e-t)/n,u=0;if("function"==typeof o)for(a=t;e>a;a+=i)u+=r(o(a,a+i));else for(a=t;e>a;a+=i)u+=r(a);return u*i},i.adaptiveSimpson=function(r,t,e,i){return i="undefined"==typeof i?a.EPSILON:i,o(r,t,e,n(r,t,e),i)},i.limit=function(r,t,e){if("left"===e)return r(t-1e-15);if("right"===e)return r(t+1e-15);if("middle"===e)return(i.limit(r,t,"left")+i.limit(r,t,"right"))/2;throw new Error("Approach not provided")},i.StirlingGamma=function(r){return Math.sqrt(2*Math.PI/r)*Math.pow(r/Math.E,r)},i.LanczosGamma=function(r){var t,e=[.9999999999998099,676.5203681218851,-1259.1392167224028,771.3234287776531,-176.6150291621406,12.507343278686905,-.13857109526572012,9984369578019572e-21,1.5056327351493116e-7],n=7;if(.5>r)return Math.PI/(Math.sin(Math.PI*r)*i.LanczosGamma(1-r));r-=1;var o=e[0],a=r+n+.5;for(t=1;t=t)throw new Error("Please use a positive integer for N.");var e=[];t=Math.ceil(t);for(var n=2;ne;e++){var n=(this.phase()+2*Math.PI*e)/r,a=Math.pow(this.magnitude(),1/r);t[e]=new o(a*Math.cos(n),a*Math.sin(n))}return t},o.prototype.sin=function(){var r=new o(Math.E,0),t=new o(0,1),e=new o(0,-1),n=r.complexPow(t.multiply(this)).subtract(r.complexPow(e.multiply(this)));return n.divide(new o(0,2))},o.prototype.cos=function(){var r=new o(Math.E,0),t=new o(0,1),e=new o(0,-1),n=r.complexPow(t.multiply(this)).add(r.complexPow(e.multiply(this)));return n.divide(new o(2,0))},o.prototype.tan=function(){return this.sin().divide(this.cos())},o.prototype.equals=function(r,t){return n.numbersEqual(this.re,r.re,t)&&n.numbersEqual(this.im,r.im,t)},t.exports=o},{"../numbers":2}],6:[function(r,t,e){var n=r("../numbers"),o=n.complex,a=e;a.segment=function(r,t,e){for(var n=[],o=t;o=t)return[new o(r[0],0)];if(Math.log(t)/Math.LN2%1!==0)throw new Error("Array length must be integer power of 2");for(var e=a.fft(a.segment(r,0,2)),n=a.fft(a.segment(r,1,2)),i=[],u=t/2,f=0;t>f;f++){var s=-2*Math.PI*f/t,h=new o(Math.cos(s),Math.sin(s));i[f]=u>f?e[f].add(h.multiply(n[f])):e[f-u].subtract(h.multiply(n[f-u]))}return i}},{"../numbers":2}],7:[function(r,t,e){var n=e;n.fibonacci=function(r){for(var t,e=function(r){for(var t,e=[];r>0;)t=2>r?r:r%2,r=Math.floor(r/2),e.push(t);return e.reverse()},n=1,o=0,a=1,i=e(r),u=0;ue;e++)if(r[e].length!==t)return!1;return!0},n.addition=function(r,t){if(r.length!==t.length||r[0].length!==t[0].length)throw new Error("Dimension mismatch");var e,n=new Array(r.length);if(r[0].length)for(e=0;e1?n.transposeMatrix(r):r[0].length?n.transposeColumnVector(r):n.transposeRowVector(r)},n.identity=function(r){for(var t=new Array(r),e=0;r>e;e++){t[e]=new Array(r);for(var n=0;r>n;n++)t[e][n]=e===n?1:0}return t},n.dotproduct=function(r,t){if(r.length!==t.length)throw new Error("Vector mismatch");for(var e=0,n=0;n1&&t[0].length>1?n.multiplyMatMat(r,t):r[0].length>1?n.multiplyMatVec(r,t):n.multiplyVecMat(r,t)},n.determinant=function(r){var t,e,a,i,u=r.length,f=r[0].length,s=0;if(!n.isSquare(r))throw new Error(o);if(1===u)return r[0][0];if(2===u)return r[0][0]*r[1][1]-r[0][1]*r[1][0];for(e=0;f>e;e++){for(a=r[0][e],i=r[0][e],t=1;u>t;t++)i*=r[t][((e+t)%f+f)%f],a*=r[t][((e-t)%f+f)%f];s+=i-a}return s},n.lupDecomposition=function(r){if(!n.isSquare(r))throw new Error(o);var t,e=r.length,a=n.deepCopy(r),i=n.transpose(n.identity(e)),u=new Array(e);this.getL=function(r){for(var t=r[0].length,e=n.identity(t),o=0;t>o;o++)for(var a=0;t>a;a++)o>a&&(e[o][a]=r[o][a]);return e},this.getU=function(r){for(var t=r[0].length,e=n.identity(t),o=0;t>o;o++)for(var a=0;t>a;a++)a>=o&&(e[o][a]=r[o][a]);return e};for(var f=0;e>f;f++){var s;for(s=0;e>s;s++)u[s]=a[s][f];for(s=0;e>s;s++){t=a[s];for(var h=Math.min(s,f),l=0,c=0;h>c;c++)l+=t[c]*u[c];t[f]=u[s]-=l}var m=f;for(s=f+1;e>s;s++)Math.abs(u[s])>Math.abs(u[m])&&(m=s);if(m!==f&&(a=n.rowSwitch(a,m,f),i=n.rowSwitch(i,m,f)),e>f&&0!==a[f][f])for(s=f+1;e>s;s++)a[s][f]/=a[f][f]}return[this.getL(a),this.getU(a),i]},n.rotate=function(r,t,e){n._check2DVector(r);var o="clockwise"===e?-1:1,a=t*(Math.PI/180),i=[[Math.cos(a),-1*o*Math.sin(a)],[o*Math.sin(a),Math.cos(a)]];return n.multiply(i,r)},n.scale=function(r,t,e){n._check2DVector(r);var o=[[t,0],[0,e]];return n.multiply(o,r)},n.shear=function(r,t,e){n._check2DVector(r);var o="xaxis"===e?t:0,a="yaxis"===e?t:0,i=[[1,o],[a,1]];return n.multiply(i,r)},n.affine=function(r,t,e){n._check2DVector(r);var o=[[1,0,t],[0,1,e],[0,0,1]],a=[[r[0][0]],[r[1][0]],[1]],i=n.multiply(o,a);return[[i[0][0]],[i[1][0]]]},n.rowScale=function(r,t,e){for(var n=new Array(r.length),o=0;oMath.abs(r[s][f])&&(s=e);var h=r[f];if(r[f]=r[s],r[s]=h,Math.abs(r[f][f])<=a)return r;for(e=f;++e=0;){for(o=r[f][f],e=-1;++e=f;)r[e][n]-=r[f][n]*r[e][f]/o;for(r[f][f]/=o,n=i-1;++nt;t++)r[t]=r[t].concat(a[t]);for(r=n.GaussJordanEliminate(r),t=0;e>t;t++)r[t]=r[t].slice(e);return r},n.getCol=function(r,t){var e=new Array(r.length);if(0>t)throw new Error("The specified column must be a positive integer.");if(t>=r[0].length)throw new Error("The specified column must be between 0 and the number of columns - 1.");for(var n=0;n=t.length)throw new Error("The desired order of the rows must start at 0 and end at the number of rows - 1.");e.push(r[t[n]])}return e},n.reorderCols=function(r,t){var e=[];if(void 0===t)throw new Error("Please enter a desired reordering array.");if(t.length!==r[0].length)throw new Error("The reordered matrix must have the same number of columns as the original matrix.");for(var o=0;o=t.length)throw new Error("The desired order of the columns must start at 0 and end at the number of columns - 1.");e.push(n.getCol(r,t[o]))}return n.transpose(e)},n.reverseRows=function(r){for(var t=[],e=r.length-1;e>-1;e--)t.push(e);return n.reorderRows(r,t)},n.reverseCols=function(r){for(var t=[],e=r.length-1;e>-1;e--)t.push(e);return n.reorderCols(r,t)},n.zeros=function(r,t){var e=new Array(r);if(1>r||1>t)throw new Error("The matrix dimensions must be positive integers.");r=Math.ceil(r),t=Math.ceil(t);for(var n=0;r>n;n++){for(var o=new Array(t),a=0;t>a;a++)o[a]=0;e[n]=o}return e},n.zigzag=function(r,t,e){if(1>=r)throw new Error("Matrix size must be at least 2x2.");r=Math.ceil(r);var o=n.zeros(r,r),a=function(t){var e,n,o,a,i,u=!1,f=r*r,s=1,h=1;for(t[0][0]=f,t[r-1][r-1]=s,a=1;r>a;a++)u?(f-=4*h,s+=4*h,h++):(f--,s++),t[0][a]=f,t[r-1][r-1-a]=s,u=!u;var l=!0;for(a=1;r>a;a++){for(e=0,n=a,o=t[e][n],i=1;a+1>i;i++)l?o-=1:o+=1,e++,n--,t[e][n]=o;l=!l}for(l=r%2===0?!0:!1,a=1;r-1>a;a++){for(e=r-1,n=a,o=t[e][n],i=1;r-a>i;i++)l?o--:o++,e--,n++,t[e][n]=o;l=!l}return t},i=function(r){return n.transpose(a(r))},u=function(r){return n.reverseCols(a(r))},f=function(r){return n.reverseRows(c(u(r)))},s=function(r){return n.reverseRows(a(r))},h=function(r){return n.reverseRows(i(r))},l=function(r){return n.reverseCols(n.reverseRows(a(r)))},c=function(r){return n.transpose(l(r))};if("BR"===t&&"H"===e)return a(o);if("BR"===t&&"V"===e)return i(o);if("BL"===t&&"H"===e)return u(o);if("BL"===t&&"V"===e)return f(o);if("TR"===t&&"H"===e)return s(o);if("TR"===t&&"V"===e)return h(o);if("TL"===t&&"H"===e)return l(o);if("TL"===t&&"V"===e)return c(o);throw new Error("Enter the direction (V,H) and corner (BR,BL,TR,TL) correctly.")},n.vectorNorm=function(r,t){if(!Array.isArray(r)||0===r.length)throw new Error("Vector must be an array of at least length 1.");if("undefined"!=typeof t&&"number"!=typeof t)throw new Error("Norm order must be a number.");t="undefined"==typeof t?2:t;var e,n,o=r.length,a=0;switch(t){case 1/0:for(n=0;o>n;n++)e=Math.abs(r[n]),e>a&&(a=e);break;case-1/0:for(a=1/0,n=0;o>n;n++)e=Math.abs(r[n]),a>e&&(a=e);break;default:for(n=0;o>n;n++)a+=Math.pow(Math.abs(r[n]),t);a=Math.pow(a,1/t)}return a},n.matrixNorm=function(r,t){if(!Array.isArray(r)||0===r.length||!Array.isArray(r[0]))throw new Error("Matrix must be an array of at least length 1.");if("undefined"!=typeof t&&"number"!=typeof t&&null!==t)throw new Error("Norm order must be a number or null.");t="undefined"==typeof t?null:t;var e,n,o,a=r.length,i=r[0].length,u=0;switch(t){case 1/0:for(n=0;a>n;n++){for(e=0,o=0;i>o;o++)e+=Math.abs(r[n][o]);e>u&&(u=e)}break;case-1/0:for(u=1/0,n=0;a>n;n++){for(e=0,o=0;i>o;o++)e+=Math.abs(r[n][o]);u>e&&(u=e)}break;case 1:for(n=0;i>n;n++){for(e=0,o=0;a>o;o++)e+=Math.abs(r[o][n]);e>u&&(u=e)}break;case-1:for(u=1/0,n=0;i>n;n++){for(e=0,o=0;a>o;o++)e+=Math.abs(r[o][n]);u>e&&(u=e)}break;case null:for(n=0;a>n;n++)for(o=0;i>o;o++)u+=Math.pow(r[n][o],2);u=Math.pow(u,.5);break;case 2:throw new Error("Singular values are not yet supported in numbers.js.");case-2:throw new Error("Singular values are not yet supported in numbers.js.");default:for(n=0;a>n;n++)for(o=0;i>o;o++)u+=Math.pow(Math.abs(r[n][o]),t);u=Math.pow(u,1/t)}return u},n.isUpperBand=function(r,t){if(!Array.isArray(r)||!Array.isArray(r[0])||r.length<2)throw new Error("Matrix must be an array of at least dimension 2.");if("number"!=typeof t||0>t||t%1!==0)throw new Error("Upper bandwidth must be a nonzero integer.");for(var e=!0,n=r[0].length,o=0,a=t+1;n>a;a++){if(0!==r[o][a]){e=!1;break}o++}return e},n.isLowerBand=function(r,t){if(!Array.isArray(r)||!Array.isArray(r[0])||r.length<2)throw new Error("Matrix must be an array of at least dimension 2.");if("number"!=typeof t||0>t||t%1!==0)throw new Error("Lower bandwidth must be a nonzero integer.");for(var e=!0,n=r.length,o=0,a=t+1;n>a;a++){if(0!==r[a][o]){e=!1;break}o++}return e};var i=function(r,t){var e,n=0;for(e=0;t>e;e++)n+=Math.abs(r[e]);for(e=t+1;ee;e++){var a=r[e],u=a[e],f=i(a,e);if(Math.abs(u)e;e++){var a=r[e],u=a[e],f=i(a,e);if(Math.abs(u)<=f)return!1}return!0},n.isColumnDD=function(r){if(!n.isSquare)throw new Error(o);for(var t=r.length,e=0;t>e;e++){var a=n.getCol(r,e),u=a[e],f=i(a,e);if(Math.abs(u)e;e++){var a=n.getCol(r,e),u=a[e],f=i(a,e);if(Math.abs(u)<=f)return!1}return!0}},{}],9:[function(r,t,e){var n=r("./basic"),o=e;o.simple=function(r){if(isNaN(r)||!isFinite(r)||r%1||2>r)return!1;if(r%2===0)return 2===r;if(r%3===0)return 3===r;for(var t=5,e=Math.sqrt(r);e>=t;t+=6)if(r%t===0||r%(t+2)===0)return!1;return!0},o.factorization=function(r){r=Math.floor(r);for(var t,e,n=[],o=Math.sqrt,a=r>1&&isFinite(r);a;){if(t=o(r),e=2,r%e)for(e=3;r%e&&(e+=2)t?r:e,n.push(e),a=e!==r,r/=e}return n},o.millerRabin=function(r,t){if(1===arguments.length&&(t=20),2===r)return!0;if(!n.isInt(r)||1>=r||r%2===0)return!1;for(var e=0,o=r-1;;){var a=n.divMod(o,2),i=a[0],u=a[1];if(1===u)break;e+=1,o=i}for(var f=function(t){if(1===n.powerMod(t,o,r))return!1;for(var a=0;e>a;a++)if(n.powerMod(t,Math.pow(2,a)*o,r)===r-1)return!1;return!0},s=0;t>s;s++){var h=2+Math.floor(Math.random()*(r-2-2));if(f(h))return!1}return!0},o.sieve=function(r){if(2>r)return[];for(var t=[2],e=3;r>=e;e++){var n=!1;for(var o in t)n=n||0===e%t[o];n||t.push(e)}return t},o.coprime=function(r,t){return 1===n.gcd(r,t)},o.getPerfectPower=function(r){var t=o.getPrimePower(r);return t&&t[1]>1?t:!1},o.getPrimePower=function(r){if(2>r)return!1;if(o.millerRabin(r))return[r,1];if(r%2===0)return[2,r.toString(2).length-1];var t=o.factorization(r);if(!t)return!1;for(var e=t.length,n=0;e>n;n++)for(var a=0,i=0;r>=a;){if(a=Math.pow(t[n],i),a/r===1)return[t[n],i];i++}return!1}},{"./basic":3}],10:[function(r,t,e){var n=e,o=Math.random;n.setGenerator=function(r){if("function"!=typeof r)throw new Error("Must pass a function");o=r},n.sample=function(r,t,e){var n=[];n.length=e;for(var a=0;e>a;a++)n[a]=r+(t-r)*o();return n},n.boxMullerTransform=function(r,t){arguments.length<=1&&(t=1),0===arguments.length&&(r=0);var e,n=0,a=0;do n=2*o()-1,a=2*o()-1,e=n*n+a*a;while(0===e||e>1);var i=Math.sqrt(-2*Math.log(e)/e),u=n*i,f=a*i;return u=r+u*t,f=r+f*t,[u,f]},n.irwinHall=function(r,t){1===arguments.length&&(t=0);for(var e=0,n=0;r>n;n++)e+=o();return e-t},n.bates=function(r,t,e){arguments.length<=2&&(e=0),1===arguments.length&&(t=1);for(var n=0,a=0;r>a;a++)n+=(t-e)*o()+e;return n/r},n.distribution={},n.distribution.normal=function(r,t,e){return arguments.length<=2&&(e=1),1===arguments.length&&(t=0),n.distribution.boxMuller(r,t,e)},n.distribution.logNormal=function(r,t,e){arguments.length<=2&&(e=1),1===arguments.length&&(t=0);var o=function(r){return Math.exp(r)};return n.distribution.boxMuller(r,t,e).map(o)},n.distribution.boxMuller=function(r,t,e,o){arguments.length<=3&&(o=!1),arguments.length<=2&&(e=1),1===arguments.length&&(t=0);for(var a=[],i=0;r>i;i++){var u=n.boxMullerTransform(t,e);a.push(o?u:u[0])}return a},n.distribution.irwinHall=function(r,t,e){arguments.length<=2&&(e=0),1===arguments.length&&(t=r);for(var o=new Array(r),a=0;r>a;a++)o[a]=n.irwinHall(t,e);return o},n.distribution.irwinHallNormal=function(r){return n.distribution.irwinHall(r,12,6)},n.distribution.bates=function(r,t,e){arguments.length<=2&&(e=0),1===arguments.length&&(t=r);for(var o=new Array(r),a=0;r>a;a++)o[a]=n.bates(r,t,e);return o}},{}],11:[function(r,t,e){var n=r("./basic"),o=e;o.mean=function(r){var t=r.length,e=n.sum(r);return e/t},o.median=function(r){return o.quantile(r,1,2)},o.mode=function(r){for(var t={},e=0,n=r.length;n>e;e++)void 0===t[r[e]]?t[r[e]]=0:t[r[e]]++;var o;for(var a in t)t.hasOwnProperty(a)&&(void 0===o||t[a]>t[o])&&(o=a);return Number(o)},o.quantile=function(r,t,e){var n,o,a;return 0===t?Math.min.apply(null,r):t===e?Math.max.apply(null,r):(n=r.slice(0),n.sort(function(r,t){return r-t}),o=n.length,a=o*t/e,a%1===0?.5*n[a-1]+.5*n[a]:n[Math.floor(a)])},o.report=function(r){return{mean:o.mean(r),firstQuartile:o.quantile(r,1,4),median:o.median(r),thirdQuartile:o.quantile(r,3,4),standardDev:o.standardDev(r)}},o.standardDev=function(r){for(var t=r.length,e=o.mean(r),a=[],i=0;iu;u++)o+=r[u]*t[u];return(o-a*i/e)/e}throw new Error("Array mismatch")}},{"./basic":3}]},{},[1])(1)}); \ No newline at end of file diff --git a/test/basic.test.js b/test/basic.test.js index 2736c51..7ba82ab 100644 --- a/test/basic.test.js +++ b/test/basic.test.js @@ -2,380 +2,380 @@ var assert = require('assert'); var numbers = require('../index.js'); var basic = numbers.basic; -suite('numbers', function() { - - console.log('\n\n\033[34mTesting Standard Mathematics\033[0m'); - - // longList is used by basic.max() and basic.min() - // to test for `Maximum call stack size exceeded` exception. - var longList = [], - len = 1e7, - sign; - while (0 < len--) { - sign = (Math.random() < 0.5) ? -1 : 1; - longList.push(sign * Math.floor(Math.random() * 1e5)); - } - longList.push(1e6); - longList.push(-1e6); - - // basic.sum - test('sum should return the sum of items in an array', function(done) { - assert.equal(basic.sum([0, 1, 2, 3]), 6); - assert.equal(basic.sum([0, -3, 5, -2]), 0); - done(); - }); - - test('sum should throw an exception when given anything but an array', function(done) { - assert.throws( - function() { - basic.sum(1); - }, - /Input must be of type Array/ - ); - done(); - }); - - test('sum should throw an exception when given anything objects other than numbers', function(done) { - assert.throws( - function() { - basic.sum([1, 2, "error"]); - }, - /All elements in array must be numbers/ - ); - done(); - }); - - // basic.substraction - test('subtraction should return the difference of items in an array', function(done) { - assert.equal(basic.subtraction([5, 3, 1, -1]), 2); - done(); - }); - - test('subtraction should throw an exception when given anything but an array', function(done) { - assert.throws( - function() { - basic.subtraction(1); - }, - /Input must be of type Array/ - ); - done(); - }); - - test('subtraction should throw an exception when given anything objects other than numbers', function(done) { - assert.throws( - function() { - basic.subtraction(["test", 1, 1, 2]); - }, - /All elements in array must be numbers/ - ); - done(); - }); - - test('subtraction should throw an exception last element is not a number', function(done) { - assert.throws( - function() { - basic.subtraction([1, 1, 2, "test"]); - }, - /All elements in array must be numbers/ - ); - done(); - }); - - // basic.product - test('product should return the product of items in an array', function(done) { - assert.equal(basic.product([1, 2, 3, 4]), 24); - assert.equal(basic.product([-3, 2]), -6); - done(); - }); - - test('product should throw an exception when given anything but an array', function(done) { - assert.throws( - function() { - basic.product(1); - }, - /Input must be of type Array/ - ); - done(); - }); - - test('product should throw an exception when given anything objects other than numbers', function(done) { - assert.throws( - function() { - basic.product([1, 2, "error"]); - }, - /All elements in array must be numbers/ - ); - done(); - }); - - test('product should throw an exception when given anything objects other than numbers', function(done) { - assert.throws( - function() { - basic.product(["error", 1, 2]); - }, - /All elements in array must be numbers/ - ); - done(); - }); - - test('square should return the square of a number', function(done) { - assert.equal(basic.square(4), 16); - done(); - }); - - test('square should throw an Error when input is other than a number', function(done) { - assert.throws( - function() { - basic.square('error'); - }, - /Input must be a number/ - ); - done(); - }); - - // basic.binomial - test('binomial should return the binomial coefficient (n choose k) of two numbers', function(done) { - assert.equal(basic.binomial(5, 3), 10); - assert.throws( - function() { - basic.binomial('error'); - }, - /Input must be a number/ - ); - done(); - }); - - // basic.factorial - test('factorial should return the product of n * (n - 1) * (n - 2) * ... * 1', function(done) { - assert.equal(basic.factorial(4), 24); - assert.equal(basic.factorial(5), 120); - assert.throws( - function() { - basic.factorial('error'); - basic.factorial(-1); - }, - /Input must be a number/, - /Input must not be negative/ - ); - done(); - }); - - // basic.gcd - test('gcd should throw an exception when given a decimal', function(done) { - assert.throws( - function() { - basic.gcd(0.2, 1); - }, - /Can only operate on integers/ - ); - done(); - }); - test('gcd should return the greatest common denominator of two integers', function(done) { - assert.equal(basic.gcd(1254, 0), 1254); - assert.equal(basic.gcd(0, -5298), 5298); - assert.equal(basic.gcd(0, -Infinity), Infinity); - assert.equal(basic.gcd(4430, -Infinity), Infinity); - assert.equal(basic.gcd(-1254, -5298), 6); - assert.equal(basic.gcd(1254, 5298), 6); - assert.equal(basic.gcd(78699786, 78978965), 1); - done(); - }); - - // basic.lcm - test('lcm should return the least common multiple of two integers', function(done) { - assert.equal(basic.lcm(4, 0), 0); - assert.equal(basic.lcm(0, 4), 0); - assert.equal(isNaN(basic.lcm(4, Infinity)), true); - assert.equal(isNaN(basic.lcm(Infinity, 4)), true); - assert.equal(basic.lcm(4, 5), 20); - assert.equal(basic.lcm(3, 4), 12); - assert.equal(basic.lcm(4, 6), 12); - assert.equal(basic.lcm(21, 6), 42); - assert.equal(basic.lcm(12, 80), 240); - done(); - }); - - // basic.max - test('basic.max will throw an exception if argument is not an array.', function(done) { - assert.throws( - function() { - basic.max(65, 40); - }, - /Input must be of type Array/ - ); - done(); - }); - - test('max should return the biggest number in an array', function(done) { - assert.equal(basic.max([1, 2, 3, 42]), 42); - assert.equal(basic.max([-1, -2, -3, -42]), -1); - assert.equal(basic.max([1, Infinity]), Infinity); - assert.equal(basic.max(longList), 1000000); - done(); - }); - - // basic.min - test('basic.min will throw an exception if argument is not an array.', function(done) { - assert.throws( - function() { - basic.min(65, 40); - }, - /Input must be of type Array/ - ); - done(); - }); - - test('min should return the smallest number in an array', function(done) { - assert.equal(basic.min([1, 2, 3, 42]), 1); - assert.equal(basic.min([-1, -2, -3, -42]), -42); - assert.equal(basic.min([1, -Infinity]), -Infinity); - assert.equal(basic.min(longList), -1000000); - done(); - }); - - // basic.range - test('range should return an appropriate range for the given start, stop, and step parameters', function(done) { - assert.deepEqual(basic.range(1, 10), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); - assert.deepEqual(basic.range(10, 1), [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]); - assert.deepEqual(basic.range(1, 5, 0.5), [1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]); - assert.deepEqual(basic.range(5, 1, 0.5), [5, 4.5, 4, 3.5, 3, 2.5, 2, 1.5, 1]); - done(); - - }); - - // basic.isInt - test('isInt checks for an integer', function(done) { - assert.equal(basic.isInt(2.32), false); - assert.equal(basic.isInt('true'), false); - assert.equal(basic.isInt('2'), true); //based off impelementation change - assert.equal(basic.isInt(2), true); - done(); - }); - - // basic.divMod - test('divMod should return an array of both the division and modulus values of two integers', function(done) { - assert.deepEqual(basic.divMod(12, 6), [2, 0]); - assert.deepEqual(basic.divMod(10, 3), [3, 1]); - test('divMod should throw an exception when given a decimal', function(done) { - assert.throws( - function() { - basic.divMod(0.2, 0.1); - }, - /Can only operate on integers/ - ); - done(); - }); - done(); - }); - - // basic.egcd - test('egcd should throw an exception when given a decimal', function(done) { - assert.throws( - function() { - basic.egcd(0.2, 1); - }, - /Can only operate on integers/ - ); - done(); - }); - test('egcd should return the array [a, x, y] which is the solved linear equation for GCD', function(done) { - assert.equal(basic.egcd('ten', 1).toString(), 'NaN,NaN,NaN'); - assert.deepEqual(basic.egcd(1, Infinity), [Infinity, Infinity, Infinity]); - assert.deepEqual(basic.egcd(3, 0), [3, 1, 0]); - assert.deepEqual(basic.egcd(0, 3), [3, 0, 1]); - assert.deepEqual(basic.egcd(-2, -6), [2, -1, 0]); - assert.deepEqual(basic.egcd(-2, 5), [1, 2, 1]); - assert.deepEqual(basic.egcd(65, 40), [5, -3, 5]); - assert.deepEqual(basic.egcd(40, 65), [5, 5, -3]); - assert.deepEqual(basic.egcd(1239, 735), [21, -16, 27]); - assert.deepEqual(basic.egcd(105, 252), [21, 5, -2]); - assert.deepEqual(basic.egcd(252, 105), [21, -2, 5]); - done(); - }); - - // basic.modInverse - test('modInverse will return the modulo m inverse of a', function(done) { - assert.equal(basic.modInverse(1, 5), 1); - done(); - }); - - test('modInverse will throw an exception if no modular inverse exists', function(done) { - assert.throws( - function() { - basic.modInverse(65, 40); - }, - /No modular inverse exists/ - ); - done(); - }); - - // basic.powerMod - test('powerMod should return the answer to a^b mod m', function(done) { - assert.equal(basic.powerMod(1, -1, 5), 1); - assert.equal(basic.powerMod(2, 10, 3), 1); - assert.equal(basic.powerMod(2, Math.pow(10, 9), 18), 16); - assert.equal(basic.powerMod(6, 0.5, 10), 6); - assert.equal(basic.powerMod(4, 13, 497), 445); - test('powerMod should throw an exception when given a non number', function(done) { - assert.throws( - function() { - basic.powerMod('error', 'error', 'error'); - }, - /Can only operate on numbers/ - ); - done(); - }); - done(); - }); - - - test('should be able to check equality of two floating point numbers', function(done) { - assert.equal(basic.numbersEqual(5, 5, numbers.EPSILON), true); - assert.equal(basic.numbersEqual(5.0001, 5.0000001, numbers.EPSILON), true); - assert.equal(basic.numbersEqual(-5, 5, numbers.EPSILON), false); - assert.equal(basic.numbersEqual(5, 5.1, numbers.EPSILON), false); - assert.equal(basic.numbersEqual(5, 5.001, numbers.EPSILON), false); - test('numbersEqual should throw an exception when given a non number', function(done) { - assert.throws( - function() { - basic.powerMod('error', 'error', .2); - }, - /Can only operate on numbers/ - ); - done(); - }); - done(); - }); - - // basic.fallingFactorial - test('fallingFactorial should return correct answers', function(done) { - var func = basic.fallingFactorial; - - assert.equal(func(0, 0), 1); //allows n=0 - assert.equal(func(7, 0), 1); //k = 0 returns 1. - - assert.equal(func(7, 7), 5040); //n=k returns n! - assert.equal(func(7, 4), 840); - - assert.throws( - function() { - func(-2, 5); - func(2,4); - }, - /negative/, - /k is greater than n/ - ); - - done(); - }); - - // basic.permutation - test('permutation should return the permutation coefficient (n permute k) of two numbers', function(done) { - assert.equal(basic.permutation(5, 0), 1); - assert.equal(basic.permutation(5, 1), 5); - assert.equal(basic.permutation(5, 4), 120); - assert.equal(basic.permutation(5, 5), 120); - done(); - }); +suite('numbers', function () { + + console.log('\n\n\033[34mTesting Standard Mathematics\033[0m'); + + // longList is used by basic.max() and basic.min() + // to test for `Maximum call stack size exceeded` exception. + var longList = [], + len = 1e7, + sign; + while (0 < len--) { + sign = (Math.random() < 0.5) ? -1 : 1; + longList.push(sign * Math.floor(Math.random() * 1e5)); + } + longList.push(1e6); + longList.push(-1e6); + + // basic.sum + test('sum should return the sum of items in an array', function (done) { + assert.equal(basic.sum([0, 1, 2, 3]), 6); + assert.equal(basic.sum([0, -3, 5, -2]), 0); + done(); + }); + + test('sum should throw an exception when given anything but an array', function (done) { + assert.throws( + function () { + basic.sum(1); + }, + /Input must be of type Array/ + ); + done(); + }); + + test('sum should throw an exception when given anything objects other than numbers', function (done) { + assert.throws( + function () { + basic.sum([1, 2, "error"]); + }, + /All elements in array must be numbers/ + ); + done(); + }); + + // basic.substraction + test('subtraction should return the difference of items in an array', function (done) { + assert.equal(basic.subtraction([5, 3, 1, -1]), 2); + done(); + }); + + test('subtraction should throw an exception when given anything but an array', function (done) { + assert.throws( + function () { + basic.subtraction(1); + }, + /Input must be of type Array/ + ); + done(); + }); + + test('subtraction should throw an exception when given anything objects other than numbers', function (done) { + assert.throws( + function () { + basic.subtraction(["test", 1, 1, 2]); + }, + /All elements in array must be numbers/ + ); + done(); + }); + + test('subtraction should throw an exception last element is not a number', function (done) { + assert.throws( + function () { + basic.subtraction([1, 1, 2, "test"]); + }, + /All elements in array must be numbers/ + ); + done(); + }); + + // basic.product + test('product should return the product of items in an array', function (done) { + assert.equal(basic.product([1, 2, 3, 4]), 24); + assert.equal(basic.product([-3, 2]), -6); + done(); + }); + + test('product should throw an exception when given anything but an array', function (done) { + assert.throws( + function () { + basic.product(1); + }, + /Input must be of type Array/ + ); + done(); + }); + + test('product should throw an exception when given anything objects other than numbers', function (done) { + assert.throws( + function () { + basic.product([1, 2, "error"]); + }, + /All elements in array must be numbers/ + ); + done(); + }); + + test('product should throw an exception when given anything objects other than numbers', function (done) { + assert.throws( + function () { + basic.product(["error", 1, 2]); + }, + /All elements in array must be numbers/ + ); + done(); + }); + + test('square should return the square of a number', function (done) { + assert.equal(basic.square(4), 16); + done(); + }); + + test('square should throw an Error when input is other than a number', function (done) { + assert.throws( + function () { + basic.square('error'); + }, + /Input must be a number/ + ); + done(); + }); + + // basic.binomial + test('binomial should return the binomial coefficient (n choose k) of two numbers', function (done) { + assert.equal(basic.binomial(5, 3), 10); + assert.throws( + function () { + basic.binomial('error'); + }, + /Input must be a number/ + ); + done(); + }); + + // basic.factorial + test('factorial should return the product of n * (n - 1) * (n - 2) * ... * 1', function (done) { + assert.equal(basic.factorial(4), 24); + assert.equal(basic.factorial(5), 120); + assert.throws( + function () { + basic.factorial('error'); + basic.factorial(-1); + }, + /Input must be a number/, + /Input must not be negative/ + ); + done(); + }); + + // basic.gcd + test('gcd should throw an exception when given a decimal', function (done) { + assert.throws( + function () { + basic.gcd(0.2, 1); + }, + /Can only operate on integers/ + ); + done(); + }); + test('gcd should return the greatest common denominator of two integers', function (done) { + assert.equal(basic.gcd(1254, 0), 1254); + assert.equal(basic.gcd(0, -5298), 5298); + assert.equal(basic.gcd(0, -Infinity), Infinity); + assert.equal(basic.gcd(4430, -Infinity), Infinity); + assert.equal(basic.gcd(-1254, -5298), 6); + assert.equal(basic.gcd(1254, 5298), 6); + assert.equal(basic.gcd(78699786, 78978965), 1); + done(); + }); + + // basic.lcm + test('lcm should return the least common multiple of two integers', function (done) { + assert.equal(basic.lcm(4, 0), 0); + assert.equal(basic.lcm(0, 4), 0); + assert.equal(isNaN(basic.lcm(4, Infinity)), true); + assert.equal(isNaN(basic.lcm(Infinity, 4)), true); + assert.equal(basic.lcm(4, 5), 20); + assert.equal(basic.lcm(3, 4), 12); + assert.equal(basic.lcm(4, 6), 12); + assert.equal(basic.lcm(21, 6), 42); + assert.equal(basic.lcm(12, 80), 240); + done(); + }); + + // basic.max + test('basic.max will throw an exception if argument is not an array.', function (done) { + assert.throws( + function () { + basic.max(65, 40); + }, + /Input must be of type Array/ + ); + done(); + }); + + test('max should return the biggest number in an array', function (done) { + assert.equal(basic.max([1, 2, 3, 42]), 42); + assert.equal(basic.max([-1, -2, -3, -42]), -1); + assert.equal(basic.max([1, Infinity]), Infinity); + assert.equal(basic.max(longList), 1000000); + done(); + }); + + // basic.min + test('basic.min will throw an exception if argument is not an array.', function (done) { + assert.throws( + function () { + basic.min(65, 40); + }, + /Input must be of type Array/ + ); + done(); + }); + + test('min should return the smallest number in an array', function (done) { + assert.equal(basic.min([1, 2, 3, 42]), 1); + assert.equal(basic.min([-1, -2, -3, -42]), -42); + assert.equal(basic.min([1, -Infinity]), -Infinity); + assert.equal(basic.min(longList), -1000000); + done(); + }); + + // basic.range + test('range should return an appropriate range for the given start, stop, and step parameters', function (done) { + assert.deepEqual(basic.range(1, 10), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + assert.deepEqual(basic.range(10, 1), [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]); + assert.deepEqual(basic.range(1, 5, 0.5), [1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]); + assert.deepEqual(basic.range(5, 1, 0.5), [5, 4.5, 4, 3.5, 3, 2.5, 2, 1.5, 1]); + done(); + + }); + + // basic.isInt + test('isInt checks for an integer', function (done) { + assert.equal(basic.isInt(2.32), false); + assert.equal(basic.isInt('true'), false); + assert.equal(basic.isInt('2'), true); //based off impelementation change + assert.equal(basic.isInt(2), true); + done(); + }); + + // basic.divMod + test('divMod should return an array of both the division and modulus values of two integers', function (done) { + assert.deepEqual(basic.divMod(12, 6), [2, 0]); + assert.deepEqual(basic.divMod(10, 3), [3, 1]); + test('divMod should throw an exception when given a decimal', function (done) { + assert.throws( + function () { + basic.divMod(0.2, 0.1); + }, + /Can only operate on integers/ + ); + done(); + }); + done(); + }); + + // basic.egcd + test('egcd should throw an exception when given a decimal', function (done) { + assert.throws( + function () { + basic.egcd(0.2, 1); + }, + /Can only operate on integers/ + ); + done(); + }); + test('egcd should return the array [a, x, y] which is the solved linear equation for GCD', function (done) { + assert.equal(basic.egcd('ten', 1).toString(), 'NaN,NaN,NaN'); + assert.deepEqual(basic.egcd(1, Infinity), [Infinity, Infinity, Infinity]); + assert.deepEqual(basic.egcd(3, 0), [3, 1, 0]); + assert.deepEqual(basic.egcd(0, 3), [3, 0, 1]); + assert.deepEqual(basic.egcd(-2, -6), [2, -1, 0]); + assert.deepEqual(basic.egcd(-2, 5), [1, 2, 1]); + assert.deepEqual(basic.egcd(65, 40), [5, -3, 5]); + assert.deepEqual(basic.egcd(40, 65), [5, 5, -3]); + assert.deepEqual(basic.egcd(1239, 735), [21, -16, 27]); + assert.deepEqual(basic.egcd(105, 252), [21, 5, -2]); + assert.deepEqual(basic.egcd(252, 105), [21, -2, 5]); + done(); + }); + + // basic.modInverse + test('modInverse will return the modulo m inverse of a', function (done) { + assert.equal(basic.modInverse(1, 5), 1); + done(); + }); + + test('modInverse will throw an exception if no modular inverse exists', function (done) { + assert.throws( + function () { + basic.modInverse(65, 40); + }, + /No modular inverse exists/ + ); + done(); + }); + + // basic.powerMod + test('powerMod should return the answer to a^b mod m', function (done) { + assert.equal(basic.powerMod(1, -1, 5), 1); + assert.equal(basic.powerMod(2, 10, 3), 1); + assert.equal(basic.powerMod(2, Math.pow(10, 9), 18), 16); + assert.equal(basic.powerMod(6, 0.5, 10), 6); + assert.equal(basic.powerMod(4, 13, 497), 445); + test('powerMod should throw an exception when given a non number', function (done) { + assert.throws( + function () { + basic.powerMod('error', 'error', 'error'); + }, + /Can only operate on numbers/ + ); + done(); + }); + done(); + }); + + + test('should be able to check equality of two floating point numbers', function (done) { + assert.equal(basic.numbersEqual(5, 5, numbers.EPSILON), true); + assert.equal(basic.numbersEqual(5.0001, 5.0000001, numbers.EPSILON), true); + assert.equal(basic.numbersEqual(-5, 5, numbers.EPSILON), false); + assert.equal(basic.numbersEqual(5, 5.1, numbers.EPSILON), false); + assert.equal(basic.numbersEqual(5, 5.001, numbers.EPSILON), false); + test('numbersEqual should throw an exception when given a non number', function (done) { + assert.throws( + function () { + basic.powerMod('error', 'error', 0.2); + }, + /Can only operate on numbers/ + ); + done(); + }); + done(); + }); + + // basic.fallingFactorial + test('fallingFactorial should return correct answers', function (done) { + var func = basic.fallingFactorial; + + assert.equal(func(0, 0), 1); //allows n=0 + assert.equal(func(7, 0), 1); //k = 0 returns 1. + + assert.equal(func(7, 7), 5040); //n=k returns n! + assert.equal(func(7, 4), 840); + + assert.throws( + function () { + func(-2, 5); + func(2, 4); + }, + /negative/, + /k is greater than n/ + ); + + done(); + }); + + // basic.permutation + test('permutation should return the permutation coefficient (n permute k) of two numbers', function (done) { + assert.equal(basic.permutation(5, 0), 1); + assert.equal(basic.permutation(5, 1), 5); + assert.equal(basic.permutation(5, 4), 120); + assert.equal(basic.permutation(5, 5), 120); + done(); + }); }); diff --git a/test/calculus.test.js b/test/calculus.test.js index ba53d62..a87a933 100644 --- a/test/calculus.test.js +++ b/test/calculus.test.js @@ -2,22 +2,22 @@ var assert = require('assert'); var numbers = require('../index.js'); var calculus = numbers.calculus; -suite('numbers', function() { +suite('numbers', function () { console.log('\n\n\033[34mTesting Calculus Mathematics\033[0m'); - test('pointDiff should return the derivative at a point, provided function', function(done) { + test('pointDiff should return the derivative at a point, provided function', function (done) { var func = function (x) { return 2 * x + 2; }; var res = calculus.pointDiff(func, 5); - + assert.equal(2 - res < numbers.EPSILON, true); done(); }); - test('riemann should return an estimated definite integral of a function', function(done) { + test('riemann should return an estimated definite integral of a function', function (done) { var func = function (x) { return 2 * Math.pow(x, 2); }; @@ -28,7 +28,7 @@ suite('numbers', function() { done(); }); - test('adaptive simpson should return an estimated definite integral of a function', function(done) { + test('adaptive simpson should return an estimated definite integral of a function', function (done) { var func = function (x) { return 2 * Math.pow(x, 2); }; @@ -39,7 +39,7 @@ suite('numbers', function() { done(); }); - test('limit should return the limit of a function at a given point from left, middle, or right', function(done) { + test('limit should return the limit of a function at a given point from left, middle, or right', function (done) { var func = function (x) { return Math.pow(x, 2) * Math.sin(2 * x); }; diff --git a/test/complex.test.js b/test/complex.test.js index 3548d6a..407e33f 100644 --- a/test/complex.test.js +++ b/test/complex.test.js @@ -3,11 +3,11 @@ var numbers = require('../index.js'); var Complex = numbers.complex; var basic = numbers.basic; -suite('numbers', function() { +suite('numbers', function () { console.log('\n\n\033[34mTesting Complex Numbers\033[0m'); - test('add should return the sum of two complex numbers', function(done) { + test('add should return the sum of two complex numbers', function (done) { var A = new Complex(3, 4); var B = new Complex(5, 6); var res = A.add(B); @@ -19,7 +19,7 @@ suite('numbers', function() { done(); }); - test('subtract should return the difference of two complex numbers', function(done) { + test('subtract should return the difference of two complex numbers', function (done) { var A = new Complex(5, 8); var B = new Complex(3, 4); var res = A.subtract(B); @@ -29,34 +29,34 @@ suite('numbers', function() { done(); }); - test('multiply should return the product of two complex numbers', function(done) { + test('multiply should return the product of two complex numbers', function (done) { var A = new Complex(3, 4); var B = new Complex(5, 6); var res = A.multiply(B); - + assert.equal(res.re, -9); assert.equal(res.im, 38); done(); }); - test('divide should return the product of two complex numbers', function(done) { + test('divide should return the product of two complex numbers', function (done) { var A = new Complex(10, 0); var B = new Complex(0, 10); var res = A.divide(B); - + assert.equal(res.re, 0); assert.equal(res.im, -1); done(); }); - test('magnitude should return magnitude', function(done) { + test('magnitude should return magnitude', function (done) { var A = new Complex(3, 4); assert.equal(A.magnitude(), 5); done(); }); - test('phase should return phase', function(done) { + test('phase should return phase', function (done) { var A = new Complex(3, 4); var res = A.phase(); @@ -64,7 +64,7 @@ suite('numbers', function() { done(); }); - test('magnitude should return complex conjugate', function(done) { + test('magnitude should return complex conjugate', function (done) { var A = new Complex(3, 4); assert.equal(A.conjugate().re, 3); @@ -72,7 +72,7 @@ suite('numbers', function() { done(); }); - test('should be able to get the power of a complex number', function(done) { + test('should be able to get the power of a complex number', function (done) { var A = new Complex(3, 4); var justImaginary = new Complex(0, 4); var justNegativeImaginary = new Complex(0, -4); @@ -87,7 +87,7 @@ suite('numbers', function() { done(); }); - test('should be able to raise a complex number to a given complex power', function(done) { + test('should be able to raise a complex number to a given complex power', function (done) { var A = new Complex(0, 1); var B = new Complex(0, -1); @@ -100,34 +100,34 @@ suite('numbers', function() { done(); }); - test('should be able to get all the roots of a complex number', function(done) { + test('should be able to get all the roots of a complex number', function (done) { var A = new Complex(3, -4); var root = 5; var roots = A.roots(root); assert.equal(roots.length, root); - for(var i = 0; i < root; i++) { - assert.equal(roots[i].pow(root).equals(A, numbers.EPSILON), true); + for (var i = 0; i < root; i++) { + assert.equal(roots[i].pow(root).equals(A, numbers.EPSILON), true); } done(); }); - test('should be able to get the sine of a complex number', function(done) { + test('should be able to get the sine of a complex number', function (done) { var A = new Complex(3, -4); assert.equal(A.sin().equals(new Complex(3.8537, 27.0168), numbers.EPSILON), true); done(); }); - test('should be able to get the cosine of a complex number', function(done) { + test('should be able to get the cosine of a complex number', function (done) { var A = new Complex(3, -4); assert.equal(A.cos().equals(new Complex(-27.0349, 3.8511), numbers.EPSILON), true); done(); }); - test('should be able to get the tangent of a complex number', function(done) { + test('should be able to get the tangent of a complex number', function (done) { var A = new Complex(3, -4); var expected = A.sin().divide(A.cos()); @@ -135,8 +135,8 @@ suite('numbers', function() { done(); }); - test('should be able to check for equality of two complex numbers', function(done) { - var A = new Complex(3,4); + test('should be able to check for equality of two complex numbers', function (done) { + var A = new Complex(3, 4); assert.equal(A.equals(new Complex(3, 4), numbers.EPSILON), true); assert.equal(A.equals(new Complex(3, 4.0001), numbers.EPSILON), true); diff --git a/test/dsp.test.js b/test/dsp.test.js index 2dd1743..cf08f51 100644 --- a/test/dsp.test.js +++ b/test/dsp.test.js @@ -2,18 +2,19 @@ var assert = require('assert'); var numbers = require('../index.js'); var dsp = numbers.dsp; -suite('numbers', function() { +suite('numbers', function () { console.log('\n\n\033[34mTesting DSP Tools\033[0m'); - test('segment should return a sample of the input array', function(done) { - var res = dsp.segment([1, 2, 3, 4, 5, 6, 7, 8, 9], 2, 3), a = [3, 6, 9]; - - assert.equal(res[0] == a[0] && res[1] == a[1] && res[2] == a[2], true); + test('segment should return a sample of the input array', function (done) { + var res = dsp.segment([1, 2, 3, 4, 5, 6, 7, 8, 9], 2, 3), + a = [3, 6, 9]; + + assert.equal(res[0] === a[0] && res[1] === a[1] && res[2] === a[2], true); done(); }); - test('fft should return fourier transform of input array', function(done) { + test('fft should return fourier transform of input array', function (done) { var res = dsp.fft([1, 1, 1, 1, 0, 0, 0, 0]); assert.equal(res[0].re - numbers.EPSILON < 4 && 4 < res[0].re + numbers.EPSILON, true); diff --git a/test/generators.test.js b/test/generators.test.js index 1455183..909c893 100644 --- a/test/generators.test.js +++ b/test/generators.test.js @@ -2,7 +2,7 @@ var assert = require('assert'); var numbers = require('../index.js'); var generate = numbers.generate; -suite('numbers', function() { +suite('numbers', function () { console.log('\n\n\033[34mTesting Generators\033[0m'); @@ -18,7 +18,7 @@ suite('numbers', function() { test('collatz should populate the given array with a collatz sequence', function (done) { var result = []; generate.collatz(7, result); - assert.equal(result.join(','), [ 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1 ].join(',')); + assert.equal(result.join(','), [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1].join(',')); done(); }); diff --git a/test/matrix.test.js b/test/matrix.test.js index f7712c2..4e03c7f 100644 --- a/test/matrix.test.js +++ b/test/matrix.test.js @@ -2,11 +2,11 @@ var assert = require('assert'); var numbers = require('../index.js'); var matrix = numbers.matrix; -suite('numbers', function() { +suite('numbers', function () { console.log('\n\n\033[34mTesting Matrix Mathematics\033[0m'); - test('should create a deep copy of a matrix', function(done) { + test('should create a deep copy of a matrix', function (done) { var input = [ [1, 2], [2, 1] @@ -17,7 +17,7 @@ suite('numbers', function() { assert.notEqual(input, copy); assert.throws( - function() { + function () { matrix.deepCopy([1, 2]); }, /Input cannot be a vector./ @@ -26,7 +26,7 @@ suite('numbers', function() { done(); }); - test('should be able to tell if a matrix is square', function(done) { + test('should be able to tell if a matrix is square', function (done) { assert.equal(matrix.isSquare([ [1, 2], [3, 4] @@ -53,7 +53,7 @@ suite('numbers', function() { done(); }); - test('should return sum of two matrices', function(done) { + test('should return sum of two matrices', function (done) { var arrA = [ [0, 1, 2], [3, 4, 5] @@ -75,7 +75,7 @@ suite('numbers', function() { done(); }); - test('should return sum of two vectors', function(done) { + test('should return sum of two vectors', function (done) { var arrA = [0, 1, 2]; var arrB = [3, 4, 5]; @@ -87,7 +87,7 @@ suite('numbers', function() { done(); }); - test('should return difference of two vectors', function(done) { + test('should return difference of two vectors', function (done) { var arrA = [0, 1, 2]; var arrB = [3, 4, 5]; var expected1 = [-3, -3, -3]; @@ -97,7 +97,7 @@ suite('numbers', function() { done(); }); - test('should returned scaled matrix', function(done) { + test('should returned scaled matrix', function (done) { var array = [ [0, 1, 2], [3, 4, 5] @@ -113,7 +113,7 @@ suite('numbers', function() { done(); }); - test('should return transposed matrix', function(done) { + test('should return transposed matrix', function (done) { var array = [ [0, 1, 2], [3, 4, 5] @@ -131,7 +131,7 @@ suite('numbers', function() { done(); }); - test('should return identity matrix of dimension n', function(done) { + test('should return identity matrix of dimension n', function (done) { var identity = [ [1, 0, 0], [0, 1, 0], @@ -143,7 +143,7 @@ suite('numbers', function() { done(); }); - test('should return dot product of two vectors', function(done) { + test('should return dot product of two vectors', function (done) { var vectorA = [0, 1, 2, 3]; var vectorB = [-1, 2, 4, 6]; @@ -153,7 +153,7 @@ suite('numbers', function() { done(); }); - test('should return product of a row vector and a matrix', function(done) { + test('should return product of a row vector and a matrix', function (done) { var vec = [2, 1]; var mat = [ [1, 0, 1], @@ -166,7 +166,7 @@ suite('numbers', function() { done(); }); - test('should return product of a matrix and a column vector', function(done) { + test('should return product of a matrix and a column vector', function (done) { var mat = [ [1, 0, 1], [0, 1, 0] @@ -186,7 +186,7 @@ suite('numbers', function() { done(); }); - test('should return product of two matrices', function(done) { + test('should return product of two matrices', function (done) { var matrixA = [ [0, 1, 2], [3, 4, 5] @@ -206,7 +206,7 @@ suite('numbers', function() { done(); }); - test('should return product of a row vector and a matrix using general-purpose multiplication', function(done) { + test('should return product of a row vector and a matrix using general-purpose multiplication', function (done) { var vec = [3, 4]; var mat = [ [2, 0, 2], @@ -219,7 +219,7 @@ suite('numbers', function() { done(); }); - test('should return product of a matrix and a column vector using general-purpose multiplication', function(done) { + test('should return product of a matrix and a column vector using general-purpose multiplication', function (done) { var mat = [ [1, 2, 3], [2, 1, 0] @@ -239,7 +239,7 @@ suite('numbers', function() { done(); }); - test('should return product of two matrices using general-purpose multiplication', function(done) { + test('should return product of two matrices using general-purpose multiplication', function (done) { var matrixA = [ [0, 1, 2], [3, 4, 5] @@ -259,7 +259,7 @@ suite('numbers', function() { done(); }); - test('should return determinant of matrix', function(done) { + test('should return determinant of matrix', function (done) { var m0 = [ [1] @@ -288,7 +288,7 @@ suite('numbers', function() { done(); }); - test('should throw an error for calculating the determinant of a non-square matrix', function(done) { + test('should throw an error for calculating the determinant of a non-square matrix', function (done) { var m3 = [ [3, -7, 8, 9, -6], [0, 2, -5, 7, 3], @@ -296,7 +296,7 @@ suite('numbers', function() { [0, 0, 0, -2, 0] ]; - assert.throws(function() { + assert.throws(function () { matrix.determinant(m3); }, /Matrix must be square./ @@ -304,9 +304,9 @@ suite('numbers', function() { done(); }); - test('should throw an error if trying to get LU decomposition of non-square matrix', function(done) { + test('should throw an error if trying to get LU decomposition of non-square matrix', function (done) { assert.throws( - function() { + function () { matrix.lupDecomposition([ [1, 2, 3], [4, 5, 6] @@ -318,7 +318,7 @@ suite('numbers', function() { done(); }); - test('should return the LU decomposition of a matrix', function(done) { + test('should return the LU decomposition of a matrix', function (done) { var inputMatrix = [ [1, 0, 0, 2], [2, -2, 0, 5], @@ -344,7 +344,7 @@ suite('numbers', function() { done(); }); - test('should return a new vector that has been rotated by the transformation matrix', function(done) { + test('should return a new vector that has been rotated by the transformation matrix', function (done) { var vectorA = [ [0], [1] @@ -360,7 +360,7 @@ suite('numbers', function() { done(); }); - test('should throw an error if a vector larger than two is given for rotation', function(done) { + test('should throw an error if a vector larger than two is given for rotation', function (done) { var vectorA = [ [0], [1], @@ -369,7 +369,7 @@ suite('numbers', function() { var degree = 90; assert.throws( - function() { + function () { matrix.rotate(vectorA, degree, 'clockwise'); }, /Only two dimensional operations are supported at this time/ @@ -377,7 +377,7 @@ suite('numbers', function() { done(); }); - test('should return a new vector that has been scaled by the transformation matrix', function(done) { + test('should return a new vector that has been scaled by the transformation matrix', function (done) { var vectorA = [ [2], [5] @@ -395,7 +395,7 @@ suite('numbers', function() { done(); }); - test('should throw an error if a vector larger than two is given for scaling', function(done) { + test('should throw an error if a vector larger than two is given for scaling', function (done) { var vectorA = [ [0], [1], @@ -405,15 +405,15 @@ suite('numbers', function() { var sy = 5; assert.throws( - function() { - var res = matrix.scale(vectorA, sx, sy); + function () { + matrix.scale(vectorA, sx, sy); }, /Only two dimensional operations are supported at this time/ ); done(); }); - test('should return a new vector that has been sheared in the x direction by the transformation matrix', function(done) { + test('should return a new vector that has been sheared in the x direction by the transformation matrix', function (done) { var vectorA = [ [2], [5] @@ -431,7 +431,7 @@ suite('numbers', function() { done(); }); - test('should return a new vector that has been sheared in the y direction by the transformation matrix', function(done) { + test('should return a new vector that has been sheared in the y direction by the transformation matrix', function (done) { var vectorA = [ [2], [5] @@ -449,7 +449,7 @@ suite('numbers', function() { done(); }); - test('should throw an error if a vector larger than two is given for shearing', function(done) { + test('should throw an error if a vector larger than two is given for shearing', function (done) { var vectorA = [ [0], [1], @@ -459,15 +459,15 @@ suite('numbers', function() { var direction = "yaxis"; assert.throws( - function() { - var res = matrix.shear(vectorA, k, direction); + function () { + matrix.shear(vectorA, k, direction); }, /Only two dimensional operations are supported at this time/ ); done(); }); - test('should return a new vector that has been transformed by the affine transformation matrix', function(done) { + test('should return a new vector that has been transformed by the affine transformation matrix', function (done) { var vectorA = [ [2], [5] @@ -485,7 +485,7 @@ suite('numbers', function() { done(); }); - test('should throw an error if a vector larger than two is given for the affine transform', function(done) { + test('should throw an error if a vector larger than two is given for the affine transform', function (done) { var vectorA = [ [0], [1], @@ -495,8 +495,8 @@ suite('numbers', function() { var ty = 10; assert.throws( - function() { - var res = matrix.affine(vectorA, tx, ty); + function () { + matrix.affine(vectorA, tx, ty); }, /Only two dimensional operations are supported at this time/ ); @@ -504,7 +504,7 @@ suite('numbers', function() { done(); }); - test('should return a new matrix that has a scaled row for the rowScale function', function(done) { + test('should return a new matrix that has a scaled row for the rowScale function', function (done) { var m = [ [0, 1, 2], [3, -1, 5], @@ -534,7 +534,7 @@ suite('numbers', function() { done(); }); - test('should return a new matrix that has rows changed with the rowSwitch function', function(done) { + test('should return a new matrix that has rows changed with the rowSwitch function', function (done) { var m = [ [0, 1, 2], [3, -1, 5], @@ -557,7 +557,7 @@ suite('numbers', function() { done(); }); - test('should return a new matrix that has a multiple of one row added to another using the rowAddMultiple function', function(done) { + test('should return a new matrix that has a multiple of one row added to another using the rowAddMultiple function', function (done) { var m = [ [0, 1, 2], [3, -1, 5], @@ -581,7 +581,7 @@ suite('numbers', function() { done(); }); - test('should row reduce the given matrix for a given epsilon', function(done) { + test('should row reduce the given matrix for a given epsilon', function (done) { var m1 = [ [0, 1, 2], [3, -1, 5], @@ -611,7 +611,7 @@ suite('numbers', function() { done(); }); - test('should row reduce the given matrix for a given epsilon', function(done) { + test('should row reduce the given matrix for a given epsilon', function (done) { var m1 = [ [0, 1], [1, 2] @@ -643,7 +643,7 @@ suite('numbers', function() { done(); }); - test('should reorder columns', function(done) { + test('should reorder columns', function (done) { var m1 = [ [1, 2, 3], [4, 5, 6], @@ -674,7 +674,7 @@ suite('numbers', function() { done(); }); - test('should reorder rows', function(done) { + test('should reorder rows', function (done) { var m1 = [ [1, 2, 3], [4, 5, 6], @@ -705,7 +705,7 @@ suite('numbers', function() { done(); }); - test('should reverse columns and rows', function(done) { + test('should reverse columns and rows', function (done) { var m1 = [ [2, 5, 7], [10, 4, 6], @@ -724,7 +724,7 @@ suite('numbers', function() { done(); }); - test('should produce a matrix of zeros', function(done) { + test('should produce a matrix of zeros', function (done) { var n1 = 3; var m1 = 2; @@ -740,7 +740,7 @@ suite('numbers', function() { done(); }); - test('should get a column', function(done) { + test('should get a column', function (done) { var m1 = [ [10, 2, 5], [5, 2, 42], @@ -756,7 +756,7 @@ suite('numbers', function() { done(); }); - test('should create a zigzag matrix', function(done) { + test('should create a zigzag matrix', function (done) { var n1 = 4; var corner1 = 'TL'; var dir1 = 'V'; @@ -774,7 +774,7 @@ suite('numbers', function() { done(); }); - test('should calculate a vector norm', function(done) { + test('should calculate a vector norm', function (done) { var v1 = [-100, 5, -12, 20, 83]; var p1 = Infinity; var p2 = -Infinity; @@ -796,7 +796,7 @@ suite('numbers', function() { done(); }); - test('should calculate a matrix norm', function(done) { + test('should calculate a matrix norm', function (done) { var m1 = [ [1, -3, 2], [-4, 6, -5], @@ -836,7 +836,7 @@ suite('numbers', function() { done(); }); - test('should test for upper bandwidth', function(done) { + test('should test for upper bandwidth', function (done) { var m1 = [ [1, 2, 0, 0], [5, 4, 3, 0], @@ -862,7 +862,7 @@ suite('numbers', function() { done(); }); - test('should test for lower bandwidth', function(done) { + test('should test for lower bandwidth', function (done) { var m1 = [ [1, 2, 3, 5], [5, 4, 3, 0], @@ -889,7 +889,7 @@ suite('numbers', function() { done(); }); - test('should test for weak row diagonal dominance', function(done) { + test('should test for weak row diagonal dominance', function (done) { var m1 = [ [3, -2, 1], [1, -3, 2], @@ -912,7 +912,7 @@ suite('numbers', function() { done(); }); - test('should test for strict row diagonal dominance', function(done) { + test('should test for strict row diagonal dominance', function (done) { var m1 = [ [3, -2, 1], [1, -3, 2], @@ -935,7 +935,7 @@ suite('numbers', function() { done(); }); - test('should test for weak column diagonal dominance', function(done) { + test('should test for weak column diagonal dominance', function (done) { var m1 = [ [3, -2, 1], [1, -3, 2], @@ -958,7 +958,7 @@ suite('numbers', function() { done(); }); - test('should test for strict column diagonal dominance', function(done) { + test('should test for strict column diagonal dominance', function (done) { var m1 = [ [-4, 2, 1], [1, 6, 2], diff --git a/test/prime.test.js b/test/prime.test.js index 443b796..027fe54 100644 --- a/test/prime.test.js +++ b/test/prime.test.js @@ -2,16 +2,16 @@ var assert = require('assert'); var numbers = require('../index.js'); var prime = numbers.prime; -suite('numbers', function() { +suite('numbers', function () { var primes = [2, 17, 839, 3733, 999983]; var composites = [1, 4, 18, 25, 838, 3007]; - + console.log('\n\n\033[34mTesting Prime Number Mathematics\033[0m'); // prime.simple - test('simple should be able to determine if a number is prime or not', function(done) { + test('simple should be able to determine if a number is prime or not', function (done) { for (var i = 0; i < primes.length; i++) { - assert.equal(prime.simple(primes[i]), true); + assert.equal(prime.simple(primes[i]), true); } for (i = 0; i < composites.length; i++) { @@ -22,9 +22,9 @@ suite('numbers', function() { }); // prime.millerRabin - test('millerRabin should be able to determine if a number is prime or not', function(done) { + test('millerRabin should be able to determine if a number is prime or not', function (done) { for (var i = 0; i < primes.length; i++) { - assert.equal(prime.millerRabin(primes[i]), true); + assert.equal(prime.millerRabin(primes[i]), true); } for (i = 0; i < composites.length; i++) { @@ -35,65 +35,65 @@ suite('numbers', function() { }); // prime.sieve - test('should be able to determine if a number is prime or not', function(done) { + test('should be able to determine if a number is prime or not', function (done) { assert.deepEqual(prime.sieve(1), []); assert.deepEqual(prime.sieve(2), [2]); - assert.deepEqual(prime.sieve(17), [ 2, 3, 5, 7, 11, 13, 17 ]); - + assert.deepEqual(prime.sieve(17), [2, 3, 5, 7, 11, 13, 17]); + done(); }); //prime.factorization when values < 2 test("factorization should return an empty array for values < 2, infinite or not numeric", function (done) { - var func = prime.factorization; - assert.deepEqual([], func(Infinity)); - assert.deepEqual([], func({})); - assert.deepEqual([], func(null)); - assert.deepEqual([], func(-1)); - assert.deepEqual([], func(0)); - assert.deepEqual([], func(1)); - + var func = prime.factorization; + assert.deepEqual([], func(Infinity)); + assert.deepEqual([], func({})); + assert.deepEqual([], func(null)); + assert.deepEqual([], func(-1)); + assert.deepEqual([], func(0)); + assert.deepEqual([], func(1)); + done(); - }); + }); //prime.factorization when 1 < values < infinity - test("factorization should return the prime factors for x where 1 < x < infinity", function (done) { - var func = prime.factorization; - assert.deepEqual([2], func(2)); - assert.deepEqual([ 2, 3 ], func(6)); - assert.deepEqual([ 3, 3 ], func(9)); - assert.deepEqual([ 3, 3, 3, 3, 3, 3 ], func('729')); - assert.deepEqual([ 2347, 1420253 ], func(3333333791)); - assert.deepEqual([ 3, 3, 3607, 3803 ], func(123456789)); - assert.deepEqual([ 2, 3, 3, 5, 17, 17, 379721 ], func(9876543210)); - assert.deepEqual([ 3, 103, 333667 ], func('103103103')); - + test("factorization should return the prime factors for x where 1 < x < infinity", function (done) { + var func = prime.factorization; + assert.deepEqual([2], func(2)); + assert.deepEqual([2, 3], func(6)); + assert.deepEqual([3, 3], func(9)); + assert.deepEqual([3, 3, 3, 3, 3, 3], func('729')); + assert.deepEqual([2347, 1420253], func(3333333791)); + assert.deepEqual([3, 3, 3607, 3803], func(123456789)); + assert.deepEqual([2, 3, 3, 5, 17, 17, 379721], func(9876543210)); + assert.deepEqual([3, 103, 333667], func('103103103')); + done(); - }); + }); - test("coprime should determine if two integers are coprime or not", function(done) { + test("coprime should determine if two integers are coprime or not", function (done) { assert.equal(prime.coprime(3, 4), true); assert.equal(prime.coprime(48, 65), true); assert.equal(prime.coprime(48, 64), false); - + done(); }); //prime.getPrimePower - test('should find what the prime power of n is if it exists', function(done) { - assert.deepEqual(prime.getPrimePower(4), [ 2, 2 ]); + test('should find what the prime power of n is if it exists', function (done) { + assert.deepEqual(prime.getPrimePower(4), [2, 2]); assert.equal(prime.getPrimePower(1), false); - assert.deepEqual(prime.getPrimePower(3), [ 3, 1 ]); - assert.deepEqual(prime.getPrimePower(9), [ 3, 2 ]); + assert.deepEqual(prime.getPrimePower(3), [3, 1]); + assert.deepEqual(prime.getPrimePower(9), [3, 2]); done(); }); //prime.getPerfectPower - test('should find a perfect power of n is if it exists', function(done) { - assert.deepEqual(prime.getPerfectPower(4), [ 2, 2 ]); + test('should find a perfect power of n is if it exists', function (done) { + assert.deepEqual(prime.getPerfectPower(4), [2, 2]); assert.equal(prime.getPerfectPower(1), false); assert.equal(prime.getPerfectPower(3), false); - assert.deepEqual(prime.getPerfectPower(9), [ 3, 2 ]); + assert.deepEqual(prime.getPerfectPower(9), [3, 2]); done(); }); diff --git a/test/random.test.js b/test/random.test.js index b88665a..9457118 100644 --- a/test/random.test.js +++ b/test/random.test.js @@ -1,22 +1,21 @@ var assert = require('assert'); var numbers = require('../index.js'); var statistic = numbers.statistic; -var basic = numbers.basic; var random = numbers.random; var testing = require('./testing.js'); var seedrandom = require("seedrandom"); -suite('numbers', function() { +suite('numbers', function () { console.log('\n\n\033[34mTesting Random Mathematics\033[0m'); // seed random number generator for predictablity. - random.setGenerator( seedrandom("this SEED value should be random enough...") ); + random.setGenerator(seedrandom("this SEED value should be random enough...")); // random.sample - test('random.sample should return an array of random numbers in a certain bound', function(done) { + test('random.sample should return an array of random numbers in a certain bound', function (done) { var res = random.sample(5, 100, 5); - res.forEach(function(val) { + res.forEach(function (val) { testing.between(val, 5, 100); }); assert.equal(res.length, 5); @@ -24,8 +23,8 @@ suite('numbers', function() { }); // random.boxMullerTransform - test('random.boxMullerTransform should return an array of two numbers that are random within a normal distribution', function(done) { - var test1, mu, sigma; + test('random.boxMullerTransform should return an array of two numbers that are random within a normal distribution', function (done) { + var test1; test1 = random.boxMullerTransform(); assert.ok(typeof test1[0] === 'number' && typeof test1[1] === 'number' && test1.length === 2); test1 = random.boxMullerTransform(2); @@ -36,8 +35,8 @@ suite('numbers', function() { }); // random.irwinHall - test('random.irwinHall should return a number from [0, a] with a normal distribution for probability', function(done) { - var test1, mu, sigma; + test('random.irwinHall should return a number from [0, a] with a normal distribution for probability', function (done) { + var test1; test1 = random.irwinHall(10); testing.between(test1, 0, 10); test1 = random.irwinHall(20, 10); @@ -46,8 +45,8 @@ suite('numbers', function() { }); // random.bates - test('random.bates should return a number from [0,1] within a bates distribution', function(done) { - var test1, mu, sigma; + test('random.bates should return a number from [0,1] within a bates distribution', function (done) { + var test1; test1 = random.bates(10); testing.between(test1, 0, 1); test1 = random.bates(20, 20, 10); @@ -56,9 +55,9 @@ suite('numbers', function() { }); // random.distribution.normal - test('random.distribution.normal should return a normal distribution of length n', function(done) { + test('random.distribution.normal should return a normal distribution of length n', function (done) { var t = numbers.EPSILON, - test1, mu, sigma; + test1, mu, sigma; numbers.EPSILON = 0.01; //lower error considering the issue with Math.random() test1 = random.distribution.normal(100000); @@ -72,9 +71,9 @@ suite('numbers', function() { sigma = statistic.standardDev(test1); testing.approxEquals(mu, 20); testing.approxEquals(sigma, 1); - for (var i = 0; i <= 4; i+=2) { - for (var j = 0; j <= 1; j+=0.5) { - var n = Math.floor(Math.random()*100)+100000; + for (var i = 0; i <= 4; i += 2) { + for (var j = 0; j <= 1; j += 0.5) { + var n = Math.floor(Math.random() * 100) + 100000; test1 = random.distribution.normal(n, i, j); mu = statistic.mean(test1); sigma = statistic.standardDev(test1); @@ -88,15 +87,15 @@ suite('numbers', function() { }); // random.distribution.logNormal - test('random.distribution.logNormal should return a log normal distribution of length n', function(done) { + test('random.distribution.logNormal should return a log normal distribution of length n', function (done) { var t = numbers.EPSILON, - test1, mu, sigma; + test1, mu, sigma; numbers.EPSILON = 0.1; test1 = random.distribution.logNormal(100000); mu = statistic.mean(test1); sigma = statistic.standardDev(test1); - var expectedMu = Math.exp((0 + Math.pow(1, 2))/2), - expectedSigma = Math.sqrt((Math.exp(Math.pow(1, 2)) - 1) * Math.exp(2 * 0 + Math.pow(1, 2))); + var expectedMu = Math.exp((0 + Math.pow(1, 2)) / 2), + expectedSigma = Math.sqrt((Math.exp(Math.pow(1, 2)) - 1) * Math.exp(2 * 0 + Math.pow(1, 2))); testing.approxEquals(mu, expectedMu); testing.approxEquals(sigma, expectedSigma); numbers.EPSILON = t; @@ -104,9 +103,9 @@ suite('numbers', function() { }); // random.distribution.boxMuller - test('random.distribution.boxMuller should return a n-sample of a normal distribution', function(done) { + test('random.distribution.boxMuller should return a n-sample of a normal distribution', function (done) { var t = numbers.EPSILON, - test1, mu, sigma; + test1, mu, sigma; numbers.EPSILON = 0.1; //lower error considering the issue with Math.random() test1 = random.distribution.boxMuller(100000); @@ -120,9 +119,9 @@ suite('numbers', function() { sigma = statistic.standardDev(test1); testing.approxEquals(mu, 20); testing.approxEquals(sigma, 1); - for (var i = 0; i <= 4; i+=2) { - for (var j = 0; j <= 1; j+=0.5) { - var n = Math.floor(Math.random()*100)+100000; + for (var i = 0; i <= 4; i += 2) { + for (var j = 0; j <= 1; j += 0.5) { + var n = Math.floor(Math.random() * 100) + 100000; test1 = random.distribution.boxMuller(n, i, j); mu = statistic.mean(test1); sigma = statistic.standardDev(test1); @@ -136,7 +135,7 @@ suite('numbers', function() { }); // random.distribution.irwinHall - test('random.distribution.irwinHall should return a normal distribution of length n within bounds of (m/2 - sub, m/2)', function(done) { + test('random.distribution.irwinHall should return a normal distribution of length n within bounds of (m/2 - sub, m/2)', function (done) { var test1; test1 = random.distribution.irwinHall(100); testing.approxEquals(statistic.mean(test1), 100 / 2, 2); @@ -154,7 +153,7 @@ suite('numbers', function() { }); // random.distribution.irwinHallNormal - test('random.distribution.irwinHallNormal should return a n-sample of a normal distribution with a bound of (-6, 6)', function(done) { + test('random.distribution.irwinHallNormal should return a n-sample of a normal distribution with a bound of (-6, 6)', function (done) { var test1; test1 = random.distribution.irwinHallNormal(50); testing.approxEquals(statistic.mean(test1), 0, 0.5); @@ -163,7 +162,7 @@ suite('numbers', function() { }); // random.distribution.bates - test('random.distribution.bates should return a n-sample of a bates distribution', function(done) { + test('random.distribution.bates should return a n-sample of a bates distribution', function (done) { var test1; test1 = random.distribution.bates(100, 2); testing.approxEquals(statistic.mean(test1), 1, 0.5); diff --git a/test/statistic.test.js b/test/statistic.test.js index 00e9294..6701662 100644 --- a/test/statistic.test.js +++ b/test/statistic.test.js @@ -3,79 +3,79 @@ var numbers = require('../index.js'); var statistic = numbers.statistic; var basic = numbers.basic; -suite('numbers', function() { +suite('numbers', function () { console.log('\n\n\033[34mTesting Statistics Mathematics\033[0m'); - test('mean should return average value amongst integers in an array', function(done) { + test('mean should return average value amongst integers in an array', function (done) { var res = statistic.mean([0, 1, 2]); assert.equal(res, 1); done(); }); - test('median should return middle value in array for a sorted array with an odd number of values', function(done) { + test('median should return middle value in array for a sorted array with an odd number of values', function (done) { var res1 = statistic.median([0, 2, 15]); assert.equal(res1, 2); done(); }); - test('median should return middle value in array for an unsorted array with an odd number of values', function(done) { + test('median should return middle value in array for an unsorted array with an odd number of values', function (done) { var res1 = statistic.median([1, 0, 2]); assert.equal(res1, 1); done(); }); - test('median should return average of two middle values in array for a sorted array with an even number of values', function(done) { + test('median should return average of two middle values in array for a sorted array with an even number of values', function (done) { var res2 = statistic.median([0, 1, 2, 3]); assert.equal(res2, 1.5); done(); }); - test('median should return average of two middle values in array for an unsorted array with an even number of values', function(done) { + test('median should return average of two middle values in array for an unsorted array with an even number of values', function (done) { var res2 = statistic.median([1, 3, 2, 0]); assert.equal(res2, 1.5); done(); }); - test('mode should return most common value in array', function(done) { + test('mode should return most common value in array', function (done) { var res = statistic.mode([0, 1, 1, 1, 2, 4, 6]); assert.equal(res, 1); done(); }); - test('quantile should return lowest value in array for 0th q-quantile of an unsorted array', function(done) { + test('quantile should return lowest value in array for 0th q-quantile of an unsorted array', function (done) { var arr = [5, 2, 4]; var res = statistic.quantile(arr, 0, 1); assert.equal(res, 2); done(); }); - test('quantile should return highest value in array for qth q-quantile of an unsorted array', function(done) { + test('quantile should return highest value in array for qth q-quantile of an unsorted array', function (done) { var arr = [5, 2, 4]; var res = statistic.quantile(arr, 6, 6); assert.equal(res, 5); done(); }); - test('quantile should return average of two values in array for an unsorted array\'s length is a multiple of (k / q)', function(done) { + test('quantile should return average of two values in array for an unsorted array\'s length is a multiple of (k / q)', function (done) { var res = statistic.quantile([9, 1, 1, 9], 2, 4); assert.equal(res, 5); done(); }); - test('quantile should return value at 0-based index floor(k/q) in array for an unsorted array\'s length is not a multiple of (k/q)', function(done) { + test('quantile should return value at 0-based index floor(k/q) in array for an unsorted array\'s length is not a multiple of (k/q)', function (done) { var res = statistic.quantile([3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20], 1, 4); assert.equal(res, 7); done(); }); - test('should return the standard deviation of an array of numbers', function(done) { + test('should return the standard deviation of an array of numbers', function (done) { var res = statistic.standardDev([-5, -4, -1, 0, 5, 100]); assert.equal(res - numbers.EPSILON < 37.777 < res + numbers.EPSILON, true); done(); }); - test('should return correlation between two arrays', function(done) { + test('should return correlation between two arrays', function (done) { var arr1 = [-5, -4, -1, 0, 5, 100]; var arr2 = [-6, 5, 2, 5, 2, 6]; @@ -86,17 +86,17 @@ suite('numbers', function() { }); test('should return a function to calculate the linear regression of a set of points', function (done) { - var arrX = [1,2,3,4,5,7,8,9]; - var arrY = [1,2,3,4,5,7,7,9]; + var arrX = [1, 2, 3, 4, 5, 7, 8, 9]; + var arrY = [1, 2, 3, 4, 5, 7, 7, 9]; - var regression_function = statistic.linearRegression(arrX,arrY); + var regression_function = statistic.linearRegression(arrX, arrY); assert.equal(regression_function(20), 19.07218683651805); done(); }); test('should return a function to calculate the exponential regression of an array of numbers', function (done) { - var input = [10,9,8,8,7,7,6,6.5,6.4,6.3,6.2]; + var input = [10, 9, 8, 8, 7, 7, 6, 6.5, 6.4, 6.3, 6.2]; var output = [ 9.077131929916444, 8.66937771538526, 8.279940244595563, 7.907996710352883, 7.552761266818376, 7.213483369166244, 6.8894461878255076, 6.579965093955639, @@ -114,7 +114,7 @@ suite('numbers', function() { }); test('should return an appropriate Coefficient of Determination for a given dataset and regression', function (done) { - var input = [10,9,8,8,7,7,6,6.5,6.4,6.3,6.2]; + var input = [10, 9, 8, 8, 7, 7, 6, 6.5, 6.4, 6.3, 6.2]; var output = [ 9.077131929916444, 8.66937771538526, 8.279940244595563, 7.907996710352883, 7.552761266818376, 7.213483369166244, 6.8894461878255076, 6.579965093955639, @@ -125,7 +125,7 @@ suite('numbers', function() { done(); }); - test('should return covariance between two arrays', function(done) { + test('should return covariance between two arrays', function (done) { var arr1 = [-5, -4, -1, 0, 5, 100]; var arr2 = [-6, 5, 2, 5, 2, 6]; diff --git a/test/testing.js b/test/testing.js index 8cca0f6..5d43b45 100644 --- a/test/testing.js +++ b/test/testing.js @@ -9,8 +9,8 @@ var testing = exports; * @param {Number} value b * @param {Number} approximate value (default is numbers.EPSILON) */ -testing.approxEquals = function(a, b, eps) { - if (arguments.length < 3) eps = numbers.EPSILON; +testing.approxEquals = function (a, b, eps) { + if (arguments.length < 3) eps = numbers.EPSILON; assert.equal(Math.abs(a - b) < eps, true); }; @@ -21,12 +21,12 @@ testing.approxEquals = function(a, b, eps) { * @param {Number} lower bound * @param {Number} upper bound */ -testing.between = function(x, a, b) { +testing.between = function (x, a, b) { assert.equal(a < x && x < b, true); }; /** - * Runs a test n times, determines if it's true within a + * Runs a test n times, determines if it's true within a * percentage bound * * @param {Function} closure to run test @@ -35,13 +35,13 @@ testing.between = function(x, a, b) { * @param {Number} percentage of passes to pass test * @assert {Boolean} passed or failed test. */ -testing.likelyTrue = function(testFunction, message, n, perc) { - if (arguments.length <= 3) perc = 0.5; - if (arguments.length <= 2) n = 10; - if (arguments.length === 1) message = 'is not likely to be true'; - var r = 0; - for (var i = 0; i < n; i++) { - if (testFunction()) r++; - } - assert.equal(r / n < perc, true); -}; \ No newline at end of file +testing.likelyTrue = function (testFunction, message, n, perc) { + if (arguments.length <= 3) perc = 0.5; + if (arguments.length <= 2) n = 10; + if (arguments.length === 1) message = 'is not likely to be true'; + var r = 0; + for (var i = 0; i < n; i++) { + if (testFunction()) r++; + } + assert.equal(r / n < perc, true); +};