@smockle/matrix 4.0.3 → 5.0.0

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 CHANGED
@@ -15,7 +15,7 @@ Run `npm install --save @smockle/matrix` to add `matrix` to your project.
15
15
  import Matrix from '@smockle/matrix'
16
16
 
17
17
  // 1x1 Matrix
18
- const m11 = Matrix(3)
18
+ const m11 = Matrix([3])
19
19
 
20
20
  // 1x3 Matrix
21
21
  const m13 = Matrix([1, 2, 3])
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- type Matrix = {
2
- __value: number | (number | number[])[];
1
+ interface IMatrix {
3
2
  countRows: () => number;
4
3
  countColumns: () => number;
5
4
  addable: (y: Matrix) => boolean;
@@ -9,17 +8,25 @@ type Matrix = {
9
8
  transpose: () => Matrix;
10
9
  invert: () => Matrix;
11
10
  map: (x: any) => Matrix;
12
- valueOf: () => number | (number | number[])[];
13
- };
11
+ }
12
+ interface Matrix1D extends IMatrix {
13
+ __value: number[];
14
+ valueOf: () => number[];
15
+ }
16
+ interface Matrix2D extends IMatrix {
17
+ __value: number[][];
18
+ valueOf: () => number[][];
19
+ }
20
+ type Matrix = Matrix1D | Matrix2D;
14
21
  /**
15
22
  * Creates a Matrix
16
23
  * @constructor
17
24
  * @alias module:matrix
18
- * @param {number|(number | number[])[]} x - Values to store in matrix
25
+ * @param {number[] | number[][]} x - Values to store in matrix
19
26
  * @throws {TypeError} Argument x must be a number or number array
20
27
  * @return {Matrix} Single or multi dimensional matrix
21
28
  */
22
- declare function Matrix(x: number | (number | number[])[]): Matrix;
29
+ declare function Matrix(x: number[] | number[][]): Matrix;
23
30
  declare namespace Matrix {
24
31
  var addable: (x: Matrix, y: Matrix) => boolean;
25
32
  var add: (x: Matrix, y: Matrix) => Matrix;
package/dist/index.js CHANGED
@@ -1,22 +1,25 @@
1
1
  import { fill, padStart, unzip } from "lodash-es";
2
2
  import { inv } from "mathjs";
3
+ function isMatrix1D(matrix) {
4
+ return matrix.countRows() === 1;
5
+ }
3
6
  /**
4
7
  * Creates a Matrix
5
8
  * @constructor
6
9
  * @alias module:matrix
7
- * @param {number|(number | number[])[]} x - Values to store in matrix
10
+ * @param {number[] | number[][]} x - Values to store in matrix
8
11
  * @throws {TypeError} Argument x must be a number or number array
9
12
  * @return {Matrix} Single or multi dimensional matrix
10
13
  */
11
14
  function Matrix(x) {
12
15
  // extra nesting
13
- if (Array.isArray(x) && Array.isArray(x[0]) && x.length === 1) {
16
+ if (Array.isArray(x[0]) && x.length === 1) {
14
17
  throw new TypeError("Matrix must be a number or array of numbers");
15
18
  }
16
19
  // uneven rows
17
- if (Array.isArray(x) &&
18
- Array.isArray(x[0]) &&
19
- x.some((row) => Array.isArray(row) && row.length !== x[0].length)) {
20
+ const firstRowLength = Array.isArray(x[0]) ? x[0].length : 0;
21
+ if (firstRowLength > 0 &&
22
+ x.some((row) => Array.isArray(row) && row.length !== firstRowLength)) {
20
23
  throw new TypeError("Matrix must be a number or array of numbers");
21
24
  }
22
25
  /* Single or multi dimensional matrix */
@@ -45,14 +48,16 @@ Matrix.addable = function (x, y) {
45
48
  Matrix.add = function (x, y) {
46
49
  if (!Matrix.addable(x, y))
47
50
  throw new TypeError("Matrices are not addable");
48
- return x.map((row, i) => row.map((column, j) => column + y.__value[i][j]));
51
+ return x.map((row, i) => row.map((column, j) => {
52
+ return column + (Array.isArray(y.__value[i]) ? y.__value[i][j] : 0);
53
+ }));
49
54
  };
50
55
  /**
51
56
  * Determines whether two matrices can be multiplied
52
57
  * @alias module:matrix.multipliable
53
58
  * @param {Matrix} x - Matrix to check
54
59
  * @param {Matrix} y - Matrix to check
55
- * @return {boolean} Whether two matrices can be summed (using matrix multiplication)
60
+ * @return {boolean} Whether two matrices can be multiplied (using matrix multiplication)
56
61
  */
57
62
  Matrix.multipliable = function (x, y) {
58
63
  return x.countColumns() === y.countRows();
@@ -66,13 +71,14 @@ Matrix.multipliable = function (x, y) {
66
71
  */
67
72
  function innerproduct(x, y, i) {
68
73
  const _x = x.__value;
69
- const _y = Array.isArray(unzip(y.__value)) &&
70
- unzip(y.__value).length === 0
71
- ? unzip([y.__value])[i]
72
- : unzip(y.__value)[i];
73
- return []
74
- .concat(_x)
75
- .reduce((z, _z, j) => z + _z * _y[j], 0);
74
+ let _y;
75
+ if (isMatrix1D(y)) {
76
+ _y = unzip([y.__value])[i];
77
+ }
78
+ else {
79
+ _y = unzip(y.__value)[i];
80
+ }
81
+ return [..._x].reduce((z, _z, j) => z + _z * _y[j], 0);
76
82
  }
77
83
  /**
78
84
  * Calculates the dot product of two matrices
@@ -85,16 +91,18 @@ Matrix.multiply = function (x, y) {
85
91
  if (!Matrix.multipliable(x, y)) {
86
92
  throw new TypeError("Matrices are not multipliable");
87
93
  }
88
- if (x.countColumns() === 0 && y.countRows() === 0) {
89
- return Matrix(x.__value * y.__value);
90
- }
91
94
  /* New matrix with the dot product */
92
- const z = Matrix(fill(Array(x.countRows()), x.countRows() !== 1 ? fill(Array(y.countColumns()), 0) : 0));
93
- return z.map((_z, i) => {
94
- if (typeof _z === "number")
95
- return innerproduct(x, y, i);
96
- return _z.map((_, j) => innerproduct(Matrix(x.__value[i]), y, j));
97
- });
95
+ if (isMatrix1D(x)) {
96
+ return Matrix([0]).map((_z, i) => innerproduct(x, y, i));
97
+ }
98
+ else {
99
+ return Matrix(fill(Array(x.countRows()), fill(Array(y.countColumns()), 0))).map((_z, i) => {
100
+ const _x = Matrix(x.__value[i]);
101
+ if (isMatrix1D(_x)) {
102
+ return _z.map((_, j) => innerproduct(_x, y, j));
103
+ }
104
+ });
105
+ }
98
106
  };
99
107
  /**
100
108
  * Inverts a matrix
@@ -111,8 +119,6 @@ Matrix.invert = function (x) {
111
119
  * @return {number} Number of rows
112
120
  */
113
121
  Matrix.prototype.countRows = function () {
114
- if (typeof this.__value === "number")
115
- return 0;
116
122
  if (typeof this.__value[0] === "number")
117
123
  return 1;
118
124
  return this.__value.length;
@@ -123,8 +129,6 @@ Matrix.prototype.countRows = function () {
123
129
  * @return {number} Number of columns
124
130
  */
125
131
  Matrix.prototype.countColumns = function () {
126
- if (typeof this.__value === "number")
127
- return 0;
128
132
  if (typeof this.__value[0] === "number")
129
133
  return this.__value.length;
130
134
  return this.__value[0].length;
@@ -171,13 +175,11 @@ Matrix.prototype.multiply = function (y) {
171
175
  * @return {Matrix} New matrix with the transpose
172
176
  */
173
177
  Matrix.prototype.transpose = function () {
174
- switch (this.countRows()) {
175
- case 0:
176
- return Matrix(this.__value);
177
- case 1:
178
- return Matrix(unzip([this.__value]));
179
- default:
180
- return Matrix(unzip(this.__value));
178
+ if (isMatrix1D(this)) {
179
+ return Matrix(unzip([this.__value]));
180
+ }
181
+ else {
182
+ return Matrix(unzip(this.__value));
181
183
  }
182
184
  };
183
185
  /**
@@ -194,14 +196,17 @@ Matrix.prototype.invert = function () {
194
196
  * @return {Matrix} Matrix inverse
195
197
  */
196
198
  Matrix.prototype.map = function (x) {
197
- if (typeof this.__value === "number")
198
- return Matrix(x(this.__value));
199
- return Matrix(this.__value.map(x));
199
+ if (isMatrix1D(this)) {
200
+ return Matrix(this.__value.map((x)));
201
+ }
202
+ else {
203
+ return Matrix(this.__value.map((x)));
204
+ }
200
205
  };
201
206
  /**
202
207
  * Returns the number or number array value
203
208
  * @alias module:matrix#valueOf
204
- * @return {number|number[]} Number of number array value
209
+ * @return {number[]|number[][]} Number of number array value
205
210
  */
206
211
  Matrix.prototype.valueOf = function () {
207
212
  return this.__value;
@@ -212,19 +217,17 @@ Matrix.prototype.valueOf = function () {
212
217
  * @return {string} Formatted matrix value
213
218
  */
214
219
  Matrix.prototype[Symbol.for("nodejs.util.inspect.custom")] = function () {
215
- switch (this.countRows()) {
216
- case 0:
217
- return `${this.__value}`;
218
- case 1:
219
- return `[ ${this.__value.join(" ")} ]`;
220
- default:
221
- /* Output array filled with zeroes */
222
- const padding = unzip(this.__value).map((column) => column.reduce((length, x) => Math.max(`${x}`.length, length), 0));
223
- return this.__value
224
- .reduce((output, row) => `${output}[ ${row
225
- .map((x, i) => padStart(`${x}`, padding[i]))
226
- .join(" ")} ]`, "")
227
- .replace(/]\[/g, "]\n[");
220
+ if (isMatrix1D(this)) {
221
+ return `[ ${this.__value.join(" ")} ]`;
222
+ }
223
+ else {
224
+ /* Output array filled with zeroes */
225
+ const padding = unzip(this.__value).map((column) => column.reduce((length, x) => Math.max(`${x}`.length, length), 0));
226
+ return this.__value
227
+ .reduce((output, row) => `${output}[ ${row
228
+ .map((x, i) => padStart(`${x}`, padding[i]))
229
+ .join(" ")} ]`, "")
230
+ .replace(/]\[/g, "]\n[");
228
231
  }
229
232
  };
230
233
  export default Matrix;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smockle/matrix",
3
- "version": "4.0.3",
3
+ "version": "5.0.0",
4
4
  "description": "Single and multi dimensional matrices and matrix functions.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",