@smockle/matrix 4.0.1 → 4.0.3

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/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { fill, padStart, unzip } from "lodash";
1
+ import { fill, padStart, unzip } from "lodash-es";
2
2
  import { inv } from "mathjs";
3
3
  /**
4
4
  * Creates a Matrix
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@smockle/matrix",
3
- "version": "4.0.1",
3
+ "version": "4.0.3",
4
4
  "description": "Single and multi dimensional matrices and matrix functions.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "scripts": {
8
8
  "build": "tsc",
9
- "test": "jest"
9
+ "test": "NODE_OPTIONS='--no-warnings=ExperimentalWarning --experimental-vm-modules' npx jest"
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
@@ -19,11 +19,11 @@
19
19
  },
20
20
  "homepage": "https://github.com/smockle/matrix#readme",
21
21
  "dependencies": {
22
- "lodash": "^4.17.4",
22
+ "lodash-es": "^4.17.21",
23
23
  "mathjs": "^14.0.1"
24
24
  },
25
25
  "devDependencies": {
26
- "@types/lodash": "^4.17.14",
26
+ "@types/lodash-es": "^4.17.12",
27
27
  "jest": "^29.7.0",
28
28
  "ts-jest": "^29.1.1",
29
29
  "typescript": "^5.2.2"
@@ -1 +0,0 @@
1
- * @smockle
@@ -1,34 +0,0 @@
1
- name: Publish
2
-
3
- on:
4
- release:
5
- types: [created]
6
-
7
- permissions:
8
- contents: read
9
- id-token: write
10
-
11
- jobs:
12
- test:
13
- name: Test
14
- uses: smockle/matrix/.github/workflows/test.yml@main
15
- secrets: inherit
16
- publish:
17
- needs: [test]
18
- name: Publish
19
- runs-on: ubuntu-latest
20
- steps:
21
- - uses: actions/checkout@v4
22
- - uses: actions/setup-node@v4
23
- with:
24
- node-version: 22
25
- registry-url: https://registry.npmjs.org/
26
- cache: npm
27
- - run: npm ci
28
- - run: npm run build
29
- - run: npm version ${TAG_NAME} --git-tag-version=false
30
- env:
31
- TAG_NAME: ${{ github.event.release.tag_name }}
32
- - run: npm whoami; npm --ignore-scripts publish --provenance --access public
33
- env:
34
- NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
@@ -1,31 +0,0 @@
1
- name: Test
2
-
3
- on:
4
- workflow_call:
5
- secrets:
6
- CODECOV_TOKEN:
7
- required: true
8
- pull_request:
9
-
10
- permissions:
11
- contents: read
12
-
13
- jobs:
14
- test:
15
- name: Test
16
- runs-on: ubuntu-latest
17
- steps:
18
- - uses: actions/checkout@v4
19
- - uses: actions/setup-node@v4
20
- with:
21
- node-version: 22
22
- registry-url: https://registry.npmjs.org/
23
- cache: npm
24
- - run: npm ci
25
- - run: npm run build
26
- - run: npm test
27
- - if: github.actor != 'dependabot[bot]'
28
- name: Upload coverage reports to Codecov
29
- uses: codecov/codecov-action@v5
30
- with:
31
- token: ${{ secrets.CODECOV_TOKEN }}
@@ -1 +0,0 @@
1
- export {};
@@ -1,355 +0,0 @@
1
- import { inspect } from "node:util";
2
- import { describe, test, expect } from "@jest/globals";
3
- import Matrix from "../index.js";
4
- describe("Matrix", () => {
5
- const error = new TypeError("Matrix must be a number or array of numbers");
6
- test("instanceof Matrix", () => {
7
- expect(Matrix([])).toBeInstanceOf(Matrix);
8
- });
9
- test("throws unnecessary nesting", () => {
10
- expect(Matrix.bind(Matrix, [[1, 2]])).toThrowError(error);
11
- });
12
- test("throws uneven rows", () => {
13
- expect(Matrix.bind(Matrix, [[1, 2], [3], [4, 5]])).toThrowError(error);
14
- });
15
- test("does not throw number", () => {
16
- expect(Matrix.bind(Matrix, 1)).not.toThrowError(error);
17
- });
18
- test("does not throw number array", () => {
19
- expect(Matrix.bind(Matrix, [1])).not.toThrowError(error);
20
- });
21
- test("does not throw 2D number array", () => {
22
- expect(Matrix.bind(Matrix, [[1], [2]])).not.toThrowError(error);
23
- });
24
- });
25
- describe("Matrix.addable", () => {
26
- test("addable mismatched columns", () => {
27
- expect(Matrix.addable(Matrix([
28
- [1, 2],
29
- [3, 4],
30
- ]), Matrix([
31
- [1, 2, 3],
32
- [4, 5, 6],
33
- ]))).toBeFalsy();
34
- });
35
- test("addable mismatched rows", () => {
36
- expect(Matrix.addable(Matrix([
37
- [1, 2],
38
- [3, 4],
39
- ]), Matrix([
40
- [1, 2],
41
- [4, 5],
42
- [7, 8],
43
- ]))).toBeFalsy();
44
- });
45
- test("addable", () => {
46
- expect(Matrix.addable(Matrix([
47
- [1, 2],
48
- [3, 4],
49
- ]), Matrix([
50
- [5, 6],
51
- [7, 8],
52
- ]))).toBeTruthy();
53
- });
54
- });
55
- describe("Matrix#addable", () => {
56
- test("addable mismatched columns", () => {
57
- expect(Matrix([
58
- [1, 2],
59
- [3, 4],
60
- ]).addable(Matrix([
61
- [1, 2, 3],
62
- [4, 5, 6],
63
- ]))).toBeFalsy();
64
- });
65
- test("addable mismatched rows", () => {
66
- expect(Matrix([
67
- [1, 2],
68
- [3, 4],
69
- ]).addable(Matrix([
70
- [1, 2],
71
- [4, 5],
72
- [7, 8],
73
- ]))).toBeFalsy();
74
- });
75
- test("addable", () => {
76
- expect(Matrix([
77
- [1, 2],
78
- [3, 4],
79
- ]).addable(Matrix([
80
- [5, 6],
81
- [7, 8],
82
- ]))).toBeTruthy();
83
- });
84
- });
85
- describe("Matrix.add", () => {
86
- test("add throws typerror", () => {
87
- expect(Matrix.add.bind(Matrix, Matrix([
88
- [1, 2],
89
- [3, 4],
90
- ]), Matrix([
91
- [1, 2, 3],
92
- [4, 5, 6],
93
- ]))).toThrowError(new TypeError("Matrices are not addable"));
94
- });
95
- test("add", () => {
96
- expect(Matrix.add(Matrix([
97
- [1, 2],
98
- [3, 4],
99
- ]), Matrix([
100
- [5, 6],
101
- [7, 8],
102
- ]))).toStrictEqual(Matrix([
103
- [6, 8],
104
- [10, 12],
105
- ]));
106
- });
107
- });
108
- describe("Matrix#add", () => {
109
- const addmatrix = Matrix([
110
- [1, 2],
111
- [3, 4],
112
- ]);
113
- test("add throws typerror", () => {
114
- expect(addmatrix.add.bind(addmatrix, Matrix([
115
- [1, 2, 3],
116
- [4, 5, 6],
117
- ]))).toThrowError(new TypeError("Matrices are not addable"));
118
- });
119
- test("add", () => {
120
- expect(Matrix([
121
- [1, 2],
122
- [3, 4],
123
- ]).add(Matrix([
124
- [5, 6],
125
- [7, 8],
126
- ]))).toStrictEqual(Matrix([
127
- [6, 8],
128
- [10, 12],
129
- ]));
130
- });
131
- });
132
- describe("Matrix.multipliable", () => {
133
- test("multipliable mismatched columns and rows", () => {
134
- expect(Matrix.multipliable(Matrix([
135
- [1, 2, 3],
136
- [4, 5, 6],
137
- ]), Matrix([
138
- [1, 2],
139
- [4, 5],
140
- ]))).toBeFalsy();
141
- });
142
- test("multipliable", () => {
143
- expect(Matrix.multipliable(Matrix([
144
- [1, 2],
145
- [3, 4],
146
- ]), Matrix([
147
- [5, 6],
148
- [7, 8],
149
- ]))).toBeTruthy();
150
- });
151
- });
152
- describe("Matrix#multipliable", () => {
153
- test("multipliable mismatched columns and rows", () => {
154
- expect(Matrix([
155
- [1, 2, 3],
156
- [4, 5, 6],
157
- ]).multipliable(Matrix([
158
- [1, 2],
159
- [4, 5],
160
- ]))).toBeFalsy();
161
- });
162
- test("multipliable", () => {
163
- expect(Matrix([
164
- [1, 2],
165
- [3, 4],
166
- ]).multipliable(Matrix([
167
- [5, 6],
168
- [7, 8],
169
- ]))).toBeTruthy();
170
- });
171
- });
172
- describe("Matrix.multiply", () => {
173
- const multiplymatrix = Matrix([1, 2, 3]);
174
- test("multiply throws typerror", () => {
175
- expect(multiplymatrix.multiply.bind(multiplymatrix, Matrix([
176
- [1, 2],
177
- [3, 4],
178
- ]))).toThrowError(new TypeError("Matrices are not multipliable"));
179
- });
180
- test("multiply number", () => {
181
- expect(Matrix(3).multiply(Matrix(6))).toStrictEqual(Matrix(18));
182
- });
183
- test("multiply A (1x2) and B (2x1)", () => {
184
- expect(Matrix([1, 2]).multiply(Matrix([[3], [4]]))).toStrictEqual(Matrix([11]));
185
- });
186
- test("multiply A (2x2) and B (2x2)", () => {
187
- expect(Matrix([
188
- [1, 2],
189
- [3, 4],
190
- ]).multiply(Matrix([
191
- [5, 6],
192
- [7, 8],
193
- ]))).toStrictEqual(Matrix([
194
- [19, 22],
195
- [43, 50],
196
- ]));
197
- });
198
- test("multiply A (2x3) and B (3x2)", () => {
199
- expect(Matrix([
200
- [1, 9, 7],
201
- [8, 1, 2],
202
- ]).multiply(Matrix([
203
- [3, 2, 1, 5],
204
- [5, 4, 7, 3],
205
- [6, 9, 6, 8],
206
- ]))).toStrictEqual(Matrix([
207
- [90, 101, 106, 88],
208
- [41, 38, 27, 59],
209
- ]));
210
- });
211
- });
212
- describe("Matrix#multiply", () => {
213
- test("multiply throws typerror", () => {
214
- expect(Matrix.multiply.bind(Matrix, Matrix([1, 2, 3]), Matrix([
215
- [1, 2],
216
- [3, 4],
217
- ]))).toThrowError(new TypeError("Matrices are not multipliable"));
218
- });
219
- test("multiply number", () => {
220
- expect(Matrix.multiply(Matrix(3), Matrix(6))).toStrictEqual(Matrix(18));
221
- });
222
- test("multiply A (1x2) and B (2x1)", () => {
223
- expect(Matrix.multiply(Matrix([1, 2]), Matrix([[3], [4]]))).toStrictEqual(Matrix([11]));
224
- });
225
- test("multiply A (2x2) and B (2x2)", () => {
226
- expect(Matrix.multiply(Matrix([
227
- [1, 2],
228
- [3, 4],
229
- ]), Matrix([
230
- [5, 6],
231
- [7, 8],
232
- ]))).toStrictEqual(Matrix([
233
- [19, 22],
234
- [43, 50],
235
- ]));
236
- });
237
- test("multiply A (2x3) and B (3x2)", () => {
238
- expect(Matrix.multiply(Matrix([
239
- [1, 9, 7],
240
- [8, 1, 2],
241
- ]), Matrix([
242
- [3, 2, 1, 5],
243
- [5, 4, 7, 3],
244
- [6, 9, 6, 8],
245
- ]))).toStrictEqual(Matrix([
246
- [90, 101, 106, 88],
247
- [41, 38, 27, 59],
248
- ]));
249
- });
250
- });
251
- describe("Matrix#valueOf", () => {
252
- const array = [3];
253
- test("valueOf Matrix", () => {
254
- expect(Matrix(array).valueOf()).toBe(array);
255
- });
256
- });
257
- describe("Matrix#countRows", () => {
258
- test("countRows number", () => {
259
- expect(Matrix(1).countRows()).toBe(0);
260
- });
261
- test("countRows number array", () => {
262
- expect(Matrix([1]).countRows()).toBe(1);
263
- });
264
- test("countRows 2D number array", () => {
265
- expect(Matrix([
266
- [1, 2],
267
- [3, 4],
268
- [5, 6],
269
- ]).countRows()).toBe(3);
270
- });
271
- });
272
- describe("Matrix#countColumns", () => {
273
- test("countColumns number", () => {
274
- expect(Matrix(1).countColumns()).toBe(0);
275
- });
276
- test("countColumns number array", () => {
277
- expect(Matrix([1]).countColumns()).toBe(1);
278
- });
279
- test("countColumns 2D number array", () => {
280
- expect(Matrix([[1], [2]]).countColumns()).toBe(1);
281
- });
282
- test("countColumns many 2D number array", () => {
283
- expect(Matrix([
284
- [1, 2],
285
- [3, 4],
286
- [5, 6],
287
- ]).countColumns()).toBe(2);
288
- });
289
- });
290
- describe("Matrix#transpose", () => {
291
- test("transpose number", () => {
292
- expect(Matrix(1).transpose()).toStrictEqual(Matrix(1));
293
- });
294
- test("transpose number array", () => {
295
- expect(Matrix([1, 2]).transpose()).toStrictEqual(Matrix([[1], [2]]));
296
- });
297
- test("transpose 2D number array", () => {
298
- expect(Matrix([
299
- [1, 2, 3],
300
- [4, 5, 6],
301
- ]).transpose()).toStrictEqual(Matrix([
302
- [1, 4],
303
- [2, 5],
304
- [3, 6],
305
- ]));
306
- });
307
- });
308
- describe("Matrix#invert", () => {
309
- test("invert 2D number array", () => {
310
- expect(Matrix([
311
- [1, 2],
312
- [3, 4],
313
- ]).invert()).toStrictEqual(Matrix([
314
- [-2, 1],
315
- [1.5, -0.5],
316
- ]));
317
- });
318
- });
319
- describe("Matrix#map", () => {
320
- const matrix = Matrix([1, 2, 3]);
321
- test("map returns a matrix", () => {
322
- expect(matrix.map((x) => x + 1)).toBeInstanceOf(Matrix);
323
- });
324
- test("map identity", () => {
325
- expect(matrix.map((x) => x)).toStrictEqual(matrix);
326
- });
327
- test("map increment", () => {
328
- expect(matrix.map((x) => x + 1)).toStrictEqual(Matrix([2, 3, 4]));
329
- });
330
- test("map non-mutable", () => {
331
- expect(matrix).toStrictEqual(Matrix([1, 2, 3]));
332
- });
333
- });
334
- describe("Matrix#inspect", () => {
335
- test("inspect number", () => {
336
- expect(inspect(Matrix(3))).toBe("3");
337
- });
338
- test("inspect number array", () => {
339
- expect(inspect(Matrix([1, 2, 3]))).toBe("[ 1 2 3 ]");
340
- });
341
- test("inspect 2D number array", () => {
342
- expect(inspect(Matrix([
343
- [1, 2, 3],
344
- [4, 5, 6],
345
- [7, 8, 9],
346
- ]))).toBe("[ 1 2 3 ]\n[ 4 5 6 ]\n[ 7 8 9 ]");
347
- });
348
- test("inspect padded 2D number array", () => {
349
- expect(inspect(Matrix([
350
- [1, 2, 3],
351
- [-10, 11, -12],
352
- [100, 0, 0],
353
- ]))).toBe("[ 1 2 3 ]\n[ -10 11 -12 ]\n[ 100 0 0 ]");
354
- });
355
- });
@@ -1,540 +0,0 @@
1
- import { inspect } from "node:util";
2
- import { describe, test, expect } from "@jest/globals";
3
- import Matrix from "../index.js";
4
-
5
- describe("Matrix", () => {
6
- const error = new TypeError("Matrix must be a number or array of numbers");
7
-
8
- test("instanceof Matrix", () => {
9
- expect(Matrix([])).toBeInstanceOf(Matrix);
10
- });
11
-
12
- test("throws unnecessary nesting", () => {
13
- expect(Matrix.bind(Matrix, [[1, 2]])).toThrowError(error);
14
- });
15
-
16
- test("throws uneven rows", () => {
17
- expect(Matrix.bind(Matrix, [[1, 2], [3], [4, 5]])).toThrowError(error);
18
- });
19
-
20
- test("does not throw number", () => {
21
- expect(Matrix.bind(Matrix, 1)).not.toThrowError(error);
22
- });
23
-
24
- test("does not throw number array", () => {
25
- expect(Matrix.bind(Matrix, [1])).not.toThrowError(error);
26
- });
27
-
28
- test("does not throw 2D number array", () => {
29
- expect(Matrix.bind(Matrix, [[1], [2]])).not.toThrowError(error);
30
- });
31
- });
32
-
33
- describe("Matrix.addable", () => {
34
- test("addable mismatched columns", () => {
35
- expect(
36
- Matrix.addable(
37
- Matrix([
38
- [1, 2],
39
- [3, 4],
40
- ]),
41
- Matrix([
42
- [1, 2, 3],
43
- [4, 5, 6],
44
- ])
45
- )
46
- ).toBeFalsy();
47
- });
48
-
49
- test("addable mismatched rows", () => {
50
- expect(
51
- Matrix.addable(
52
- Matrix([
53
- [1, 2],
54
- [3, 4],
55
- ]),
56
- Matrix([
57
- [1, 2],
58
- [4, 5],
59
- [7, 8],
60
- ])
61
- )
62
- ).toBeFalsy();
63
- });
64
-
65
- test("addable", () => {
66
- expect(
67
- Matrix.addable(
68
- Matrix([
69
- [1, 2],
70
- [3, 4],
71
- ]),
72
- Matrix([
73
- [5, 6],
74
- [7, 8],
75
- ])
76
- )
77
- ).toBeTruthy();
78
- });
79
- });
80
-
81
- describe("Matrix#addable", () => {
82
- test("addable mismatched columns", () => {
83
- expect(
84
- Matrix([
85
- [1, 2],
86
- [3, 4],
87
- ]).addable(
88
- Matrix([
89
- [1, 2, 3],
90
- [4, 5, 6],
91
- ])
92
- )
93
- ).toBeFalsy();
94
- });
95
-
96
- test("addable mismatched rows", () => {
97
- expect(
98
- Matrix([
99
- [1, 2],
100
- [3, 4],
101
- ]).addable(
102
- Matrix([
103
- [1, 2],
104
- [4, 5],
105
- [7, 8],
106
- ])
107
- )
108
- ).toBeFalsy();
109
- });
110
-
111
- test("addable", () => {
112
- expect(
113
- Matrix([
114
- [1, 2],
115
- [3, 4],
116
- ]).addable(
117
- Matrix([
118
- [5, 6],
119
- [7, 8],
120
- ])
121
- )
122
- ).toBeTruthy();
123
- });
124
- });
125
-
126
- describe("Matrix.add", () => {
127
- test("add throws typerror", () => {
128
- expect(
129
- Matrix.add.bind(
130
- Matrix,
131
- Matrix([
132
- [1, 2],
133
- [3, 4],
134
- ]),
135
- Matrix([
136
- [1, 2, 3],
137
- [4, 5, 6],
138
- ])
139
- )
140
- ).toThrowError(new TypeError("Matrices are not addable"));
141
- });
142
-
143
- test("add", () => {
144
- expect(
145
- Matrix.add(
146
- Matrix([
147
- [1, 2],
148
- [3, 4],
149
- ]),
150
- Matrix([
151
- [5, 6],
152
- [7, 8],
153
- ])
154
- )
155
- ).toStrictEqual(
156
- Matrix([
157
- [6, 8],
158
- [10, 12],
159
- ])
160
- );
161
- });
162
- });
163
-
164
- describe("Matrix#add", () => {
165
- const addmatrix = Matrix([
166
- [1, 2],
167
- [3, 4],
168
- ]);
169
-
170
- test("add throws typerror", () => {
171
- expect(
172
- addmatrix.add.bind(
173
- addmatrix,
174
- Matrix([
175
- [1, 2, 3],
176
- [4, 5, 6],
177
- ])
178
- )
179
- ).toThrowError(new TypeError("Matrices are not addable"));
180
- });
181
-
182
- test("add", () => {
183
- expect(
184
- Matrix([
185
- [1, 2],
186
- [3, 4],
187
- ]).add(
188
- Matrix([
189
- [5, 6],
190
- [7, 8],
191
- ])
192
- )
193
- ).toStrictEqual(
194
- Matrix([
195
- [6, 8],
196
- [10, 12],
197
- ])
198
- );
199
- });
200
- });
201
-
202
- describe("Matrix.multipliable", () => {
203
- test("multipliable mismatched columns and rows", () => {
204
- expect(
205
- Matrix.multipliable(
206
- Matrix([
207
- [1, 2, 3],
208
- [4, 5, 6],
209
- ]),
210
- Matrix([
211
- [1, 2],
212
- [4, 5],
213
- ])
214
- )
215
- ).toBeFalsy();
216
- });
217
-
218
- test("multipliable", () => {
219
- expect(
220
- Matrix.multipliable(
221
- Matrix([
222
- [1, 2],
223
- [3, 4],
224
- ]),
225
- Matrix([
226
- [5, 6],
227
- [7, 8],
228
- ])
229
- )
230
- ).toBeTruthy();
231
- });
232
- });
233
-
234
- describe("Matrix#multipliable", () => {
235
- test("multipliable mismatched columns and rows", () => {
236
- expect(
237
- Matrix([
238
- [1, 2, 3],
239
- [4, 5, 6],
240
- ]).multipliable(
241
- Matrix([
242
- [1, 2],
243
- [4, 5],
244
- ])
245
- )
246
- ).toBeFalsy();
247
- });
248
-
249
- test("multipliable", () => {
250
- expect(
251
- Matrix([
252
- [1, 2],
253
- [3, 4],
254
- ]).multipliable(
255
- Matrix([
256
- [5, 6],
257
- [7, 8],
258
- ])
259
- )
260
- ).toBeTruthy();
261
- });
262
- });
263
-
264
- describe("Matrix.multiply", () => {
265
- const multiplymatrix = Matrix([1, 2, 3]);
266
-
267
- test("multiply throws typerror", () => {
268
- expect(
269
- multiplymatrix.multiply.bind(
270
- multiplymatrix,
271
- Matrix([
272
- [1, 2],
273
- [3, 4],
274
- ])
275
- )
276
- ).toThrowError(new TypeError("Matrices are not multipliable"));
277
- });
278
-
279
- test("multiply number", () => {
280
- expect(Matrix(3).multiply(Matrix(6))).toStrictEqual(Matrix(18));
281
- });
282
-
283
- test("multiply A (1x2) and B (2x1)", () => {
284
- expect(Matrix([1, 2]).multiply(Matrix([[3], [4]]))).toStrictEqual(
285
- Matrix([11])
286
- );
287
- });
288
-
289
- test("multiply A (2x2) and B (2x2)", () => {
290
- expect(
291
- Matrix([
292
- [1, 2],
293
- [3, 4],
294
- ]).multiply(
295
- Matrix([
296
- [5, 6],
297
- [7, 8],
298
- ])
299
- )
300
- ).toStrictEqual(
301
- Matrix([
302
- [19, 22],
303
- [43, 50],
304
- ])
305
- );
306
- });
307
-
308
- test("multiply A (2x3) and B (3x2)", () => {
309
- expect(
310
- Matrix([
311
- [1, 9, 7],
312
- [8, 1, 2],
313
- ]).multiply(
314
- Matrix([
315
- [3, 2, 1, 5],
316
- [5, 4, 7, 3],
317
- [6, 9, 6, 8],
318
- ])
319
- )
320
- ).toStrictEqual(
321
- Matrix([
322
- [90, 101, 106, 88],
323
- [41, 38, 27, 59],
324
- ])
325
- );
326
- });
327
- });
328
-
329
- describe("Matrix#multiply", () => {
330
- test("multiply throws typerror", () => {
331
- expect(
332
- Matrix.multiply.bind(
333
- Matrix,
334
- Matrix([1, 2, 3]),
335
- Matrix([
336
- [1, 2],
337
- [3, 4],
338
- ])
339
- )
340
- ).toThrowError(new TypeError("Matrices are not multipliable"));
341
- });
342
-
343
- test("multiply number", () => {
344
- expect(Matrix.multiply(Matrix(3), Matrix(6))).toStrictEqual(Matrix(18));
345
- });
346
-
347
- test("multiply A (1x2) and B (2x1)", () => {
348
- expect(Matrix.multiply(Matrix([1, 2]), Matrix([[3], [4]]))).toStrictEqual(
349
- Matrix([11])
350
- );
351
- });
352
-
353
- test("multiply A (2x2) and B (2x2)", () => {
354
- expect(
355
- Matrix.multiply(
356
- Matrix([
357
- [1, 2],
358
- [3, 4],
359
- ]),
360
- Matrix([
361
- [5, 6],
362
- [7, 8],
363
- ])
364
- )
365
- ).toStrictEqual(
366
- Matrix([
367
- [19, 22],
368
- [43, 50],
369
- ])
370
- );
371
- });
372
-
373
- test("multiply A (2x3) and B (3x2)", () => {
374
- expect(
375
- Matrix.multiply(
376
- Matrix([
377
- [1, 9, 7],
378
- [8, 1, 2],
379
- ]),
380
- Matrix([
381
- [3, 2, 1, 5],
382
- [5, 4, 7, 3],
383
- [6, 9, 6, 8],
384
- ])
385
- )
386
- ).toStrictEqual(
387
- Matrix([
388
- [90, 101, 106, 88],
389
- [41, 38, 27, 59],
390
- ])
391
- );
392
- });
393
- });
394
-
395
- describe("Matrix#valueOf", () => {
396
- const array = [3];
397
-
398
- test("valueOf Matrix", () => {
399
- expect(Matrix(array).valueOf()).toBe(array);
400
- });
401
- });
402
-
403
- describe("Matrix#countRows", () => {
404
- test("countRows number", () => {
405
- expect(Matrix(1).countRows()).toBe(0);
406
- });
407
-
408
- test("countRows number array", () => {
409
- expect(Matrix([1]).countRows()).toBe(1);
410
- });
411
-
412
- test("countRows 2D number array", () => {
413
- expect(
414
- Matrix([
415
- [1, 2],
416
- [3, 4],
417
- [5, 6],
418
- ]).countRows()
419
- ).toBe(3);
420
- });
421
- });
422
-
423
- describe("Matrix#countColumns", () => {
424
- test("countColumns number", () => {
425
- expect(Matrix(1).countColumns()).toBe(0);
426
- });
427
-
428
- test("countColumns number array", () => {
429
- expect(Matrix([1]).countColumns()).toBe(1);
430
- });
431
-
432
- test("countColumns 2D number array", () => {
433
- expect(Matrix([[1], [2]]).countColumns()).toBe(1);
434
- });
435
-
436
- test("countColumns many 2D number array", () => {
437
- expect(
438
- Matrix([
439
- [1, 2],
440
- [3, 4],
441
- [5, 6],
442
- ]).countColumns()
443
- ).toBe(2);
444
- });
445
- });
446
-
447
- describe("Matrix#transpose", () => {
448
- test("transpose number", () => {
449
- expect(Matrix(1).transpose()).toStrictEqual(Matrix(1));
450
- });
451
-
452
- test("transpose number array", () => {
453
- expect(Matrix([1, 2]).transpose()).toStrictEqual(Matrix([[1], [2]]));
454
- });
455
-
456
- test("transpose 2D number array", () => {
457
- expect(
458
- Matrix([
459
- [1, 2, 3],
460
- [4, 5, 6],
461
- ]).transpose()
462
- ).toStrictEqual(
463
- Matrix([
464
- [1, 4],
465
- [2, 5],
466
- [3, 6],
467
- ])
468
- );
469
- });
470
- });
471
-
472
- describe("Matrix#invert", () => {
473
- test("invert 2D number array", () => {
474
- expect(
475
- Matrix([
476
- [1, 2],
477
- [3, 4],
478
- ]).invert()
479
- ).toStrictEqual(
480
- Matrix([
481
- [-2, 1],
482
- [1.5, -0.5],
483
- ])
484
- );
485
- });
486
- });
487
-
488
- describe("Matrix#map", () => {
489
- const matrix = Matrix([1, 2, 3]);
490
-
491
- test("map returns a matrix", () => {
492
- expect(matrix.map((x: number) => x + 1)).toBeInstanceOf(Matrix);
493
- });
494
-
495
- test("map identity", () => {
496
- expect(matrix.map((x: number) => x)).toStrictEqual(matrix);
497
- });
498
-
499
- test("map increment", () => {
500
- expect(matrix.map((x: number) => x + 1)).toStrictEqual(Matrix([2, 3, 4]));
501
- });
502
-
503
- test("map non-mutable", () => {
504
- expect(matrix).toStrictEqual(Matrix([1, 2, 3]));
505
- });
506
- });
507
-
508
- describe("Matrix#inspect", () => {
509
- test("inspect number", () => {
510
- expect(inspect(Matrix(3))).toBe("3");
511
- });
512
-
513
- test("inspect number array", () => {
514
- expect(inspect(Matrix([1, 2, 3]))).toBe("[ 1 2 3 ]");
515
- });
516
-
517
- test("inspect 2D number array", () => {
518
- expect(
519
- inspect(
520
- Matrix([
521
- [1, 2, 3],
522
- [4, 5, 6],
523
- [7, 8, 9],
524
- ])
525
- )
526
- ).toBe("[ 1 2 3 ]\n[ 4 5 6 ]\n[ 7 8 9 ]");
527
- });
528
-
529
- test("inspect padded 2D number array", () => {
530
- expect(
531
- inspect(
532
- Matrix([
533
- [1, 2, 3],
534
- [-10, 11, -12],
535
- [100, 0, 0],
536
- ])
537
- )
538
- ).toBe("[ 1 2 3 ]\n[ -10 11 -12 ]\n[ 100 0 0 ]");
539
- });
540
- });
package/src/index.ts DELETED
@@ -1,290 +0,0 @@
1
- import { fill, padStart, unzip } from "lodash";
2
- import { inv } from "mathjs";
3
-
4
- type Matrix = {
5
- __value: number | (number | number[])[];
6
- countRows: () => number;
7
- countColumns: () => number;
8
- addable: (y: Matrix) => boolean;
9
- add: (y: Matrix) => Matrix;
10
- multipliable: (y: Matrix) => boolean;
11
- multiply: (y: Matrix) => Matrix;
12
- transpose: () => Matrix;
13
- invert: () => Matrix;
14
- map: (x: any) => Matrix;
15
- valueOf: () => number | (number | number[])[];
16
- };
17
-
18
- /**
19
- * Creates a Matrix
20
- * @constructor
21
- * @alias module:matrix
22
- * @param {number|(number | number[])[]} x - Values to store in matrix
23
- * @throws {TypeError} Argument x must be a number or number array
24
- * @return {Matrix} Single or multi dimensional matrix
25
- */
26
- function Matrix(x: number | (number | number[])[]): Matrix {
27
- // extra nesting
28
- if (Array.isArray(x) && Array.isArray(x[0]) && x.length === 1) {
29
- throw new TypeError("Matrix must be a number or array of numbers");
30
- }
31
-
32
- // uneven rows
33
- if (
34
- Array.isArray(x) &&
35
- Array.isArray(x[0]) &&
36
- x.some(
37
- (row) => Array.isArray(row) && row.length !== (x[0] as number[]).length
38
- )
39
- ) {
40
- throw new TypeError("Matrix must be a number or array of numbers");
41
- }
42
-
43
- /* Single or multi dimensional matrix */
44
- const matrix = Object.create(Matrix.prototype);
45
- matrix.__value = x;
46
- return matrix;
47
- }
48
-
49
- /**
50
- * Determines whether two matrices can be summed
51
- * @alias module:matrix.addable
52
- * @param {Matrix} x - Matrix to check
53
- * @param {Matrix} y - Matrix to check
54
- * @return {boolean} Whether two matrices can be summed (using matrix addition)
55
- */
56
- Matrix.addable = function (x: Matrix, y: Matrix): boolean {
57
- return (
58
- x.countRows() === y.countRows() && x.countColumns() === y.countColumns()
59
- );
60
- };
61
-
62
- /**
63
- * Adds two matrices using matrix addition
64
- * @alias module:matrix.add
65
- * @param {Matrix} x - Matrix to add
66
- * @param {Matrix} y - Matrix to add
67
- * @throws {TypeError} Matrices are not addable
68
- * @return {Matrix} New matrix with the summation
69
- */
70
- Matrix.add = function (x: Matrix, y: Matrix): Matrix {
71
- if (!Matrix.addable(x, y)) throw new TypeError("Matrices are not addable");
72
- return x.map((row: number[], i: number): number[] =>
73
- row.map(
74
- (column: number, j: number): number =>
75
- column + (y.__value as number[][])[i][j]
76
- )
77
- );
78
- };
79
-
80
- /**
81
- * Determines whether two matrices can be multiplied
82
- * @alias module:matrix.multipliable
83
- * @param {Matrix} x - Matrix to check
84
- * @param {Matrix} y - Matrix to check
85
- * @return {boolean} Whether two matrices can be summed (using matrix multiplication)
86
- */
87
- Matrix.multipliable = function (x: Matrix, y: Matrix): boolean {
88
- return x.countColumns() === y.countRows();
89
- };
90
-
91
- /**
92
- * Calculates the inner product of two matrices
93
- * @param {Matrix} x - Matrix to multiply
94
- * @param {Matrix} y - Matrix to multiply
95
- * @param {number} i - Column in matrix y to multiply
96
- * @return {number} Inner product of matrices
97
- */
98
- function innerproduct(x: Matrix, y: Matrix, i: number): number {
99
- const _x: number[] = x.__value as number[];
100
- const _y: number[] =
101
- Array.isArray(unzip<number>(y.__value as number[][])) &&
102
- unzip<number>(y.__value as number[][]).length === 0
103
- ? unzip([y.__value as number[]])[i]
104
- : unzip(y.__value as number[][])[i];
105
- return ([] as number[])
106
- .concat(_x)
107
- .reduce((z: number, _z: number, j: number): number => z + _z * _y[j], 0);
108
- }
109
-
110
- /**
111
- * Calculates the dot product of two matrices
112
- * @alias module:matrix.multiply
113
- * @param {Matrix} x - Matrix to multiply
114
- * @param {Matrix} y - Matrix to multiply
115
- * @return {Matrix} New matrix with the dot product
116
- */
117
- Matrix.multiply = function (x: Matrix, y: Matrix): Matrix {
118
- if (!Matrix.multipliable(x, y)) {
119
- throw new TypeError("Matrices are not multipliable");
120
- }
121
-
122
- if (x.countColumns() === 0 && y.countRows() === 0) {
123
- return Matrix((x.__value as number) * (y.__value as number));
124
- }
125
-
126
- /* New matrix with the dot product */
127
- const z: Matrix = Matrix(
128
- fill(
129
- Array(x.countRows()),
130
- x.countRows() !== 1 ? fill(Array(y.countColumns()), 0) : 0
131
- )
132
- );
133
- return z.map((_z: number | number[], i: number): number | number[] => {
134
- if (typeof _z === "number") return innerproduct(x, y, i);
135
- return _z.map((_, j) =>
136
- innerproduct(Matrix((x.__value as number[])[i]), y, j)
137
- );
138
- });
139
- };
140
-
141
- /**
142
- * Inverts a matrix
143
- * @alias module:matrix.invert
144
- * @param {x} Matrix to invert
145
- * @return {Matrix} Matrix inverse
146
- */
147
- Matrix.invert = function (x: Matrix): Matrix {
148
- return Matrix(inv<any>(x instanceof Matrix ? x.__value : x));
149
- };
150
-
151
- /**
152
- * Counts rows in this matrix
153
- * @alias module:matrix#countRows
154
- * @return {number} Number of rows
155
- */
156
- Matrix.prototype.countRows = function (this: Matrix): number {
157
- if (typeof this.__value === "number") return 0;
158
- if (typeof this.__value[0] === "number") return 1;
159
- return this.__value.length;
160
- };
161
-
162
- /**
163
- * Counts columns in this matrix
164
- * @alias module:matrix#countColumns
165
- * @return {number} Number of columns
166
- */
167
- Matrix.prototype.countColumns = function (this: Matrix): number {
168
- if (typeof this.__value === "number") return 0;
169
- if (typeof this.__value[0] === "number") return this.__value.length;
170
- return this.__value[0].length;
171
- };
172
-
173
- /**
174
- * Determines whether this matrix can be summed
175
- * @alias module:matrix#addable
176
- * @param {Matrix} y - Matrix to check
177
- * @return {boolean} Whether this matrix can be summed (using matrix addition)
178
- */
179
- Matrix.prototype.addable = function (this: Matrix, y: Matrix): boolean {
180
- return Matrix.addable(this, y);
181
- };
182
-
183
- /**
184
- * Adds this matrix using matrix addition
185
- * @alias module:matrix#add
186
- * @param {Matrix} y - Matrix to add
187
- * @return {Matrix} New matrix with the summation
188
- */
189
- Matrix.prototype.add = function (this: Matrix, y: Matrix): Matrix {
190
- return Matrix.add(this, y);
191
- };
192
-
193
- /**
194
- * Determines whether this matrix can be multiplied
195
- * @alias module:matrix#multipliable
196
- * @param {Matrix} y - Matrix to check
197
- * @return {boolean} Whether two matrices can be summed (using matrix multiplication)
198
- */
199
- Matrix.prototype.multipliable = function (this: Matrix, y: Matrix): boolean {
200
- return Matrix.multipliable(this, y);
201
- };
202
-
203
- /**
204
- * Calculates the dot product of this matrix
205
- * @alias module:matrix#multiply
206
- * @param {Matrix} y - Matrix to multiply
207
- * @return {Matrix} New matrix with the dot product
208
- */
209
- Matrix.prototype.multiply = function (this: Matrix, y: Matrix): Matrix {
210
- return Matrix.multiply(this, y);
211
- };
212
-
213
- /**
214
- * Calculates the transpose of this matrix
215
- * @alias module:matrix#transpose
216
- * @return {Matrix} New matrix with the transpose
217
- */
218
- Matrix.prototype.transpose = function (this: Matrix): Matrix {
219
- switch (this.countRows()) {
220
- case 0:
221
- return Matrix(this.__value as number);
222
- case 1:
223
- return Matrix(unzip([this.__value as number[]]));
224
- default:
225
- return Matrix(unzip(this.__value as number[][]));
226
- }
227
- };
228
-
229
- /**
230
- * Inverts this matrix
231
- * @alias module:matrix#invert
232
- * @return {Matrix} Matrix inverse
233
- */
234
- Matrix.prototype.invert = function (this: Matrix): Matrix {
235
- return Matrix.invert(this);
236
- };
237
-
238
- /**
239
- * Maps over this matrix
240
- * @alias module:matrix#map
241
- * @return {Matrix} Matrix inverse
242
- */
243
- Matrix.prototype.map = function (this: Matrix, x: any): Matrix {
244
- if (typeof this.__value === "number") return Matrix(x(this.__value));
245
- return Matrix(this.__value.map(x));
246
- };
247
-
248
- /**
249
- * Returns the number or number array value
250
- * @alias module:matrix#valueOf
251
- * @return {number|number[]} Number of number array value
252
- */
253
- Matrix.prototype.valueOf = function (
254
- this: Matrix
255
- ): number | (number | number[])[] {
256
- return this.__value;
257
- };
258
-
259
- /**
260
- * Formats and prints the matrix value
261
- * @alias module:matrix#inspect
262
- * @return {string} Formatted matrix value
263
- */
264
- Matrix.prototype[Symbol.for("nodejs.util.inspect.custom")] = function (
265
- this: Matrix
266
- ): string {
267
- switch (this.countRows()) {
268
- case 0:
269
- return `${this.__value}`;
270
- case 1:
271
- return `[ ${(this.__value as number[]).join(" ")} ]`;
272
- default:
273
- /* Output array filled with zeroes */
274
- const padding: number[] = unzip(this.__value as number[][]).map(
275
- (column: number[]) =>
276
- column.reduce((length, x) => Math.max(`${x}`.length, length), 0)
277
- );
278
- return (this.__value as number[][])
279
- .reduce(
280
- (output, row) =>
281
- `${output}[ ${row
282
- .map((x, i) => padStart(`${x}`, padding[i]))
283
- .join(" ")} ]`,
284
- ""
285
- )
286
- .replace(/]\[/g, "]\n[");
287
- }
288
- };
289
-
290
- export default Matrix;
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "esnext",
4
- "module": "nodenext",
5
- "moduleResolution": "nodenext",
6
- "esModuleInterop": true,
7
- "strict": true,
8
- "rootDir": "src",
9
- "outDir": "dist",
10
- "composite": true,
11
- "incremental": true
12
- },
13
- "include": ["src/**/*.ts"],
14
- "ts-node": {
15
- "esm": true
16
- }
17
- }