ml-matrix 6.5.3 → 6.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -7
- package/matrix.d.ts +16 -4
- package/matrix.js +87 -23
- package/matrix.umd.js +1 -1
- package/package.json +20 -19
- package/src/dc/evd.js +4 -0
- package/src/dc/nipals.js +3 -3
- package/src/dc/svd.js +4 -0
- package/src/determinant.js +4 -0
- package/src/matrix.js +61 -20
- package/src/pseudoInverse.js +6 -0
- package/src/util.js +6 -0
- package/CHANGELOG.md +0 -518
package/src/matrix.js
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
checkColumnVector,
|
|
30
30
|
checkRange,
|
|
31
31
|
checkIndices,
|
|
32
|
+
checkNonEmpty,
|
|
32
33
|
} from './util';
|
|
33
34
|
|
|
34
35
|
export class AbstractMatrix {
|
|
@@ -219,6 +220,10 @@ export class AbstractMatrix {
|
|
|
219
220
|
return this.rows === this.columns;
|
|
220
221
|
}
|
|
221
222
|
|
|
223
|
+
isEmpty() {
|
|
224
|
+
return this.rows === 0 || this.columns === 0;
|
|
225
|
+
}
|
|
226
|
+
|
|
222
227
|
isSymmetric() {
|
|
223
228
|
if (this.isSquare()) {
|
|
224
229
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -556,6 +561,9 @@ export class AbstractMatrix {
|
|
|
556
561
|
}
|
|
557
562
|
|
|
558
563
|
max() {
|
|
564
|
+
if (this.isEmpty()) {
|
|
565
|
+
return NaN;
|
|
566
|
+
}
|
|
559
567
|
let v = this.get(0, 0);
|
|
560
568
|
for (let i = 0; i < this.rows; i++) {
|
|
561
569
|
for (let j = 0; j < this.columns; j++) {
|
|
@@ -568,6 +576,7 @@ export class AbstractMatrix {
|
|
|
568
576
|
}
|
|
569
577
|
|
|
570
578
|
maxIndex() {
|
|
579
|
+
checkNonEmpty(this);
|
|
571
580
|
let v = this.get(0, 0);
|
|
572
581
|
let idx = [0, 0];
|
|
573
582
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -583,6 +592,9 @@ export class AbstractMatrix {
|
|
|
583
592
|
}
|
|
584
593
|
|
|
585
594
|
min() {
|
|
595
|
+
if (this.isEmpty()) {
|
|
596
|
+
return NaN;
|
|
597
|
+
}
|
|
586
598
|
let v = this.get(0, 0);
|
|
587
599
|
for (let i = 0; i < this.rows; i++) {
|
|
588
600
|
for (let j = 0; j < this.columns; j++) {
|
|
@@ -595,6 +607,7 @@ export class AbstractMatrix {
|
|
|
595
607
|
}
|
|
596
608
|
|
|
597
609
|
minIndex() {
|
|
610
|
+
checkNonEmpty(this);
|
|
598
611
|
let v = this.get(0, 0);
|
|
599
612
|
let idx = [0, 0];
|
|
600
613
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -611,6 +624,9 @@ export class AbstractMatrix {
|
|
|
611
624
|
|
|
612
625
|
maxRow(row) {
|
|
613
626
|
checkRowIndex(this, row);
|
|
627
|
+
if (this.isEmpty()) {
|
|
628
|
+
return NaN;
|
|
629
|
+
}
|
|
614
630
|
let v = this.get(row, 0);
|
|
615
631
|
for (let i = 1; i < this.columns; i++) {
|
|
616
632
|
if (this.get(row, i) > v) {
|
|
@@ -622,6 +638,7 @@ export class AbstractMatrix {
|
|
|
622
638
|
|
|
623
639
|
maxRowIndex(row) {
|
|
624
640
|
checkRowIndex(this, row);
|
|
641
|
+
checkNonEmpty(this);
|
|
625
642
|
let v = this.get(row, 0);
|
|
626
643
|
let idx = [row, 0];
|
|
627
644
|
for (let i = 1; i < this.columns; i++) {
|
|
@@ -635,6 +652,9 @@ export class AbstractMatrix {
|
|
|
635
652
|
|
|
636
653
|
minRow(row) {
|
|
637
654
|
checkRowIndex(this, row);
|
|
655
|
+
if (this.isEmpty()) {
|
|
656
|
+
return NaN;
|
|
657
|
+
}
|
|
638
658
|
let v = this.get(row, 0);
|
|
639
659
|
for (let i = 1; i < this.columns; i++) {
|
|
640
660
|
if (this.get(row, i) < v) {
|
|
@@ -646,6 +666,7 @@ export class AbstractMatrix {
|
|
|
646
666
|
|
|
647
667
|
minRowIndex(row) {
|
|
648
668
|
checkRowIndex(this, row);
|
|
669
|
+
checkNonEmpty(this);
|
|
649
670
|
let v = this.get(row, 0);
|
|
650
671
|
let idx = [row, 0];
|
|
651
672
|
for (let i = 1; i < this.columns; i++) {
|
|
@@ -659,6 +680,9 @@ export class AbstractMatrix {
|
|
|
659
680
|
|
|
660
681
|
maxColumn(column) {
|
|
661
682
|
checkColumnIndex(this, column);
|
|
683
|
+
if (this.isEmpty()) {
|
|
684
|
+
return NaN;
|
|
685
|
+
}
|
|
662
686
|
let v = this.get(0, column);
|
|
663
687
|
for (let i = 1; i < this.rows; i++) {
|
|
664
688
|
if (this.get(i, column) > v) {
|
|
@@ -670,6 +694,7 @@ export class AbstractMatrix {
|
|
|
670
694
|
|
|
671
695
|
maxColumnIndex(column) {
|
|
672
696
|
checkColumnIndex(this, column);
|
|
697
|
+
checkNonEmpty(this);
|
|
673
698
|
let v = this.get(0, column);
|
|
674
699
|
let idx = [0, column];
|
|
675
700
|
for (let i = 1; i < this.rows; i++) {
|
|
@@ -683,6 +708,9 @@ export class AbstractMatrix {
|
|
|
683
708
|
|
|
684
709
|
minColumn(column) {
|
|
685
710
|
checkColumnIndex(this, column);
|
|
711
|
+
if (this.isEmpty()) {
|
|
712
|
+
return NaN;
|
|
713
|
+
}
|
|
686
714
|
let v = this.get(0, column);
|
|
687
715
|
for (let i = 1; i < this.rows; i++) {
|
|
688
716
|
if (this.get(i, column) < v) {
|
|
@@ -694,6 +722,7 @@ export class AbstractMatrix {
|
|
|
694
722
|
|
|
695
723
|
minColumnIndex(column) {
|
|
696
724
|
checkColumnIndex(this, column);
|
|
725
|
+
checkNonEmpty(this);
|
|
697
726
|
let v = this.get(0, column);
|
|
698
727
|
let idx = [0, column];
|
|
699
728
|
for (let i = 1; i < this.rows; i++) {
|
|
@@ -1012,7 +1041,9 @@ export class AbstractMatrix {
|
|
|
1012
1041
|
let newMatrix = new Matrix(this.rows, this.columns);
|
|
1013
1042
|
for (let i = 0; i < this.rows; i++) {
|
|
1014
1043
|
const row = this.getRow(i);
|
|
1015
|
-
|
|
1044
|
+
if (row.length > 0) {
|
|
1045
|
+
rescale(row, { min, max, output: row });
|
|
1046
|
+
}
|
|
1016
1047
|
newMatrix.setRow(i, row);
|
|
1017
1048
|
}
|
|
1018
1049
|
return newMatrix;
|
|
@@ -1029,11 +1060,13 @@ export class AbstractMatrix {
|
|
|
1029
1060
|
let newMatrix = new Matrix(this.rows, this.columns);
|
|
1030
1061
|
for (let i = 0; i < this.columns; i++) {
|
|
1031
1062
|
const column = this.getColumn(i);
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1063
|
+
if (column.length) {
|
|
1064
|
+
rescale(column, {
|
|
1065
|
+
min: min,
|
|
1066
|
+
max: max,
|
|
1067
|
+
output: column,
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1037
1070
|
newMatrix.setColumn(i, column);
|
|
1038
1071
|
}
|
|
1039
1072
|
return newMatrix;
|
|
@@ -1086,6 +1119,18 @@ export class AbstractMatrix {
|
|
|
1086
1119
|
return result;
|
|
1087
1120
|
}
|
|
1088
1121
|
|
|
1122
|
+
kroneckerSum(other) {
|
|
1123
|
+
other = Matrix.checkMatrix(other);
|
|
1124
|
+
if (!this.isSquare() || !other.isSquare()) {
|
|
1125
|
+
throw new Error('Kronecker Sum needs two Square Matrices');
|
|
1126
|
+
}
|
|
1127
|
+
let m = this.rows;
|
|
1128
|
+
let n = other.rows;
|
|
1129
|
+
let AxI = this.kroneckerProduct(Matrix.eye(n, n));
|
|
1130
|
+
let IxB = Matrix.eye(m, m).kroneckerProduct(other);
|
|
1131
|
+
return AxI.add(IxB);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1089
1134
|
transpose() {
|
|
1090
1135
|
let result = new Matrix(this.columns, this.rows);
|
|
1091
1136
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -1176,6 +1221,9 @@ export class AbstractMatrix {
|
|
|
1176
1221
|
|
|
1177
1222
|
setSubMatrix(matrix, startRow, startColumn) {
|
|
1178
1223
|
matrix = Matrix.checkMatrix(matrix);
|
|
1224
|
+
if (matrix.isEmpty()) {
|
|
1225
|
+
return this;
|
|
1226
|
+
}
|
|
1179
1227
|
let endRow = startRow + matrix.rows - 1;
|
|
1180
1228
|
let endColumn = startColumn + matrix.columns - 1;
|
|
1181
1229
|
checkRange(this, startRow, endRow, startColumn, endColumn);
|
|
@@ -1404,9 +1452,8 @@ export class AbstractMatrix {
|
|
|
1404
1452
|
|
|
1405
1453
|
AbstractMatrix.prototype.klass = 'Matrix';
|
|
1406
1454
|
if (typeof Symbol !== 'undefined') {
|
|
1407
|
-
AbstractMatrix.prototype[
|
|
1408
|
-
|
|
1409
|
-
] = inspectMatrix;
|
|
1455
|
+
AbstractMatrix.prototype[Symbol.for('nodejs.util.inspect.custom')] =
|
|
1456
|
+
inspectMatrix;
|
|
1410
1457
|
}
|
|
1411
1458
|
|
|
1412
1459
|
function compareNumbers(a, b) {
|
|
@@ -1429,10 +1476,10 @@ export default class Matrix extends AbstractMatrix {
|
|
|
1429
1476
|
if (Matrix.isMatrix(nRows)) {
|
|
1430
1477
|
// eslint-disable-next-line no-constructor-return
|
|
1431
1478
|
return nRows.clone();
|
|
1432
|
-
} else if (Number.isInteger(nRows) && nRows
|
|
1479
|
+
} else if (Number.isInteger(nRows) && nRows >= 0) {
|
|
1433
1480
|
// Create an empty matrix
|
|
1434
1481
|
this.data = [];
|
|
1435
|
-
if (Number.isInteger(nColumns) && nColumns
|
|
1482
|
+
if (Number.isInteger(nColumns) && nColumns >= 0) {
|
|
1436
1483
|
for (let i = 0; i < nRows; i++) {
|
|
1437
1484
|
this.data.push(new Float64Array(nColumns));
|
|
1438
1485
|
}
|
|
@@ -1443,8 +1490,8 @@ export default class Matrix extends AbstractMatrix {
|
|
|
1443
1490
|
// Copy the values from the 2D array
|
|
1444
1491
|
const arrayData = nRows;
|
|
1445
1492
|
nRows = arrayData.length;
|
|
1446
|
-
nColumns = arrayData[0].length;
|
|
1447
|
-
if (typeof nColumns !== 'number'
|
|
1493
|
+
nColumns = nRows ? arrayData[0].length : 0;
|
|
1494
|
+
if (typeof nColumns !== 'number') {
|
|
1448
1495
|
throw new TypeError(
|
|
1449
1496
|
'Data must be a 2D array with at least one element',
|
|
1450
1497
|
);
|
|
@@ -1476,9 +1523,6 @@ export default class Matrix extends AbstractMatrix {
|
|
|
1476
1523
|
|
|
1477
1524
|
removeRow(index) {
|
|
1478
1525
|
checkRowIndex(this, index);
|
|
1479
|
-
if (this.rows === 1) {
|
|
1480
|
-
throw new RangeError('A matrix cannot have less than one row');
|
|
1481
|
-
}
|
|
1482
1526
|
this.data.splice(index, 1);
|
|
1483
1527
|
this.rows -= 1;
|
|
1484
1528
|
return this;
|
|
@@ -1490,7 +1534,7 @@ export default class Matrix extends AbstractMatrix {
|
|
|
1490
1534
|
index = this.rows;
|
|
1491
1535
|
}
|
|
1492
1536
|
checkRowIndex(this, index, true);
|
|
1493
|
-
array = Float64Array.from(checkRowVector(this, array
|
|
1537
|
+
array = Float64Array.from(checkRowVector(this, array));
|
|
1494
1538
|
this.data.splice(index, 0, array);
|
|
1495
1539
|
this.rows += 1;
|
|
1496
1540
|
return this;
|
|
@@ -1498,9 +1542,6 @@ export default class Matrix extends AbstractMatrix {
|
|
|
1498
1542
|
|
|
1499
1543
|
removeColumn(index) {
|
|
1500
1544
|
checkColumnIndex(this, index);
|
|
1501
|
-
if (this.columns === 1) {
|
|
1502
|
-
throw new RangeError('A matrix cannot have less than one column');
|
|
1503
|
-
}
|
|
1504
1545
|
for (let i = 0; i < this.rows; i++) {
|
|
1505
1546
|
const newRow = new Float64Array(this.columns - 1);
|
|
1506
1547
|
for (let j = 0; j < index; j++) {
|
package/src/pseudoInverse.js
CHANGED
|
@@ -3,6 +3,12 @@ import Matrix from './matrix';
|
|
|
3
3
|
|
|
4
4
|
export function pseudoInverse(matrix, threshold = Number.EPSILON) {
|
|
5
5
|
matrix = Matrix.checkMatrix(matrix);
|
|
6
|
+
if (matrix.isEmpty()) {
|
|
7
|
+
// with a zero dimension, the pseudo-inverse is the transpose, since all 0xn and nx0 matrices are singular
|
|
8
|
+
// (0xn)*(nx0)*(0xn) = 0xn
|
|
9
|
+
// (nx0)*(0xn)*(nx0) = nx0
|
|
10
|
+
return matrix.transpose();
|
|
11
|
+
}
|
|
6
12
|
let svdSolution = new SVD(matrix, { autoTranspose: true });
|
|
7
13
|
|
|
8
14
|
let U = svdSolution.leftSingularVectors;
|
package/src/util.js
CHANGED