Refactor: Implement SmartCube renderer, improve UI styling, and fix gaps

This commit is contained in:
2026-02-22 04:35:59 +00:00
parent 57abfd6b80
commit b5ddc21662
4168 changed files with 763782 additions and 1008 deletions

16
node_modules/matrix-js/LICENSE-MIT generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
});
});