Refactor: Implement SmartCube renderer, improve UI styling, and fix gaps
This commit is contained in:
16
node_modules/matrix-js/LICENSE-MIT
generated
vendored
Normal file
16
node_modules/matrix-js/LICENSE-MIT
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Raghavendra Ravikumar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
||||
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
||||
the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
153
node_modules/matrix-js/README.md
generated
vendored
Normal file
153
node_modules/matrix-js/README.md
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
matrix
|
||||
======
|
||||
|
||||
A Javascript Library to perform basic matrix operations using the functional nature of Javascript
|
||||
|
||||
## Usage
|
||||
```javascript
|
||||
var a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
||||
var A = matrix(a);
|
||||
```
|
||||
|
||||
### Operations
|
||||
#### 1. Identity
|
||||
```javascript
|
||||
A(); //returns [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
||||
```
|
||||
#### 2. Row
|
||||
```javascript
|
||||
A(0); // returns [1, 2, 3]
|
||||
```
|
||||
#### 3. Column
|
||||
```javascript
|
||||
A([], 0); // returns [[1], [4], [7]]
|
||||
```
|
||||
#### 4. Element
|
||||
```javascript
|
||||
A(1, 2); // returns 6
|
||||
```
|
||||
#### 5. Range
|
||||
```javascript
|
||||
A([1,2]); // returns [[4, 5, 6], [7, 8, 9]]
|
||||
A([],[1,2]); // returns [[2, 3], [5, 6], [8, 9]]
|
||||
A([1,2],[1,2]); // returns [[5, 6], [8, 9]]
|
||||
A([2,1],[]); // returns [[7, 8, 9], [4, 5 ,6]]
|
||||
A([],[2,1]); // returns [[3, 2], [6, 5], [9, 8]]
|
||||
A([2,1],[2,1]); // returns [[9, 8], [6, 5]]
|
||||
```
|
||||
#### 6. Size
|
||||
```javascript
|
||||
A.size(); //returns [3, 3]
|
||||
```
|
||||
#### 7. Set
|
||||
```javascript
|
||||
A.set(0).to(0); // returns [[0, 0, 0], [4, 5, 6], [7, 8, 9]]
|
||||
A.set(1,2).to(10); // returns [[1, 2, 3], [4, 5, 10], [7, 8, 9]]
|
||||
A.set([], 0).to(0); // returns [[0, 2, 3], [0, 5, 6], [0, 8, 9]]
|
||||
A.set([1,2]).to(4); // returns [[1, 2, 3], [4, 4, 4], [4, 4, 4]]
|
||||
A.set([], [1,2]).to(1); // returns [[1, 1, 1], [4, 1, 1], [7, 1, 1]]
|
||||
```
|
||||
#### 8. Addition
|
||||
```javascript
|
||||
var B = matrix([[3, 4, 5], [6, 7, 8], [9, 10, 11]]);
|
||||
A.add(B); // returns [[4, 6, 8], [10, 12, 14], [16, 18, 20]]
|
||||
```
|
||||
#### 9. Subtraction
|
||||
```javascript
|
||||
B.sub(A); // returns [[2, 2, 2], [2, 2, 2], [2, 2, 2]]
|
||||
```
|
||||
#### 10. Multiplication
|
||||
```javascript
|
||||
A.mul(B); // returns [[3, 8, 15], [24, 35, 48], [56, 80, 99]]
|
||||
```
|
||||
**NOTE:** This is not classical matrix multiplication (which is implemented using the prod() method). This simply multiplies together each element in matrix A with the corresponding element in matrix B. If A and B are not the same size, it will produce some NaN results.
|
||||
#### 11. Division
|
||||
```javascript
|
||||
A.div(B); // returns [[0.33, 0.5, 0.6], [0.66, 0.71, 0.75], [0.77, 0.8, 0.81]]
|
||||
```
|
||||
#### 12. Product
|
||||
```javascript
|
||||
A.prod(B); // returns [[42, 48, 54], [96, 111, 126], [150, 174, 198]]
|
||||
```
|
||||
#### 13. Transpose
|
||||
```javascript
|
||||
A.trans(); // returns [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
|
||||
```
|
||||
#### 14. Determinant
|
||||
```javascript
|
||||
var C = matrix([[5, 4, 7], [4, 8, 2], [9, 0, 4]]);
|
||||
C.det(); // returns -336
|
||||
```
|
||||
#### 15. Inverse
|
||||
Should be invertible
|
||||
```javascript
|
||||
M = matrix([[1, 3, 3], [1, 4, 3], [1, 3 ,4]]);
|
||||
M.inv(); // returns [[7, -3, -3], [-1, 1, 0], [-1, 0 ,1]]
|
||||
```
|
||||
|
||||
#### 16. Merge
|
||||
Merges two matrices in all directions
|
||||
|
||||
* Left
|
||||
```javascript
|
||||
M = matrix([[3, 4], [7, 8]]);
|
||||
M.merge.left([[1, 2], [5, 6]]); // returns [[1, 2, 3, 4], [5, 6, 7, 8]]
|
||||
```
|
||||
* Right
|
||||
```javascript
|
||||
M = matrix([[1, 2], [5, 6]]);
|
||||
M.merge.right([[3, 4], [7, 8]]); // returns [[1, 2, 3, 4], [5, 6, 7, 8]]
|
||||
```
|
||||
* Top
|
||||
```javascript
|
||||
M = matrix([5, 6, 7, 8]);
|
||||
M.merge.top([1, 2, 3, 4]); // returns [[1, 2, 3, 4], [5, 6, 7, 8]]
|
||||
```
|
||||
* Bottom
|
||||
```javascript
|
||||
M = matrix([1, 2, 3 ,4]);
|
||||
M.merge.bottom([5, 6, 7, 8]); // returns [[1, 2, 3, 4], [5, 6, 7, 8]]
|
||||
```
|
||||
|
||||
#### 17. Map
|
||||
Applies a given function over the matrix, elementwise. Similar to Array.map()
|
||||
```javascript
|
||||
M = matrix([1, 2, 3]);
|
||||
M.map(x => x*x); // returns [1, 4, 9]
|
||||
```
|
||||
> This example shows the arguments provided to the function
|
||||
```javascript
|
||||
M = matrix([[1, 2], [3, 4]]);
|
||||
M.map((value, pos, mat) => value * pos[1]);
|
||||
// returns [[0, 2], [0, 4]]
|
||||
```
|
||||
|
||||
#### 18. Equals
|
||||
Checks the equality of two matrices and returns a boolean. A matrix is equal to itself.
|
||||
```javascript
|
||||
A = matrix([[1,2],[3,4]]);
|
||||
A.equals(A);
|
||||
// returns true
|
||||
B = matrix([[3,4], [1,2]]);
|
||||
A.equals(B);
|
||||
// returns false
|
||||
```
|
||||
|
||||
#### 19. Generate
|
||||
Generates a matrix with the value passed or random values across the entire matrix or just the diagonal.
|
||||
```javascript
|
||||
matrix.gen(4).size(2,3); // returns [[4,4,4],[4,4,4]]
|
||||
matrix.gen(2).size(2); // returns [[2,2],[2,2]]
|
||||
matrix.gen(1).diag(3); // return [[1,0,0],[0,1,0],[0,0,1]], identity matrix
|
||||
// Diagonal matrices are normally square. Here, only diagonal elements are filled where row and column indices are same.
|
||||
matrix.gen(1).size(2,2); // returns
|
||||
matrix.gen(2).diag(3,4); // returns [[2,0,0,0],[0,2,0,0],[0,0,2,0]
|
||||
matrix.gen().size(2);
|
||||
/* returns:
|
||||
[
|
||||
[ 0.7267589083774397, 0.0874443492491741 ],
|
||||
[ 0.29717634641194746, 0.12599783865191672 ]
|
||||
]
|
||||
*/
|
||||
matrix.gen().diag(2); // returns [ [ 0.4658129342959194, 0 ], [ 0, 0.39870431341062584 ] ]
|
||||
```
|
||||
43
node_modules/matrix-js/lib/generate.js
generated
vendored
Normal file
43
node_modules/matrix-js/lib/generate.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
function generate(val) {
|
||||
return {
|
||||
size: (row, col) => size(val, row, col),
|
||||
diag: (row, col) => diag(val, row, col)
|
||||
}
|
||||
}
|
||||
|
||||
function size(val, row, col) {
|
||||
if (!col) {
|
||||
col = row;
|
||||
}
|
||||
let rows = [];
|
||||
for (let i = 0; i < row; i++) {
|
||||
let cols = [];
|
||||
for (let j = 0; j < col; j++) {
|
||||
cols[j] = val || Math.random();
|
||||
}
|
||||
rows[i] = cols;
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
function diag(val, row, col) {
|
||||
if (!col) {
|
||||
col = row;
|
||||
}
|
||||
let rows = [];
|
||||
for (let i = 0; i < row; i++) {
|
||||
let cols = [];
|
||||
for (let j = 0; j < col; j++) {
|
||||
cols[j] = 0;
|
||||
}
|
||||
rows[i] = cols;
|
||||
if (i < col || row == col) {
|
||||
rows[i][i] = val || Math.random();
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
module.exports = generate;
|
||||
525
node_modules/matrix-js/lib/index.js
generated
vendored
Normal file
525
node_modules/matrix-js/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,525 @@
|
||||
'use strict';
|
||||
|
||||
const rational = require('./rational');
|
||||
const merge = require('./merge');
|
||||
const generate = require('./generate');
|
||||
|
||||
/**
|
||||
* Pass a 2-dimensional array that will return a function accepting indices to access the matrix
|
||||
*
|
||||
* @param mat array that initializes the matrix
|
||||
* @returns function with the array initialized and access to method that perform operations on the matrix
|
||||
*/
|
||||
function matrix(mat) {
|
||||
if (!Array.isArray(mat)) {
|
||||
throw new Error('Input should be of type array');
|
||||
}
|
||||
let _matrix = function() {
|
||||
let args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));
|
||||
return read(mat, args);
|
||||
}
|
||||
return Object.assign(_matrix, _mat(mat));
|
||||
}
|
||||
|
||||
matrix.gen = generate;
|
||||
|
||||
/**
|
||||
* Private function that returns an object containing methods
|
||||
* that perform operations on the matrix
|
||||
*
|
||||
* @param mat array that initializes the matrix
|
||||
* @returns object of methods performing matrix operations
|
||||
*/
|
||||
function _mat(mat) {
|
||||
return {
|
||||
size: () => size(mat),
|
||||
add: (operand) => operate(mat, operand, addition),
|
||||
sub: (operand) => operate(mat, operand, subtraction),
|
||||
mul: (operand) => operate(mat, operand, multiplication),
|
||||
div: (operand) => operate(mat, operand, division),
|
||||
prod: (operand) => prod(mat, operand),
|
||||
trans: () => trans(mat),
|
||||
set: function() {
|
||||
let args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));
|
||||
return {
|
||||
to: (val) => replace(mat, val, args)
|
||||
}
|
||||
},
|
||||
det: () => determinant(mat),
|
||||
inv: () => invert(mat),
|
||||
merge: merge(mat),
|
||||
map: (func) => map(mat, func),
|
||||
equals: (operand) => equals(mat, operand),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = matrix;
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the size of the array across each dimension
|
||||
*
|
||||
* @param mat input matrix that initialized the function
|
||||
* @returns size of the matrix as an array
|
||||
*/
|
||||
function size(mat) {
|
||||
let s = [];
|
||||
while (Array.isArray(mat)) {
|
||||
s.push(mat.length);
|
||||
mat = mat[0];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private function to calculate the dimensions of the matrix
|
||||
*
|
||||
* @param mat input matrix that initializes the function
|
||||
* @returns integer indicating the number of dimensions
|
||||
*/
|
||||
function dimensions(mat) {
|
||||
return size(mat).length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs the original matrix or a particular element or a matrix that is part of the original
|
||||
*
|
||||
* @param mat input matrix that initializes the function
|
||||
* @param args indices to access one or more array elements
|
||||
* @returns array or single element
|
||||
*/
|
||||
function read(mat, args) {
|
||||
if (args.length === 0) {
|
||||
return mat;
|
||||
} else {
|
||||
return extract(mat, args);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private function to extract a single element or a matrix that is part of the original
|
||||
*
|
||||
* @param mat input matrix that initializes the function
|
||||
* @param args indices to access one or more array elements
|
||||
* @returns array or single element
|
||||
*/
|
||||
function extract(mat, args) {
|
||||
let dim = dimensions(mat);
|
||||
for (let i = 0; i < dim; i++) {
|
||||
let d = args[i];
|
||||
if (d === undefined) {
|
||||
break;
|
||||
}
|
||||
if (Array.isArray(d)) {
|
||||
// if an element of args is an array, more extraction is needed
|
||||
mat = extractRange(mat, d, i);
|
||||
} else if (Number.isInteger(d)) {
|
||||
if (dimensions(mat) > 1 && i > 0) {
|
||||
mat = mat.map(function(elem) {
|
||||
return [elem[d]];
|
||||
});
|
||||
} else {
|
||||
mat = mat[d];
|
||||
}
|
||||
}
|
||||
}
|
||||
return mat;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private function to extract a portion of the array based on the specified range
|
||||
*
|
||||
* @param mat input matrix that initialized the function
|
||||
* @param arg single argument containing the range specified as an array
|
||||
* @param ind the current index of the arguments while extracting the matrix
|
||||
* @returns array from the specified range
|
||||
*/
|
||||
function extractRange(mat, arg, ind) {
|
||||
if (!arg.length) {
|
||||
return mat;
|
||||
} else if (arg.length === 2) {
|
||||
let reverse = arg[0] > arg[1];
|
||||
let first = (!reverse) ? arg[0] : arg[1];
|
||||
let last = (!reverse) ? arg[1]: arg[0];
|
||||
if (dimensions(mat) > 1 && ind > 0) {
|
||||
return mat.map(function(elem) {
|
||||
if (reverse) {
|
||||
return elem.slice(first, last+1).reverse();
|
||||
}
|
||||
return elem.slice(first, last+1);
|
||||
})
|
||||
} else {
|
||||
mat = mat.slice(first, last+1);
|
||||
return (reverse && mat.reverse()) || mat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces the specified index in the matrix with the specified value
|
||||
*
|
||||
* @param mat input matrix that initialized the function
|
||||
* @param value specified value that replace current value at index or indices
|
||||
* @param args index or indices passed in arguments to initialized function
|
||||
* @returns replaced matrix
|
||||
*/
|
||||
function replace(mat, value, args) { //TODO: Clean this function up
|
||||
let result = clone(mat);
|
||||
let prev = args[0];
|
||||
let start = prev[0] || 0;
|
||||
let end = prev[1] && prev[1] + 1 || mat.length;
|
||||
if (!Array.isArray(prev) && args.length === 1) {
|
||||
result[prev].fill(value);
|
||||
} else if (args.length === 1) {
|
||||
for (let ind = start; ind < end; ind++) {
|
||||
result[ind].fill(value);
|
||||
}
|
||||
}
|
||||
for (let i = 1; i < args.length; i++) {
|
||||
let first = Array.isArray(args[i]) ? args[i][0] || 0 : args[i];
|
||||
let last = Array.isArray(args[i]) ? args[i][1] && args[i][1] + 1 || mat[0].length : args[i] + 1;
|
||||
if (!Array.isArray(prev)) {
|
||||
result[prev].fill(value, first, last);
|
||||
} else {
|
||||
for (let ind = start; ind < end; ind++) {
|
||||
result[ind].fill(value, first, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Operates on two matrices of the same size
|
||||
*
|
||||
* @param mat input matrix that initialized the function
|
||||
* @param operand second matrix with which operation is performed
|
||||
* @param operation function performing the desired operation
|
||||
* @returns result of the operation
|
||||
*/
|
||||
function operate(mat, operand, operation) {
|
||||
let result = [];
|
||||
let op = operand();
|
||||
|
||||
for (let i = 0; i < mat.length; i++) {
|
||||
let op1 = mat[i];
|
||||
let op2 = op[i];
|
||||
result.push(op1.map(function(elem, ind) {
|
||||
return operation(elem, op2[ind]);
|
||||
}));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the product of two matrices
|
||||
*
|
||||
* @param mat input matrix that initialized the function
|
||||
* @param operand second matrix with which operation is performed
|
||||
* @returns the product of the two matrices
|
||||
*/
|
||||
function prod(mat, operand) {
|
||||
let op1 = mat;
|
||||
let op2 = operand();
|
||||
let size1 = size(op1);
|
||||
let size2 = size(op2);
|
||||
let result = [];
|
||||
if (size1[1] === size2[0]) {
|
||||
for (let i = 0; i < size1[0]; i++) {
|
||||
result[i] = [];
|
||||
for (let j = 0; j < size2[1]; j++) {
|
||||
for (let k = 0; k < size1[1]; k++) {
|
||||
if (result[i][j] === undefined) {
|
||||
result[i][j] = 0;
|
||||
}
|
||||
result[i][j] += multiplication(op1[i][k], op2[k][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the transpose of a matrix, swaps rows with columns
|
||||
*
|
||||
* @param mat input matrix that initialized the function
|
||||
* @returns a matrix with rows and columns swapped from the original matrix
|
||||
*/
|
||||
function trans(mat) {
|
||||
let input = mat;
|
||||
let s = size(mat);
|
||||
let output = [];
|
||||
for (let i = 0; i < s[0]; i++) {
|
||||
for (let j = 0; j < s[1]; j++) {
|
||||
if (Array.isArray(output[j])) {
|
||||
output[j].push(input[i][j]);
|
||||
} else {
|
||||
output[j] = [input[i][j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private method to clone the matrix
|
||||
*
|
||||
* @param mat input matrix that initialized the function
|
||||
* @returns cloned matrix
|
||||
*/
|
||||
function clone(mat) {
|
||||
let result = [];
|
||||
for (let i = 0; i < mat.length; i++) {
|
||||
result.push(mat[i].slice(0));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs addition
|
||||
*
|
||||
* @param op1 first operand
|
||||
* @param op2 second operand
|
||||
* @returns result
|
||||
*/
|
||||
function addition(op1, op2) {
|
||||
return op1 + op2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs subtraction
|
||||
*
|
||||
* @param op1 first operand
|
||||
* @param op2 second operand
|
||||
* @returns result
|
||||
*/
|
||||
function subtraction(op1, op2) {
|
||||
return op1 - op2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs multiplication
|
||||
*
|
||||
* @param op1 first operand
|
||||
* @param op2 second operand
|
||||
* @returns result
|
||||
*/
|
||||
function multiplication(op1, op2) {
|
||||
return op1 * op2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs division
|
||||
*
|
||||
* @param op1 first operand
|
||||
* @param op2 second operand
|
||||
* @returns result
|
||||
*/
|
||||
function division(op1, op2) {
|
||||
return op1/op2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the determinant using row reduced echelon form
|
||||
* Works best if the elements are integers or rational numbers
|
||||
* The matrix must be a square
|
||||
*
|
||||
* @param mat input matrix that initialized the function
|
||||
* @returns determinant value as a number
|
||||
*/
|
||||
function determinant(mat) {
|
||||
let rationalized = rationalize(mat);
|
||||
let siz = size(mat);
|
||||
let det = rational(1);
|
||||
let sign = 1;
|
||||
|
||||
for (let i = 0; i < siz[0] - 1; i++) {
|
||||
for (let j = i + 1; j < siz[0]; j++) {
|
||||
if (rationalized[j][i].num === 0) {
|
||||
continue;
|
||||
}
|
||||
if (rationalized[i][i].num === 0) {
|
||||
interchange(rationalized, i, j);
|
||||
sign = -sign;
|
||||
continue;
|
||||
}
|
||||
let temp = rationalized[j][i].div(rationalized[i][i]);
|
||||
temp = rational(Math.abs(temp.num), temp.den);
|
||||
if (Math.sign(rationalized[j][i].num) === Math.sign(rationalized[i][i].num)) {
|
||||
temp = rational(-temp.num, temp.den);
|
||||
}
|
||||
for (let k = 0; k < siz[1]; k++) {
|
||||
rationalized[j][k] = temp.mul(rationalized[i][k]).add(rationalized[j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
det = rationalized.reduce((prev, curr, index) => prev.mul(curr[index]), rational(1));
|
||||
|
||||
return sign * det.num/det.den;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interchanges one row index with another on passed matrix
|
||||
*
|
||||
* @param mat input matrix
|
||||
* @param ind1 one of the row indices to exchange
|
||||
* @param ind2 one of the row indices to exchange
|
||||
*/
|
||||
function interchange(mat, ind1, ind2) {
|
||||
let temp = mat[ind1];
|
||||
mat[ind1] = mat[ind2];
|
||||
mat[ind2] = temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts the input square matrix using row reduction technique
|
||||
* Works best if the elements are integers or rational numbers
|
||||
* The matrix has to be a square and non-singular
|
||||
*
|
||||
* @param mat input matrix
|
||||
* @returns inverse of the input matrix
|
||||
*/
|
||||
function invert(mat) {
|
||||
let rationalized = rationalize(mat);
|
||||
let siz = size(mat);
|
||||
let result = rationalize(generate(1).diag(siz[0]));
|
||||
|
||||
// row reduction
|
||||
let i = 0;
|
||||
let j = 0;
|
||||
while (j < siz[0]) {
|
||||
if (rationalized[i][j].num === 0) {
|
||||
for (let k = i + 1; k < siz[0]; k++) {
|
||||
if (rationalized[k][j].num !== 0) {
|
||||
interchange(rationalized, i, k);
|
||||
interchange(result, i, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rationalized[i][j].num !== 0) {
|
||||
if (rationalized[i][j].num !== 1 || rationalized[i][j].den !== 1) {
|
||||
let factor = rational(rationalized[i][j].num, rationalized[i][j].den);
|
||||
for (let col = 0; col < siz[1]; col++) {
|
||||
rationalized[i][col] = rationalized[i][col].div(factor);
|
||||
result[i][col] = result[i][col].div(factor);
|
||||
}
|
||||
}
|
||||
for (let k = i + 1; k < siz[0]; k++) {
|
||||
let temp = rationalized[k][j];
|
||||
for (let col = 0; col < siz[1]; col++) {
|
||||
rationalized[k][col] = rationalized[k][col].sub(temp.mul(rationalized[i][col]));
|
||||
result[k][col] = result[k][col].sub(temp.mul(result[i][col]));
|
||||
}
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
j += 1;
|
||||
}
|
||||
|
||||
// Further reduction to convert rationalized to identity
|
||||
let last = siz[0] - 1;
|
||||
if (rationalized[last][last].num !== 1 || rationalized[last][last].den !== 1) {
|
||||
let factor = rational(rationalized[last][last].num, rationalized[last][last].den);
|
||||
for (let col = 0; col < siz[1]; col++) {
|
||||
rationalized[last][col] = rationalized[last][col].div(factor);
|
||||
result[last][col] = result[last][col].div(factor);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = siz[0] - 1; i > 0; i--) {
|
||||
for (let j = i - 1; j >= 0; j--) {
|
||||
let temp = rational(-rationalized[j][i].num, rationalized[j][i].den);
|
||||
for (let k = 0; k < siz[1]; k++) {
|
||||
rationalized[j][k] = temp.mul(rationalized[i][k]).add(rationalized[j][k]);
|
||||
result[j][k] = temp.mul(result[i][k]).add(result[j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return derationalize(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a given function over the matrix, elementwise. Similar to Array.map()
|
||||
* The supplied function is provided 4 arguments:
|
||||
* the current element,
|
||||
* the row index,
|
||||
* the col index,
|
||||
* the matrix.
|
||||
*
|
||||
* @param mat input matrix
|
||||
* @returns matrix of same dimensions with values altered by the function.
|
||||
*/
|
||||
function map(mat, func) {
|
||||
const s = size(mat);
|
||||
const result = [];
|
||||
for (let i = 0; i < s[0]; i++) {
|
||||
if(Array.isArray(mat[i])) {
|
||||
result[i] = [];
|
||||
for (let j = 0; j < s[1]; j++) {
|
||||
result[i][j] = func(mat[i][j], [i, j], mat);
|
||||
}
|
||||
} else {
|
||||
result[i] = func(mat[i], [i, 0], mat);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a matrix of numbers to all rational type objects
|
||||
*
|
||||
* @param mat input matrix
|
||||
* @returns matrix with elements of type rational
|
||||
*/
|
||||
function rationalize(mat) {
|
||||
let rationalized = [];
|
||||
mat.forEach((row, ind) => {
|
||||
rationalized.push(row.map((ele) => rational(ele)));
|
||||
});
|
||||
return rationalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a rationalized matrix to all numerical values
|
||||
*
|
||||
* @param mat input matrix
|
||||
* @returns matrix with numerical values
|
||||
*/
|
||||
function derationalize(mat) {
|
||||
let derationalized = [];
|
||||
mat.forEach((row, ind) => {
|
||||
derationalized.push(row.map((ele) => ele.num/ele.den));
|
||||
});
|
||||
return derationalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the equality of two matrices
|
||||
* @param mat input matrix
|
||||
* @param operand second matrix
|
||||
*/
|
||||
function equals(mat, operand) {
|
||||
let op1 = mat;
|
||||
let op2 = operand();
|
||||
let size1 = size(op1);
|
||||
let size2 = size(op2);
|
||||
|
||||
if (!size1.every((val, ind) => val === size2[ind])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return op1.every((val, ind1) => val.every((ele, ind2) => Math.abs(ele - op2[ind1][ind2]) < 1e-10));
|
||||
}
|
||||
117
node_modules/matrix-js/lib/merge.js
generated
vendored
Normal file
117
node_modules/matrix-js/lib/merge.js
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Merges two matrices in all directions
|
||||
*
|
||||
* @param {Array} base Base matrix on which merge is performed
|
||||
*/
|
||||
function merge(base) {
|
||||
return {
|
||||
top: (mergeData) => top(base, mergeData),
|
||||
bottom: (mergeData) => bottom(base, mergeData),
|
||||
left: (mergeData) => left(base, mergeData),
|
||||
right: (mergeData) => right(base, mergeData)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = merge;
|
||||
|
||||
/**
|
||||
* Merges the base matrix with the incoming matrix in the top direction
|
||||
* @param {Array} base
|
||||
* @param {Array} mergeData incoming matrix
|
||||
*/
|
||||
function top(base, mergeData) {
|
||||
let baseWidth = base[0].length || base.length;
|
||||
let mergeDataWidth = mergeData[mergeData.length - 1].length || mergeData.length;
|
||||
|
||||
if (baseWidth !== mergeDataWidth) {
|
||||
return base;
|
||||
}
|
||||
|
||||
if (!Array.isArray(base[0])) {
|
||||
base = [base];
|
||||
}
|
||||
|
||||
if (!Array.isArray(mergeData[mergeData.length - 1])) {
|
||||
mergeData = [mergeData];
|
||||
}
|
||||
|
||||
for (let row = mergeData.length - 1; row >= 0; row--) {
|
||||
base.unshift(mergeData[row].map((ele) => ele));
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the base matrix with the incoming matrix in the bottom direction
|
||||
* @param {Array} base
|
||||
* @param {Array} mergeData incoming matrix
|
||||
*/
|
||||
function bottom(base, mergeData) {
|
||||
let baseWidth = base[base.length - 1].length || base.length;
|
||||
let mergeDataWidth = mergeData[0].length || mergeData.length;
|
||||
if (baseWidth !== mergeDataWidth) {
|
||||
return base;
|
||||
}
|
||||
|
||||
if (!Array.isArray(base[base.length - 1])) {
|
||||
base = [base];
|
||||
}
|
||||
|
||||
if (!Array.isArray(mergeData[0])) {
|
||||
mergeData = [mergeData];
|
||||
}
|
||||
|
||||
|
||||
for (let row = 0; row < mergeData.length; row++) {
|
||||
base.push(mergeData[row].map((ele) => ele));
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the base matrix with the incoming matrix in the left direction
|
||||
* @param {Array} base
|
||||
* @param {Array} mergeData incoming matrix
|
||||
*/
|
||||
function left(base, mergeData) {
|
||||
let baseHeight = base.length;
|
||||
let mergeDataHeight = mergeData.length;
|
||||
if (!Array.isArray(base[0]) && !Array.isArray(mergeData[0])) {
|
||||
base.unshift.apply(base, mergeData);
|
||||
return base;
|
||||
}
|
||||
|
||||
if (baseHeight !== mergeDataHeight) {
|
||||
return base;
|
||||
}
|
||||
|
||||
for (let row = 0; row < baseHeight; row++) {
|
||||
base[row].unshift.apply(base[row], mergeData[row].map((ele) => ele));
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the base matrix with the incoming matrix in the right direction
|
||||
* @param {Array} base
|
||||
* @param {Array} mergeData incoming matrix
|
||||
*/
|
||||
function right(base, mergeData) {
|
||||
let baseHeight = base.length;
|
||||
let mergeDataHeight = mergeData.length;
|
||||
if (!Array.isArray(base[0]) && !Array.isArray(mergeData[0])) {
|
||||
base.push.apply(base, mergeData);
|
||||
return base;
|
||||
}
|
||||
|
||||
if (baseHeight !== mergeDataHeight) {
|
||||
return base;
|
||||
}
|
||||
|
||||
for (let row = 0; row < baseHeight; row++) {
|
||||
base[row].push.apply(base[row], mergeData[row].map((ele) => ele));
|
||||
}
|
||||
return base;
|
||||
}
|
||||
57
node_modules/matrix-js/lib/rational.js
generated
vendored
Normal file
57
node_modules/matrix-js/lib/rational.js
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Constructs an object storing rational numbers and methods performing operations
|
||||
*
|
||||
* @param num numerator of the rational number
|
||||
* @param den denomenator of the rational number
|
||||
* @returns Object storing the rational number and method doing arthmetic operations
|
||||
*/
|
||||
function rational(num, den) {
|
||||
den = den || 1;
|
||||
if (Math.sign(den) === -1) {
|
||||
num = -num;
|
||||
den = -den;
|
||||
}
|
||||
return {
|
||||
num: num,
|
||||
den: den,
|
||||
add: (op) => rational(num * op.den + den * op.num, den * op.den),
|
||||
sub: (op) => rational(num * op.den - den * op.num, den * op.den),
|
||||
mul: (op) => multiply(op, num, den),
|
||||
div: (op) => {
|
||||
let _num = op.den;
|
||||
let _den = op.num;
|
||||
return multiply(rational(_num, _den), num, den);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = rational;
|
||||
|
||||
/**
|
||||
* Multiplies two rational number based on multiplication rules that cancels common terms
|
||||
*
|
||||
* @param op the second operand
|
||||
* @param num numerator of first operand
|
||||
* @param den denominator of second operand
|
||||
* @returns another rational number
|
||||
*/
|
||||
function multiply(op, num, den) {
|
||||
let _num = Math.sign(num) * Math.sign(op.num);
|
||||
let _den = Math.sign(den) * Math.sign(op.den);
|
||||
if (Math.abs(num) === Math.abs(op.den) && Math.abs(den) === Math.abs(op.num)) {
|
||||
_num = _num;
|
||||
_den = _den;
|
||||
} else if (Math.abs(den) === Math.abs(op.num)) {
|
||||
_num = _num * Math.abs(num);
|
||||
_den = _den * Math.abs(op.den);
|
||||
} else if (Math.abs(num) === Math.abs(op.den)) {
|
||||
_num = _num * Math.abs(op.num);
|
||||
_den = _den * Math.abs(den);
|
||||
} else {
|
||||
_num = num * op.num;
|
||||
_den = den * op.den;
|
||||
}
|
||||
return rational(_num, _den);
|
||||
}
|
||||
35
node_modules/matrix-js/package.json
generated
vendored
Normal file
35
node_modules/matrix-js/package.json
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "matrix-js",
|
||||
"version": "1.8.0",
|
||||
"description": "A Javascript Library to perform basic matrix operations using the functional nature of Javascript",
|
||||
"main": "lib",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha --recursive --reporter spec"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/raghavgujjar/matrix.git"
|
||||
},
|
||||
"keywords": [
|
||||
"matrix",
|
||||
"linear",
|
||||
"algebra"
|
||||
],
|
||||
"author": "Raghavendra Ravikumar <raghavendra.ravikumar@gmail.com>",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/raghavgujjar/matrix/blob/master/LICENSE-MIT"
|
||||
}
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/raghavgujjar/matrix/issues"
|
||||
},
|
||||
"homepage": "https://github.com/raghavgujjar/matrix#readme",
|
||||
"devDependencies": {
|
||||
"mocha": "^9"
|
||||
}
|
||||
}
|
||||
174
node_modules/matrix-js/test/index.js
generated
vendored
Normal file
174
node_modules/matrix-js/test/index.js
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
'use strict';
|
||||
|
||||
const matrix = require('../lib');
|
||||
const assert = require('assert');
|
||||
let a, a1, a2, a3, a4, mat, mat1, mat2, mat3, mat4, m;
|
||||
|
||||
it('should exist', () => {
|
||||
assert.ok(matrix);
|
||||
});
|
||||
|
||||
it('should throw not array', () => {
|
||||
assert.throws(matrix, Error, 'Input should be of type array');
|
||||
});
|
||||
|
||||
describe('Matrix operations', () => {
|
||||
before(() => {
|
||||
a = [[1, 2, 3], [4, 5, 6]];
|
||||
a1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
||||
a2 = [[1, 1, 1], [1, 1, 1], [1, 1, 1]];
|
||||
a3 = [[7, 8], [9, 10], [11, 12]];
|
||||
m = matrix([[2, 2, 2], [2, 2, 2], [2, 2, 2]]);
|
||||
mat = matrix(a);
|
||||
mat1 = matrix(a1);
|
||||
mat2 = matrix(a2);
|
||||
mat3 = matrix(a3);
|
||||
});
|
||||
it('should return size', () => {
|
||||
assert.deepEqual(mat.size(), [2, 3]);
|
||||
});
|
||||
|
||||
it('should return back the matrix', () => {
|
||||
assert.deepEqual(mat(), a);
|
||||
});
|
||||
|
||||
it('should return a single element', () => {
|
||||
assert.equal(mat(0, 0), 1);
|
||||
});
|
||||
|
||||
it('should return a row', () => {
|
||||
assert.deepEqual(mat(0), [1, 2, 3]);
|
||||
});
|
||||
|
||||
it('should return column', () => {
|
||||
assert.deepEqual(mat([],0), [[1],[4]]);
|
||||
});
|
||||
|
||||
it('should return in specified range', () => {
|
||||
assert.deepEqual(mat([1,0],[2,1]), [[6, 5], [3, 2]]);
|
||||
assert.deepEqual(mat(0,[2,1]), [3, 2]);
|
||||
assert.deepEqual(mat([1,0],1), [[5], [2]]);
|
||||
});
|
||||
|
||||
it('should replace the specified index', () => {
|
||||
assert.deepEqual(mat.set(1).to(8), [[1,2,3], [8,8,8]]);
|
||||
assert.deepEqual(mat.set(1,2).to(8), [[1,2,3], [4,5,8]]);
|
||||
assert.deepEqual(mat.set([],1).to(8), [[1,8,3], [4,8,6]]);
|
||||
assert.deepEqual(mat1.set([],[1,2]).to(8), [[1,8,8], [4,8,8], [7,8,8]]);
|
||||
assert.deepEqual(mat1.set([1,2],[1,2]).to(8), [[1,2,3], [4,8,8], [7,8,8]]);
|
||||
});
|
||||
|
||||
it('should add two matrices', () => {
|
||||
assert.deepEqual(mat1.add(mat2), [[2, 3, 4], [5, 6, 7], [8, 9, 10]]);
|
||||
});
|
||||
|
||||
it('should subtract two matrices', () => {
|
||||
assert.deepEqual(mat1.sub(mat2), [[0, 1, 2], [3, 4, 5], [6, 7, 8]]);
|
||||
});
|
||||
|
||||
|
||||
it('should find scalar product two matrices', () => {
|
||||
assert.deepEqual(mat1.mul(m), [[2, 4, 6], [8, 10, 12], [14, 16, 18]]);
|
||||
});
|
||||
|
||||
it('should divide each element of two matrices', () => {
|
||||
assert.deepEqual(mat1.div(m), [[0.5, 1, 1.5], [2, 2.5, 3], [3.5, 4, 4.5]]);
|
||||
});
|
||||
|
||||
it('should find the product of two matrices', () => {
|
||||
assert.deepEqual(mat1.prod(mat2), [[6, 6, 6], [15, 15, 15], [24, 24, 24]]);
|
||||
assert.deepEqual(mat.prod(mat3), [[58, 64], [139, 154]]);
|
||||
assert.deepEqual(mat3.prod(mat), [[39, 54, 69], [49, 68, 87], [59, 82, 105]]);
|
||||
});
|
||||
|
||||
it('should return the transpose of a matrix', () => {
|
||||
assert.deepEqual(mat.trans(), [[1, 4], [2, 5], [3, 6]]);
|
||||
assert.deepEqual(mat1.trans(), [[1, 4, 7], [2, 5, 8], [3, 6, 9]]);
|
||||
});
|
||||
|
||||
it('should return the determinant', () => {
|
||||
assert.equal(mat1.det(), 0);
|
||||
assert.equal(matrix([[8, 4, 3], [8, 1, 1], [6, 3, 4]]).det(), -42);
|
||||
assert.equal(matrix([[3, 4, 7], [0, 0, 6], [8, 3, 2]]).det(), 138);
|
||||
assert.equal(matrix([[5, 4, 7], [4, 8, 2], [9, 0, 4]]).det(), -336);
|
||||
});
|
||||
|
||||
it('should invert the matrix', () => {
|
||||
assert.deepEqual(matrix([[5, 4, 7], [4, 8, 2], [9, 0, 4]]).inv(),
|
||||
[
|
||||
[-0.09523809523809523, 0.047619047619047616, 0.14285714285714285],
|
||||
[-0.005952380952380952, 0.12797619047619047, -0.05357142857142857],
|
||||
[0.21428571428571427, -0.10714285714285714, -0.07142857142857142]
|
||||
]
|
||||
);
|
||||
assert.deepEqual(matrix([[1, 3, 3], [1, 4, 3], [1, 3, 4]]).inv(),
|
||||
[[7, -3, -3], [-1, 1, 0], [-1, 0, 1]]);
|
||||
assert.deepEqual(matrix([[3, 4, 7], [0, 0, 6], [8, 3, 2]]).inv(),
|
||||
[
|
||||
[-0.13043478260869565, 0.09420289855072464, 0.17391304347826086],
|
||||
[0.34782608695652173, -0.36231884057971014, -0.13043478260869565],
|
||||
[0, 0.16666666666666666, 0]
|
||||
]);
|
||||
assert.deepEqual(matrix([[0, 1, 0],[0, 0, 1],[1, 1, 1]]).inv(),
|
||||
[[-1, -1, 1],[1, 0, 0],[0, 1, 0]]);
|
||||
assert.deepEqual(matrix([[0, 1, 0], [-1, 0, 1], [0, 0, 1]]).inv(),
|
||||
[[0, -1, 1], [1, 0, 0], [0, 0, 1]]);
|
||||
});
|
||||
|
||||
it('should merge two matrices', () => {
|
||||
// top
|
||||
assert.deepEqual(mat.merge.top([11, 12, 13]), [[11, 12, 13], [1, 2, 3], [4, 5, 6]]);
|
||||
assert.deepEqual(matrix([2, 3, 4]).merge.top([1, 2, 3]), [[1, 2, 3], [2, 3, 4]]);
|
||||
assert.deepEqual(matrix([2, 3, 4]).merge.top([[1, 2, 3],[4, 5, 6]]), [[1, 2, 3], [4, 5, 6], [2, 3, 4]]);
|
||||
|
||||
// bottom
|
||||
assert.deepEqual(mat1.merge.bottom([11, 12, 13]), [[1, 2, 3], [4, 5, 6], [7, 8, 9], [11, 12, 13]]);
|
||||
assert.deepEqual(matrix([2, 3, 4]).merge.bottom([1, 2, 3]), [[2, 3, 4], [1, 2, 3]]);
|
||||
assert.deepEqual(matrix([2, 3, 4]).merge.bottom([[1, 2, 3],[4, 5, 6]]), [[2, 3, 4], [1, 2, 3], [4, 5, 6]]);
|
||||
|
||||
// left
|
||||
assert.deepEqual(matrix([[1], [3], [5]]).merge.left([[2], [4], [6]]), [[2, 1], [4, 3], [6, 5]]);
|
||||
assert.deepEqual(matrix([5, 6, 7]).merge.left([1, 2, 3, 4]), [1, 2, 3, 4, 5, 6, 7]);
|
||||
assert.deepEqual(matrix([[2, 4], [5, 5]]).merge.left([[1, 1], [1, 1]]), [[1, 1, 2, 4], [1, 1, 5, 5]]);
|
||||
|
||||
// right
|
||||
assert.deepEqual(matrix([[1], [3], [5]]).merge.right([[2], [4], [6]]), [[1, 2], [3, 4], [5, 6]]);
|
||||
assert.deepEqual(matrix([1, 2, 3, 4]).merge.right([5, 6, 7]), [1, 2, 3, 4, 5, 6, 7]);
|
||||
assert.deepEqual(matrix([[2, 4], [5, 5]]).merge.right([[1, 1], [1, 1]]), [[2, 4, 1, 1], [5, 5, 1, 1]]);
|
||||
});
|
||||
|
||||
it('map: should map a function over a matrix', () => {
|
||||
const square = (x) => x*x;
|
||||
assert.deepEqual(matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).map(square),
|
||||
[[1, 2*2, 3*3], [4*4, 5*5, 6*6], [7*7, 8*8, 9*9]]);
|
||||
assert.deepEqual(matrix([1, 2, 3]).map(square), [1, 2*2, 3*3]);
|
||||
assert.deepEqual(matrix([[1, 2], [3, 4]]).map((ele, pos) => pos[0] === pos[1] ? ele : 0), [[1, 0], [0, 4]]);
|
||||
});
|
||||
|
||||
it('should check if two matrices are equal', () => {
|
||||
let A = matrix([[1/3,2],[3/5,4]]);
|
||||
let B = matrix([[1,2],[-1,3]]);
|
||||
let C = matrix([[1/3, 4, 5/9], [3/7, Math.E, Math.PI]]);
|
||||
assert.equal(A.equals(A), true);
|
||||
assert.equal(A.equals(B), false);
|
||||
assert.equal(C.equals(C), true);
|
||||
});
|
||||
|
||||
it('should generate a matrix', () => {
|
||||
assert.deepEqual(matrix.gen(4).size(2,3), [[4,4,4],[4,4,4]]);
|
||||
assert.deepEqual(matrix.gen(2).size(2), [[2,2],[2,2]]);
|
||||
assert.deepEqual(matrix.gen(1).diag(3,2), [[1,0],[0,1],[0,0]]);
|
||||
assert.deepEqual(matrix.gen(2).diag(3,4), [[2,0,0,0],[0,2,0,0],[0,0,2,0]]);
|
||||
assert.deepEqual(matrix.gen(1).diag(3), [[1,0,0],[0,1,0],[0,0,1]]);
|
||||
assert.ok(matrix.gen().size(2).flat().every(v => v >= 0 && v <= 1));
|
||||
console.log(matrix.gen().diag(3).flat());
|
||||
matrix.gen().diag(3).flat().forEach((v, i) => {
|
||||
if (i % 4 === 0) {
|
||||
console.log(i);
|
||||
assert.ok(v > 0 && v < 1);
|
||||
} else {
|
||||
assert.equal(v, 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
49
node_modules/matrix-js/test/rational.js
generated
vendored
Normal file
49
node_modules/matrix-js/test/rational.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
|
||||
const rational = require('../lib/rational');
|
||||
const assert = require('assert');
|
||||
|
||||
describe('rational operations', () => {
|
||||
it('should divide two equal rational numbers to return 1', () => {
|
||||
let result = rational(4, 5).div(rational(4, 5));
|
||||
assert.equal(result.num, 1);
|
||||
assert.equal(result.den, 1);
|
||||
});
|
||||
|
||||
it('should divide two rational numbers with same numerator', () => {
|
||||
let result = rational(4, 5).div(rational(4, 7));
|
||||
assert.equal(result.num, 7);
|
||||
assert.equal(result.den, 5);
|
||||
});
|
||||
|
||||
it('should multiply two inverse rational numbers to return 1', () => {
|
||||
let result = rational(4, 5).mul(rational(5, 4));
|
||||
let result2 = rational(-1,1).mul(rational(8, 1));
|
||||
let result3 = rational(-6, 8).mul(rational(8, 1));
|
||||
assert.equal(result.num, 1);
|
||||
assert.equal(result.den, 1);
|
||||
assert.equal(result2.num, -8);
|
||||
assert.equal(result2.den, 1);
|
||||
assert.equal(result3.num, -6);
|
||||
assert.equal(result3.den, 1);
|
||||
});
|
||||
|
||||
it('should multiply two rational numbers with same numerator and denominator', () => {
|
||||
let result = rational(4, 5).mul(rational(7, 4));
|
||||
assert.equal(result.num, 7);
|
||||
assert.equal(result.den, 5);
|
||||
});
|
||||
|
||||
|
||||
it('should add two rational numbers', () => {
|
||||
let result = rational(4, 5).add(rational(5, 4));
|
||||
assert.equal(result.num, 41);
|
||||
assert.equal(result.den, 20);
|
||||
});
|
||||
|
||||
it('should subtract two rational numbers', () => {
|
||||
let result = rational(4, 5).sub(rational(5, 4));
|
||||
assert.equal(result.num, -9);
|
||||
assert.equal(result.den, 20);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user