@pawells/math-extended 1.0.1 → 1.0.2
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/package.json +1 -1
- package/build/angles.spec.d.ts +0 -2
- package/build/angles.spec.d.ts.map +0 -1
- package/build/angles.spec.js +0 -147
- package/build/angles.spec.js.map +0 -1
- package/build/clamp.spec.d.ts +0 -2
- package/build/clamp.spec.d.ts.map +0 -1
- package/build/clamp.spec.js +0 -19
- package/build/clamp.spec.js.map +0 -1
- package/build/documentation-validation.spec.d.ts +0 -11
- package/build/documentation-validation.spec.d.ts.map +0 -1
- package/build/documentation-validation.spec.js +0 -401
- package/build/documentation-validation.spec.js.map +0 -1
- package/build/interpolation.spec.d.ts +0 -2
- package/build/interpolation.spec.d.ts.map +0 -1
- package/build/interpolation.spec.js +0 -480
- package/build/interpolation.spec.js.map +0 -1
- package/build/matrices/arithmetic.spec.d.ts +0 -2
- package/build/matrices/arithmetic.spec.d.ts.map +0 -1
- package/build/matrices/arithmetic.spec.js +0 -915
- package/build/matrices/arithmetic.spec.js.map +0 -1
- package/build/matrices/asserts.spec.d.ts +0 -2
- package/build/matrices/asserts.spec.d.ts.map +0 -1
- package/build/matrices/asserts.spec.js +0 -565
- package/build/matrices/asserts.spec.js.map +0 -1
- package/build/matrices/core.spec.d.ts +0 -2
- package/build/matrices/core.spec.d.ts.map +0 -1
- package/build/matrices/core.spec.js +0 -634
- package/build/matrices/core.spec.js.map +0 -1
- package/build/matrices/decompositions.spec.d.ts +0 -2
- package/build/matrices/decompositions.spec.d.ts.map +0 -1
- package/build/matrices/decompositions.spec.js +0 -195
- package/build/matrices/decompositions.spec.js.map +0 -1
- package/build/matrices/linear-algebra.spec.d.ts +0 -2
- package/build/matrices/linear-algebra.spec.d.ts.map +0 -1
- package/build/matrices/linear-algebra.spec.js +0 -355
- package/build/matrices/linear-algebra.spec.js.map +0 -1
- package/build/matrices/normalization.spec.d.ts +0 -2
- package/build/matrices/normalization.spec.d.ts.map +0 -1
- package/build/matrices/normalization.spec.js +0 -335
- package/build/matrices/normalization.spec.js.map +0 -1
- package/build/matrices/transformations.spec.d.ts +0 -2
- package/build/matrices/transformations.spec.d.ts.map +0 -1
- package/build/matrices/transformations.spec.js +0 -755
- package/build/matrices/transformations.spec.js.map +0 -1
- package/build/quaternions/asserts.spec.d.ts +0 -2
- package/build/quaternions/asserts.spec.d.ts.map +0 -1
- package/build/quaternions/asserts.spec.js +0 -320
- package/build/quaternions/asserts.spec.js.map +0 -1
- package/build/quaternions/conversions.spec.d.ts +0 -2
- package/build/quaternions/conversions.spec.d.ts.map +0 -1
- package/build/quaternions/conversions.spec.js +0 -344
- package/build/quaternions/conversions.spec.js.map +0 -1
- package/build/quaternions/core.spec.d.ts +0 -2
- package/build/quaternions/core.spec.d.ts.map +0 -1
- package/build/quaternions/core.spec.js +0 -294
- package/build/quaternions/core.spec.js.map +0 -1
- package/build/quaternions/interpolation.spec.d.ts +0 -2
- package/build/quaternions/interpolation.spec.d.ts.map +0 -1
- package/build/quaternions/interpolation.spec.js +0 -64
- package/build/quaternions/interpolation.spec.js.map +0 -1
- package/build/quaternions/predefined.spec.d.ts +0 -2
- package/build/quaternions/predefined.spec.d.ts.map +0 -1
- package/build/quaternions/predefined.spec.js +0 -35
- package/build/quaternions/predefined.spec.js.map +0 -1
- package/build/random.spec.d.ts +0 -2
- package/build/random.spec.d.ts.map +0 -1
- package/build/random.spec.js +0 -267
- package/build/random.spec.js.map +0 -1
- package/build/vectors/asserts.spec.d.ts +0 -2
- package/build/vectors/asserts.spec.d.ts.map +0 -1
- package/build/vectors/asserts.spec.js +0 -260
- package/build/vectors/asserts.spec.js.map +0 -1
- package/build/vectors/core.spec.d.ts +0 -2
- package/build/vectors/core.spec.d.ts.map +0 -1
- package/build/vectors/core.spec.js +0 -343
- package/build/vectors/core.spec.js.map +0 -1
- package/build/vectors/interpolation.spec.d.ts +0 -2
- package/build/vectors/interpolation.spec.d.ts.map +0 -1
- package/build/vectors/interpolation.spec.js +0 -378
- package/build/vectors/interpolation.spec.js.map +0 -1
- package/build/vectors/predefined.spec.d.ts +0 -2
- package/build/vectors/predefined.spec.d.ts.map +0 -1
- package/build/vectors/predefined.spec.js +0 -333
- package/build/vectors/predefined.spec.js.map +0 -1
|
@@ -1,915 +0,0 @@
|
|
|
1
|
-
import { MatrixAdd, MatrixSubtract, MatrixMultiply, MatrixSubmatrix, MatrixPad, MatrixCombine, } from './arithmetic.js';
|
|
2
|
-
import { AssertMatrixRow } from './asserts.js';
|
|
3
|
-
import { MatrixCreate } from './core.js';
|
|
4
|
-
describe('Matrix Arithmetic', () => {
|
|
5
|
-
describe('MatrixAdd', () => {
|
|
6
|
-
it('should add two 1x1 matrices', () => {
|
|
7
|
-
const a = [[5]];
|
|
8
|
-
const b = [[3]];
|
|
9
|
-
const result = MatrixAdd(a, b);
|
|
10
|
-
expect(result).toEqual([[8]]);
|
|
11
|
-
});
|
|
12
|
-
it('should add two 2x2 matrices', () => {
|
|
13
|
-
const a = [[1, 2], [3, 4]];
|
|
14
|
-
const b = [[5, 6], [7, 8]];
|
|
15
|
-
const result = MatrixAdd(a, b);
|
|
16
|
-
expect(result).toEqual([[6, 8], [10, 12]]);
|
|
17
|
-
});
|
|
18
|
-
it('should add two 3x3 matrices', () => {
|
|
19
|
-
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
|
20
|
-
const b = [[9, 8, 7], [6, 5, 4], [3, 2, 1]];
|
|
21
|
-
const result = MatrixAdd(a, b);
|
|
22
|
-
expect(result).toEqual([[10, 10, 10], [10, 10, 10], [10, 10, 10]]);
|
|
23
|
-
});
|
|
24
|
-
it('should add matrices with negative numbers', () => {
|
|
25
|
-
const a = [[1, -2], [-3, 4]];
|
|
26
|
-
const b = [[-1, 2], [3, -4]];
|
|
27
|
-
const result = MatrixAdd(a, b);
|
|
28
|
-
expect(result).toEqual([[0, 0], [0, 0]]);
|
|
29
|
-
});
|
|
30
|
-
it('should add matrices with zeros', () => {
|
|
31
|
-
const a = [[1, 2], [3, 4]];
|
|
32
|
-
const b = [[0, 0], [0, 0]];
|
|
33
|
-
const result = MatrixAdd(a, b);
|
|
34
|
-
expect(result).toEqual([[1, 2], [3, 4]]);
|
|
35
|
-
});
|
|
36
|
-
it('should add matrices with decimal numbers', () => {
|
|
37
|
-
const a = [[1.5, 2.5], [3.5, 4.5]];
|
|
38
|
-
const b = [[0.5, 0.5], [0.5, 0.5]];
|
|
39
|
-
const result = MatrixAdd(a, b);
|
|
40
|
-
expect(result).toEqual([[2, 3], [4, 5]]);
|
|
41
|
-
});
|
|
42
|
-
it('should throw error for matrices with different dimensions', () => {
|
|
43
|
-
const a = [[1, 2], [3, 4]];
|
|
44
|
-
const b = [[1, 2, 3], [4, 5, 6]];
|
|
45
|
-
expect(() => MatrixAdd(a, b)).toThrow();
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
describe('MatrixSubtract', () => {
|
|
49
|
-
it('should subtract two 1x1 matrices', () => {
|
|
50
|
-
const a = [[8]];
|
|
51
|
-
const b = [[3]];
|
|
52
|
-
const result = MatrixSubtract(a, b);
|
|
53
|
-
expect(result).toEqual([[5]]);
|
|
54
|
-
});
|
|
55
|
-
it('should subtract two 2x2 matrices', () => {
|
|
56
|
-
const a = [[5, 6], [7, 8]];
|
|
57
|
-
const b = [[1, 2], [3, 4]];
|
|
58
|
-
const result = MatrixSubtract(a, b);
|
|
59
|
-
expect(result).toEqual([[4, 4], [4, 4]]);
|
|
60
|
-
});
|
|
61
|
-
it('should subtract two 3x3 matrices', () => {
|
|
62
|
-
const a = [[10, 10, 10], [10, 10, 10], [10, 10, 10]];
|
|
63
|
-
const b = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
|
64
|
-
const result = MatrixSubtract(a, b);
|
|
65
|
-
expect(result).toEqual([[9, 8, 7], [6, 5, 4], [3, 2, 1]]);
|
|
66
|
-
});
|
|
67
|
-
it('should handle negative results', () => {
|
|
68
|
-
const a = [[1, 2], [3, 4]];
|
|
69
|
-
const b = [[5, 6], [7, 8]];
|
|
70
|
-
const result = MatrixSubtract(a, b);
|
|
71
|
-
expect(result).toEqual([[-4, -4], [-4, -4]]);
|
|
72
|
-
});
|
|
73
|
-
it('should subtract zero matrix', () => {
|
|
74
|
-
const a = [[1, 2], [3, 4]];
|
|
75
|
-
const b = [[0, 0], [0, 0]];
|
|
76
|
-
const result = MatrixSubtract(a, b);
|
|
77
|
-
expect(result).toEqual([[1, 2], [3, 4]]);
|
|
78
|
-
});
|
|
79
|
-
it('should handle decimal numbers', () => {
|
|
80
|
-
const a = [[3.5, 4.5], [5.5, 6.5]];
|
|
81
|
-
const b = [[1.5, 2.5], [3.5, 4.5]];
|
|
82
|
-
const result = MatrixSubtract(a, b);
|
|
83
|
-
expect(result).toEqual([[2, 2], [2, 2]]);
|
|
84
|
-
});
|
|
85
|
-
it('should throw error for matrices with different dimensions', () => {
|
|
86
|
-
const a = [[1, 2], [3, 4]];
|
|
87
|
-
const b = [[1], [2], [3]];
|
|
88
|
-
expect(() => MatrixSubtract(a, b)).toThrow();
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
describe('MatrixMultiply', () => {
|
|
92
|
-
describe('overload: scalar multiplication (matrix, scalar) -> matrix', () => {
|
|
93
|
-
it('should multiply 1x1 matrix by scalar', () => {
|
|
94
|
-
const matrix = [[5]];
|
|
95
|
-
const result = MatrixMultiply(matrix, 3);
|
|
96
|
-
expect(result).toEqual([[15]]);
|
|
97
|
-
});
|
|
98
|
-
it('should multiply 2x2 matrix by scalar', () => {
|
|
99
|
-
const matrix = [[1, 2], [3, 4]];
|
|
100
|
-
const result = MatrixMultiply(matrix, 2);
|
|
101
|
-
expect(result).toEqual([[2, 4], [6, 8]]);
|
|
102
|
-
});
|
|
103
|
-
it('should multiply 3x3 matrix by scalar', () => {
|
|
104
|
-
const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
|
105
|
-
const result = MatrixMultiply(matrix, 2);
|
|
106
|
-
expect(result).toEqual([[2, 4, 6], [8, 10, 12], [14, 16, 18]]);
|
|
107
|
-
});
|
|
108
|
-
it('should multiply 4x4 matrix by scalar', () => {
|
|
109
|
-
const matrix = [
|
|
110
|
-
[1, 2, 3, 4],
|
|
111
|
-
[5, 6, 7, 8],
|
|
112
|
-
[9, 10, 11, 12],
|
|
113
|
-
[13, 14, 15, 16],
|
|
114
|
-
];
|
|
115
|
-
const result = MatrixMultiply(matrix, 0.5);
|
|
116
|
-
expect(result).toEqual([
|
|
117
|
-
[0.5, 1, 1.5, 2],
|
|
118
|
-
[2.5, 3, 3.5, 4],
|
|
119
|
-
[4.5, 5, 5.5, 6],
|
|
120
|
-
[6.5, 7, 7.5, 8],
|
|
121
|
-
]);
|
|
122
|
-
});
|
|
123
|
-
it('should multiply matrix by zero', () => {
|
|
124
|
-
const matrix = [[1, 2], [3, 4]];
|
|
125
|
-
const result = MatrixMultiply(matrix, 0);
|
|
126
|
-
expect(result).toEqual([[0, 0], [0, 0]]);
|
|
127
|
-
});
|
|
128
|
-
it('should multiply matrix by negative scalar', () => {
|
|
129
|
-
const matrix = [[1, 2], [3, 4]];
|
|
130
|
-
const result = MatrixMultiply(matrix, -1);
|
|
131
|
-
expect(result).toEqual([[-1, -2], [-3, -4]]);
|
|
132
|
-
});
|
|
133
|
-
it('should multiply matrix by decimal scalar', () => {
|
|
134
|
-
const matrix = [[2, 4], [6, 8]];
|
|
135
|
-
const result = MatrixMultiply(matrix, 0.5);
|
|
136
|
-
expect(result).toEqual([[1, 2], [3, 4]]);
|
|
137
|
-
});
|
|
138
|
-
it('should multiply rectangular matrix by scalar', () => {
|
|
139
|
-
const matrix = [[1, 2, 3], [4, 5, 6]];
|
|
140
|
-
const result = MatrixMultiply(matrix, 3);
|
|
141
|
-
expect(result).toEqual([[3, 6, 9], [12, 15, 18]]);
|
|
142
|
-
});
|
|
143
|
-
it('should preserve matrix type with scalar multiplication', () => {
|
|
144
|
-
const matrix = [[1, 2], [3, 4]];
|
|
145
|
-
const scalar = 5;
|
|
146
|
-
const result = MatrixMultiply(matrix, scalar);
|
|
147
|
-
expect(typeof result).toBe('object');
|
|
148
|
-
expect(Array.isArray(result)).toBe(true);
|
|
149
|
-
expect(Array.isArray(result[0])).toBe(true);
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
describe('overload: vector multiplication (matrix, vector) -> vector', () => {
|
|
153
|
-
it('should multiply 2x2 matrix by 2D vector', () => {
|
|
154
|
-
const matrix = [[1, 2], [3, 4]];
|
|
155
|
-
const vector = [5, 6];
|
|
156
|
-
const result = MatrixMultiply(matrix, vector);
|
|
157
|
-
expect(result).toEqual([17, 39]);
|
|
158
|
-
});
|
|
159
|
-
it('should multiply 3x3 matrix by 3D vector', () => {
|
|
160
|
-
const matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
|
161
|
-
const vector = [5, 6, 7];
|
|
162
|
-
const result = MatrixMultiply(matrix, vector);
|
|
163
|
-
expect(result).toEqual([5, 6, 7]);
|
|
164
|
-
});
|
|
165
|
-
it('should multiply 4x4 matrix by 4D vector', () => {
|
|
166
|
-
const matrix = [
|
|
167
|
-
[1, 0, 0, 0],
|
|
168
|
-
[0, 2, 0, 0],
|
|
169
|
-
[0, 0, 3, 0],
|
|
170
|
-
[0, 0, 0, 4],
|
|
171
|
-
];
|
|
172
|
-
const vector = [1, 2, 3, 4];
|
|
173
|
-
const result = MatrixMultiply(matrix, vector);
|
|
174
|
-
expect(result).toEqual([1, 4, 9, 16]);
|
|
175
|
-
});
|
|
176
|
-
it('should multiply rectangular matrix by vector', () => {
|
|
177
|
-
const matrix = [[1, 2, 3], [4, 5, 6]];
|
|
178
|
-
const vector = [1, 2, 3];
|
|
179
|
-
const result = MatrixMultiply(matrix, vector);
|
|
180
|
-
expect(result).toEqual([14, 32]);
|
|
181
|
-
});
|
|
182
|
-
it('should handle zero vector', () => {
|
|
183
|
-
const matrix = [[1, 2], [3, 4]];
|
|
184
|
-
const vector = [0, 0];
|
|
185
|
-
const result = MatrixMultiply(matrix, vector);
|
|
186
|
-
expect(result).toEqual([0, 0]);
|
|
187
|
-
});
|
|
188
|
-
it('should handle vector with negative values', () => {
|
|
189
|
-
const matrix = [[1, 2], [3, 4]];
|
|
190
|
-
const vector = [-1, 2];
|
|
191
|
-
const result = MatrixMultiply(matrix, vector);
|
|
192
|
-
expect(result).toEqual([3, 5]);
|
|
193
|
-
});
|
|
194
|
-
it('should handle vector with decimal values', () => {
|
|
195
|
-
const matrix = [[2, 0], [0, 2]];
|
|
196
|
-
const vector = [1.5, 2.5];
|
|
197
|
-
const result = MatrixMultiply(matrix, vector);
|
|
198
|
-
expect(result).toEqual([3, 5]);
|
|
199
|
-
});
|
|
200
|
-
it('should perform identity transformation', () => {
|
|
201
|
-
const identity = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
|
202
|
-
const vector = [7, 8, 9];
|
|
203
|
-
const result = MatrixMultiply(identity, vector);
|
|
204
|
-
expect(result).toEqual([7, 8, 9]);
|
|
205
|
-
});
|
|
206
|
-
it('should perform linear transformation', () => {
|
|
207
|
-
// Rotation by 90 degrees counterclockwise in 2D
|
|
208
|
-
const rotationMatrix = [[0, -1], [1, 0]];
|
|
209
|
-
const vector = [1, 0];
|
|
210
|
-
const result = MatrixMultiply(rotationMatrix, vector);
|
|
211
|
-
expect(result).toEqual([0, 1]);
|
|
212
|
-
});
|
|
213
|
-
it('should return vector result type', () => {
|
|
214
|
-
const matrix = [[1, 2], [3, 4]];
|
|
215
|
-
const vector = [1, 1];
|
|
216
|
-
const result = MatrixMultiply(matrix, vector);
|
|
217
|
-
expect(Array.isArray(result)).toBe(true);
|
|
218
|
-
expect(result.length).toBe(2);
|
|
219
|
-
expect(typeof result[0]).toBe('number');
|
|
220
|
-
expect(typeof result[1]).toBe('number');
|
|
221
|
-
});
|
|
222
|
-
it('should throw error for incompatible dimensions', () => {
|
|
223
|
-
const matrix = [[1, 2], [3, 4]];
|
|
224
|
-
const vector = [1, 2, 3]; // Wrong size
|
|
225
|
-
expect(() => MatrixMultiply(matrix, vector)).toThrow(/Matrix-vector multiplication requires matrix columns/);
|
|
226
|
-
});
|
|
227
|
-
it('should throw error for empty vector', () => {
|
|
228
|
-
const matrix = [[1, 2], [3, 4]];
|
|
229
|
-
const vector = [];
|
|
230
|
-
expect(() => MatrixMultiply(matrix, vector)).toThrow(/Matrix-vector multiplication requires matrix columns/);
|
|
231
|
-
});
|
|
232
|
-
it('should handle matrix-vector multiplication examples from documentation', () => {
|
|
233
|
-
// Example from the documentation
|
|
234
|
-
const matrix = [[1, 2, 3], [4, 5, 6]];
|
|
235
|
-
const vector = [7, 8, 9];
|
|
236
|
-
const result = MatrixMultiply(matrix, vector);
|
|
237
|
-
expect(result).toEqual([50, 122]);
|
|
238
|
-
});
|
|
239
|
-
it('should handle single row matrix multiplication', () => {
|
|
240
|
-
const matrix = [[1, 2, 3]];
|
|
241
|
-
const vector = [4, 5, 6];
|
|
242
|
-
const result = MatrixMultiply(matrix, vector);
|
|
243
|
-
expect(result).toEqual([32]);
|
|
244
|
-
});
|
|
245
|
-
it('should handle single column matrix multiplication', () => {
|
|
246
|
-
const matrix = [[1], [2], [3]];
|
|
247
|
-
const vector = [5];
|
|
248
|
-
const result = MatrixMultiply(matrix, vector);
|
|
249
|
-
expect(result).toEqual([5, 10, 15]);
|
|
250
|
-
});
|
|
251
|
-
it('should handle very large vectors', () => {
|
|
252
|
-
const matrix = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]];
|
|
253
|
-
const vector = [1, 1, 1, 1, 1];
|
|
254
|
-
const result = MatrixMultiply(matrix, vector);
|
|
255
|
-
expect(result).toEqual([15, 40]);
|
|
256
|
-
});
|
|
257
|
-
it('should preserve precision with decimal arithmetic', () => {
|
|
258
|
-
const matrix = [[0.1, 0.2], [0.3, 0.4]];
|
|
259
|
-
const vector = [0.5, 0.6];
|
|
260
|
-
const result = MatrixMultiply(matrix, vector);
|
|
261
|
-
expect(result[0]).toBeCloseTo(0.17, 10);
|
|
262
|
-
expect(result[1]).toBeCloseTo(0.39, 10);
|
|
263
|
-
});
|
|
264
|
-
it('should handle scaling transformations', () => {
|
|
265
|
-
const scalingMatrix = [[2, 0], [0, 3]];
|
|
266
|
-
const vector = [4, 5];
|
|
267
|
-
const result = MatrixMultiply(scalingMatrix, vector);
|
|
268
|
-
expect(result).toEqual([8, 15]);
|
|
269
|
-
});
|
|
270
|
-
it('should handle reflection transformations', () => {
|
|
271
|
-
// Reflection across x-axis
|
|
272
|
-
const reflectionMatrix = [[1, 0], [0, -1]];
|
|
273
|
-
const vector = [3, 4];
|
|
274
|
-
const result = MatrixMultiply(reflectionMatrix, vector);
|
|
275
|
-
expect(result).toEqual([3, -4]);
|
|
276
|
-
});
|
|
277
|
-
it('should handle shear transformations', () => {
|
|
278
|
-
// Horizontal shear
|
|
279
|
-
const shearMatrix = [[1, 2], [0, 1]];
|
|
280
|
-
const vector = [1, 3];
|
|
281
|
-
const result = MatrixMultiply(shearMatrix, vector);
|
|
282
|
-
expect(result).toEqual([7, 3]);
|
|
283
|
-
});
|
|
284
|
-
});
|
|
285
|
-
describe('overload: matrix multiplication (matrix, matrix) -> matrix', () => {
|
|
286
|
-
it('should multiply two 1x1 matrices', () => {
|
|
287
|
-
const a = [[5]];
|
|
288
|
-
const b = [[3]];
|
|
289
|
-
const result = MatrixMultiply(a, b);
|
|
290
|
-
expect(result).toEqual([[15]]);
|
|
291
|
-
});
|
|
292
|
-
it('should multiply two 2x2 matrices', () => {
|
|
293
|
-
const a = [[1, 2], [3, 4]];
|
|
294
|
-
const b = [[5, 6], [7, 8]];
|
|
295
|
-
const result = MatrixMultiply(a, b);
|
|
296
|
-
expect(result).toEqual([[19, 22], [43, 50]]);
|
|
297
|
-
});
|
|
298
|
-
it('should multiply two 3x3 matrices', () => {
|
|
299
|
-
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
|
300
|
-
const b = [[9, 8, 7], [6, 5, 4], [3, 2, 1]];
|
|
301
|
-
const result = MatrixMultiply(a, b);
|
|
302
|
-
expect(result).toEqual([[30, 24, 18], [84, 69, 54], [138, 114, 90]]);
|
|
303
|
-
});
|
|
304
|
-
it('should multiply two 4x4 matrices', () => {
|
|
305
|
-
const a = [
|
|
306
|
-
[1, 2, 3, 4],
|
|
307
|
-
[5, 6, 7, 8],
|
|
308
|
-
[9, 10, 11, 12],
|
|
309
|
-
[13, 14, 15, 16],
|
|
310
|
-
];
|
|
311
|
-
const b = [
|
|
312
|
-
[16, 15, 14, 13],
|
|
313
|
-
[12, 11, 10, 9],
|
|
314
|
-
[8, 7, 6, 5],
|
|
315
|
-
[4, 3, 2, 1],
|
|
316
|
-
];
|
|
317
|
-
const result = MatrixMultiply(a, b);
|
|
318
|
-
expect(result).toEqual([
|
|
319
|
-
[80, 70, 60, 50],
|
|
320
|
-
[240, 214, 188, 162],
|
|
321
|
-
[400, 358, 316, 274],
|
|
322
|
-
[560, 502, 444, 386],
|
|
323
|
-
]);
|
|
324
|
-
});
|
|
325
|
-
it('should multiply rectangular matrices (2x3 × 3x2)', () => {
|
|
326
|
-
const a = [[1, 2, 3], [4, 5, 6]];
|
|
327
|
-
const b = [[7, 8], [9, 10], [11, 12]];
|
|
328
|
-
const result = MatrixMultiply(a, b);
|
|
329
|
-
expect(result).toEqual([[58, 64], [139, 154]]);
|
|
330
|
-
});
|
|
331
|
-
it('should multiply rectangular matrices (3x2 × 2x4)', () => {
|
|
332
|
-
const a = [[1, 2], [3, 4], [5, 6]];
|
|
333
|
-
const b = [[7, 8, 9, 10], [11, 12, 13, 14]];
|
|
334
|
-
const result = MatrixMultiply(a, b);
|
|
335
|
-
expect(result).toEqual([
|
|
336
|
-
[29, 32, 35, 38],
|
|
337
|
-
[65, 72, 79, 86],
|
|
338
|
-
[101, 112, 123, 134],
|
|
339
|
-
]);
|
|
340
|
-
});
|
|
341
|
-
it('should multiply by identity matrix', () => {
|
|
342
|
-
const a = [[1, 2], [3, 4]];
|
|
343
|
-
const identity = [[1, 0], [0, 1]];
|
|
344
|
-
const result = MatrixMultiply(a, identity);
|
|
345
|
-
expect(result).toEqual([[1, 2], [3, 4]]);
|
|
346
|
-
});
|
|
347
|
-
it('should multiply identity by matrix', () => {
|
|
348
|
-
const identity = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
|
349
|
-
const a = [[2, 3, 4], [5, 6, 7], [8, 9, 10]];
|
|
350
|
-
const result = MatrixMultiply(identity, a);
|
|
351
|
-
expect(result).toEqual([[2, 3, 4], [5, 6, 7], [8, 9, 10]]);
|
|
352
|
-
});
|
|
353
|
-
it('should handle matrices with zeros', () => {
|
|
354
|
-
const a = [[1, 2], [3, 4]];
|
|
355
|
-
const b = [[0, 0], [0, 0]];
|
|
356
|
-
const result = MatrixMultiply(a, b);
|
|
357
|
-
expect(result).toEqual([[0, 0], [0, 0]]);
|
|
358
|
-
});
|
|
359
|
-
it('should handle matrices with negative values', () => {
|
|
360
|
-
const a = [[1, -2], [-3, 4]];
|
|
361
|
-
const b = [[-1, 2], [3, -4]];
|
|
362
|
-
const result = MatrixMultiply(a, b);
|
|
363
|
-
expect(result).toEqual([[-7, 10], [15, -22]]);
|
|
364
|
-
});
|
|
365
|
-
it('should handle matrices with decimal values', () => {
|
|
366
|
-
const a = [[1.5, 2.5], [3.5, 4.5]];
|
|
367
|
-
const b = [[0.5, 1.5], [2.5, 3.5]];
|
|
368
|
-
const result = MatrixMultiply(a, b);
|
|
369
|
-
expect(result).toEqual([[7, 11], [13, 21]]);
|
|
370
|
-
});
|
|
371
|
-
it('should verify non-commutativity (A×B ≠ B×A)', () => {
|
|
372
|
-
const a = [[1, 2], [3, 4]];
|
|
373
|
-
const b = [[5, 6], [7, 8]];
|
|
374
|
-
const ab = MatrixMultiply(a, b);
|
|
375
|
-
const ba = MatrixMultiply(b, a);
|
|
376
|
-
expect(ab).toEqual([[19, 22], [43, 50]]);
|
|
377
|
-
expect(ba).toEqual([[23, 34], [31, 46]]);
|
|
378
|
-
expect(ab).not.toEqual(ba);
|
|
379
|
-
});
|
|
380
|
-
it('should verify associativity ((A×B)×C = A×(B×C))', () => {
|
|
381
|
-
const a = [[1, 2]];
|
|
382
|
-
const b = [[3], [4]];
|
|
383
|
-
const c = [[5, 6]];
|
|
384
|
-
const abC = MatrixMultiply(MatrixMultiply(a, b), c);
|
|
385
|
-
const aBc = MatrixMultiply(a, MatrixMultiply(b, c));
|
|
386
|
-
expect(abC).toEqual(aBc);
|
|
387
|
-
});
|
|
388
|
-
it('should return proper matrix type', () => {
|
|
389
|
-
const a = [[1, 2], [3, 4]];
|
|
390
|
-
const b = [[5, 6], [7, 8]];
|
|
391
|
-
const result = MatrixMultiply(a, b);
|
|
392
|
-
expect(Array.isArray(result)).toBe(true);
|
|
393
|
-
expect(Array.isArray(result[0])).toBe(true);
|
|
394
|
-
expect(result.length).toBe(2);
|
|
395
|
-
const [firstRow] = result;
|
|
396
|
-
if (firstRow) {
|
|
397
|
-
expect(firstRow.length).toBe(2);
|
|
398
|
-
}
|
|
399
|
-
});
|
|
400
|
-
it('should throw error for incompatible dimensions', () => {
|
|
401
|
-
const a = [[1, 2], [3, 4]]; // 2x2
|
|
402
|
-
const b = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; // 3x3
|
|
403
|
-
expect(() => MatrixMultiply(a, b)).toThrow();
|
|
404
|
-
});
|
|
405
|
-
it('should throw error for dimension mismatch in rectangular matrices', () => {
|
|
406
|
-
const a = [[1, 2, 3], [4, 5, 6]]; // 2x3
|
|
407
|
-
const b = [[1, 2], [3, 4]]; // 2x2 (need 3x2)
|
|
408
|
-
expect(() => MatrixMultiply(a, b)).toThrow();
|
|
409
|
-
});
|
|
410
|
-
});
|
|
411
|
-
describe('overload type safety and dispatch', () => {
|
|
412
|
-
it('should correctly dispatch to scalar multiplication', () => {
|
|
413
|
-
const matrix = [[1, 2], [3, 4]];
|
|
414
|
-
const scalar = 5;
|
|
415
|
-
// Type should be inferred as IMatrix
|
|
416
|
-
const result = MatrixMultiply(matrix, scalar);
|
|
417
|
-
expect(result).toEqual([[5, 10], [15, 20]]);
|
|
418
|
-
expect(Array.isArray(result)).toBe(true);
|
|
419
|
-
expect(Array.isArray(result[0])).toBe(true);
|
|
420
|
-
});
|
|
421
|
-
it('should correctly dispatch to vector multiplication', () => {
|
|
422
|
-
const matrix = [[1, 2], [3, 4]];
|
|
423
|
-
const vector = [2, 3];
|
|
424
|
-
// Type should be inferred as TVector (1D array)
|
|
425
|
-
const result = MatrixMultiply(matrix, vector);
|
|
426
|
-
expect(result).toEqual([8, 18]);
|
|
427
|
-
expect(Array.isArray(result)).toBe(true);
|
|
428
|
-
expect(typeof result[0]).toBe('number');
|
|
429
|
-
});
|
|
430
|
-
it('should correctly dispatch to matrix multiplication', () => {
|
|
431
|
-
const matrixA = [[1, 2], [3, 4]];
|
|
432
|
-
const matrixB = [[2, 0], [1, 2]];
|
|
433
|
-
// Type should be inferred as IMatrix
|
|
434
|
-
const result = MatrixMultiply(matrixA, matrixB);
|
|
435
|
-
expect(result).toEqual([[4, 4], [10, 8]]);
|
|
436
|
-
expect(Array.isArray(result)).toBe(true);
|
|
437
|
-
expect(Array.isArray(result[0])).toBe(true);
|
|
438
|
-
expect(result[0].length).toBe(2); // Square matrix
|
|
439
|
-
});
|
|
440
|
-
it('should handle mixed operand types correctly', () => {
|
|
441
|
-
const matrix = [[2, 1], [1, 2]];
|
|
442
|
-
// Scalar multiplication
|
|
443
|
-
const scalarResult = MatrixMultiply(matrix, 3);
|
|
444
|
-
expect(scalarResult).toEqual([[6, 3], [3, 6]]);
|
|
445
|
-
// Vector multiplication
|
|
446
|
-
const vectorResult = MatrixMultiply(matrix, [1, 2]);
|
|
447
|
-
expect(vectorResult).toEqual([4, 5]);
|
|
448
|
-
// Matrix multiplication
|
|
449
|
-
const matrixResult = MatrixMultiply(matrix, [[1, 0], [0, 1]]);
|
|
450
|
-
expect(matrixResult).toEqual([[2, 1], [1, 2]]);
|
|
451
|
-
});
|
|
452
|
-
it('should preserve specific matrix types in results', () => {
|
|
453
|
-
const matrix1 = [[5]];
|
|
454
|
-
const matrix2 = [[1, 2], [3, 4]];
|
|
455
|
-
const matrix3 = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
|
456
|
-
// All should return IMatrix type (base type)
|
|
457
|
-
const result1 = MatrixMultiply(matrix1, 2);
|
|
458
|
-
const result2 = MatrixMultiply(matrix2, 0.5);
|
|
459
|
-
const result3 = MatrixMultiply(matrix3, 3);
|
|
460
|
-
expect(result1).toEqual([[10]]);
|
|
461
|
-
expect(result2).toEqual([[0.5, 1], [1.5, 2]]);
|
|
462
|
-
expect(result3).toEqual([[3, 0, 0], [0, 3, 0], [0, 0, 3]]);
|
|
463
|
-
});
|
|
464
|
-
it('should handle edge cases for each overload', () => {
|
|
465
|
-
const matrix = [[1, 0], [0, 1]];
|
|
466
|
-
// Scalar: multiply by 0
|
|
467
|
-
const zeroScalar = MatrixMultiply(matrix, 0);
|
|
468
|
-
expect(zeroScalar).toEqual([[0, 0], [0, 0]]);
|
|
469
|
-
// Vector: zero vector
|
|
470
|
-
const zeroVector = MatrixMultiply(matrix, [0, 0]);
|
|
471
|
-
expect(zeroVector).toEqual([0, 0]);
|
|
472
|
-
// Matrix: zero matrix
|
|
473
|
-
const zeroMatrix = MatrixMultiply(matrix, [[0, 0], [0, 0]]);
|
|
474
|
-
expect(zeroMatrix).toEqual([[0, 0], [0, 0]]);
|
|
475
|
-
});
|
|
476
|
-
it('should validate input types correctly', () => {
|
|
477
|
-
const matrix = [[1, 2], [3, 4]];
|
|
478
|
-
// Test type detection with edge values
|
|
479
|
-
expect(MatrixMultiply(matrix, 1)).toEqual([[1, 2], [3, 4]]);
|
|
480
|
-
expect(MatrixMultiply(matrix, -1)).toEqual([[-1, -2], [-3, -4]]);
|
|
481
|
-
expect(MatrixMultiply(matrix, 0.5)).toEqual([[0.5, 1], [1.5, 2]]);
|
|
482
|
-
});
|
|
483
|
-
it('should handle type coercion edge cases', () => {
|
|
484
|
-
const matrix = [[2, 3]];
|
|
485
|
-
// Ensure vector is detected correctly vs matrix
|
|
486
|
-
const vectorResult = MatrixMultiply(matrix, [4, 5]);
|
|
487
|
-
expect(vectorResult).toEqual([23]);
|
|
488
|
-
// Ensure 2D matrix is detected correctly
|
|
489
|
-
const matrixResult = MatrixMultiply(matrix, [[4], [5]]);
|
|
490
|
-
expect(matrixResult).toEqual([[23]]);
|
|
491
|
-
});
|
|
492
|
-
it('should maintain precision in type-specific operations', () => {
|
|
493
|
-
const matrix2 = [[1.1, 2.2], [3.3, 4.4]];
|
|
494
|
-
const vector2 = [0.5, 0.25];
|
|
495
|
-
const result = MatrixMultiply(matrix2, vector2);
|
|
496
|
-
expect(result[0]).toBeCloseTo((1.1 * 0.5) + (2.2 * 0.25), 10);
|
|
497
|
-
expect(result[1]).toBeCloseTo((3.3 * 0.5) + (4.4 * 0.25), 10);
|
|
498
|
-
});
|
|
499
|
-
});
|
|
500
|
-
describe.skip('large matrix multiplication (Strassen)', () => {
|
|
501
|
-
it('should handle large square matrices using Strassen algorithm', () => {
|
|
502
|
-
// Create 32x32 matrices to trigger Strassen algorithm
|
|
503
|
-
const size = 32;
|
|
504
|
-
const a = MatrixCreate(size, size);
|
|
505
|
-
const b = MatrixCreate(size, size);
|
|
506
|
-
// Fill with simple pattern for testing
|
|
507
|
-
for (let i = 0; i < size; i++) {
|
|
508
|
-
const arow = a[i];
|
|
509
|
-
AssertMatrixRow(arow, { rowIndex: i });
|
|
510
|
-
const brow = b[i];
|
|
511
|
-
AssertMatrixRow(brow, { rowIndex: i });
|
|
512
|
-
for (let j = 0; j < size; j++) {
|
|
513
|
-
arow[j] = i + j;
|
|
514
|
-
brow[j] = i - j;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
// This should use Strassen algorithm internally
|
|
518
|
-
const result = MatrixMultiply(a, b);
|
|
519
|
-
const [resultRow] = result;
|
|
520
|
-
AssertMatrixRow(resultRow, { rowIndex: 0 });
|
|
521
|
-
expect(result).toBeDefined();
|
|
522
|
-
expect(result.length).toBe(size);
|
|
523
|
-
expect(resultRow.length).toBe(size);
|
|
524
|
-
});
|
|
525
|
-
it('should use standard algorithm for matrices smaller than 32x32', () => {
|
|
526
|
-
// Create 31x31 matrices - should use standard algorithm, not Strassen
|
|
527
|
-
const size = 31;
|
|
528
|
-
const a = MatrixCreate(size, size);
|
|
529
|
-
const b = MatrixCreate(size, size);
|
|
530
|
-
// Fill with simple pattern for testing
|
|
531
|
-
for (let i = 0; i < size; i++) {
|
|
532
|
-
const arow = a[i];
|
|
533
|
-
AssertMatrixRow(arow, { rowIndex: i });
|
|
534
|
-
const brow = b[i];
|
|
535
|
-
AssertMatrixRow(brow, { rowIndex: i });
|
|
536
|
-
for (let j = 0; j < size; j++) {
|
|
537
|
-
arow[j] = i + j;
|
|
538
|
-
brow[j] = i - j;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
// This should use standard algorithm internally
|
|
542
|
-
const result = MatrixMultiply(a, b);
|
|
543
|
-
const [resultRow] = result;
|
|
544
|
-
AssertMatrixRow(resultRow, { rowIndex: 0 });
|
|
545
|
-
expect(result).toBeDefined();
|
|
546
|
-
expect(result.length).toBe(size);
|
|
547
|
-
expect(resultRow.length).toBe(size);
|
|
548
|
-
});
|
|
549
|
-
it('should handle boundary case at 32x32 threshold', () => {
|
|
550
|
-
// Test exactly at the Strassen threshold
|
|
551
|
-
const size = 32;
|
|
552
|
-
const identity = MatrixCreate(size, size);
|
|
553
|
-
const testMatrix = MatrixCreate(size, size);
|
|
554
|
-
// Create identity matrix
|
|
555
|
-
for (let i = 0; i < size; i++) {
|
|
556
|
-
const identityRow = identity[i];
|
|
557
|
-
AssertMatrixRow(identityRow, { rowIndex: i });
|
|
558
|
-
const testRow = testMatrix[i];
|
|
559
|
-
AssertMatrixRow(testRow, { rowIndex: i });
|
|
560
|
-
for (let j = 0; j < size; j++) {
|
|
561
|
-
identityRow[j] = i === j ? 1 : 0;
|
|
562
|
-
testRow[j] = (i * size) + j; // Sequential values for testing
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
// Identity multiplication should preserve the matrix
|
|
566
|
-
const result = MatrixMultiply(identity, testMatrix);
|
|
567
|
-
expect(result).toEqual(testMatrix);
|
|
568
|
-
});
|
|
569
|
-
it('should handle very large matrices (64x64) with Strassen', () => {
|
|
570
|
-
const size = 64;
|
|
571
|
-
const a = MatrixCreate(64);
|
|
572
|
-
const b = MatrixCreate(64);
|
|
573
|
-
// Fill with identity pattern for predictable results
|
|
574
|
-
for (let i = 0; i < size; i++) {
|
|
575
|
-
const arow = a[i];
|
|
576
|
-
AssertMatrixRow(arow, { rowIndex: i });
|
|
577
|
-
const brow = b[i];
|
|
578
|
-
AssertMatrixRow(brow, { rowIndex: i });
|
|
579
|
-
for (let j = 0; j < size; j++) {
|
|
580
|
-
arow[j] = i === j ? 1 : 0; // Identity matrix
|
|
581
|
-
brow[j] = j; // Simple pattern
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
const result = MatrixMultiply(a, b);
|
|
585
|
-
const [firstRow, secondRow] = result;
|
|
586
|
-
AssertMatrixRow(firstRow, { rowIndex: 0 });
|
|
587
|
-
AssertMatrixRow(secondRow, { rowIndex: 1 });
|
|
588
|
-
// Verify identity multiplication worked
|
|
589
|
-
expect(firstRow[0]).toBe(0);
|
|
590
|
-
expect(secondRow[1]).toBe(1);
|
|
591
|
-
expect(result[size - 1]?.[size - 1]).toBe(size - 1);
|
|
592
|
-
});
|
|
593
|
-
});
|
|
594
|
-
describe('edge cases and error handling', () => {
|
|
595
|
-
it('should throw descriptive errors for dimension mismatches', () => {
|
|
596
|
-
const matrix2x3 = [[1, 2, 3], [4, 5, 6]];
|
|
597
|
-
const matrix2x2 = [[1, 2], [3, 4]];
|
|
598
|
-
const vector3 = [1, 2, 3];
|
|
599
|
-
// Matrix-matrix dimension mismatch
|
|
600
|
-
expect(() => MatrixMultiply(matrix2x3, matrix2x2))
|
|
601
|
-
.toThrow(/Matrix row must be an array|incompatible.+multiplication/i);
|
|
602
|
-
// Matrix-vector dimension mismatch
|
|
603
|
-
expect(() => MatrixMultiply(matrix2x2, vector3))
|
|
604
|
-
.toThrow(/Matrix-vector multiplication requires matrix columns/);
|
|
605
|
-
// Empty vector
|
|
606
|
-
expect(() => MatrixMultiply(matrix2x2, []))
|
|
607
|
-
.toThrow(/Matrix-vector multiplication requires matrix columns/);
|
|
608
|
-
});
|
|
609
|
-
it('should handle matrices with extreme values', () => {
|
|
610
|
-
const matrix = [[Number.MAX_SAFE_INTEGER, 0], [0, Number.MIN_SAFE_INTEGER]];
|
|
611
|
-
const scalar = 0.5;
|
|
612
|
-
const result = MatrixMultiply(matrix, scalar);
|
|
613
|
-
expect(result[0]).toBeDefined();
|
|
614
|
-
expect(result[1]).toBeDefined();
|
|
615
|
-
expect(result[0]?.[0]).toBe(Number.MAX_SAFE_INTEGER * 0.5);
|
|
616
|
-
expect(result[1]?.[1]).toBe(Number.MIN_SAFE_INTEGER * 0.5);
|
|
617
|
-
});
|
|
618
|
-
it('should handle very small decimal numbers', () => {
|
|
619
|
-
const matrix = [[1e-10, 2e-10], [3e-10, 4e-10]];
|
|
620
|
-
const scalar = 1e10;
|
|
621
|
-
const result = MatrixMultiply(matrix, scalar);
|
|
622
|
-
expect(result[0]?.[0]).toBeCloseTo(1, 10);
|
|
623
|
-
expect(result[0]?.[1]).toBeCloseTo(2, 10);
|
|
624
|
-
expect(result[1]?.[0]).toBeCloseTo(3, 10);
|
|
625
|
-
expect(result[1]?.[1]).toBeCloseTo(4, 10);
|
|
626
|
-
});
|
|
627
|
-
it('should preserve exact zero values', () => {
|
|
628
|
-
const matrix = [[0, 1], [1, 0]];
|
|
629
|
-
const vector = [5, 0];
|
|
630
|
-
const result = MatrixMultiply(matrix, vector);
|
|
631
|
-
expect(result[0]).toBe(0);
|
|
632
|
-
expect(result[1]).toBe(5);
|
|
633
|
-
});
|
|
634
|
-
it('should handle NaN and Infinity gracefully', () => {
|
|
635
|
-
const matrix = [[1, 2], [3, 4]];
|
|
636
|
-
// NaN scalar should throw validation error
|
|
637
|
-
expect(() => MatrixMultiply(matrix, NaN))
|
|
638
|
-
.toThrow(/Scalar multiplier must be a valid number/);
|
|
639
|
-
// Infinity scalar should throw validation error
|
|
640
|
-
expect(() => MatrixMultiply(matrix, Infinity))
|
|
641
|
-
.toThrow(/Scalar multiplier must be a valid number/);
|
|
642
|
-
});
|
|
643
|
-
it('should handle matrices with mixed positive/negative values', () => {
|
|
644
|
-
const matrix = [[-1, 2, -3], [4, -5, 6]];
|
|
645
|
-
const vector = [-1, -1, -1];
|
|
646
|
-
const result = MatrixMultiply(matrix, vector);
|
|
647
|
-
expect(result[0]).toBe((-1 * -1) + (2 * -1) + (-3 * -1)); // 1 - 2 + 3 = 2
|
|
648
|
-
expect(result[1]).toBe((4 * -1) + (-5 * -1) + (6 * -1)); // -4 + 5 - 6 = -5
|
|
649
|
-
});
|
|
650
|
-
it('should handle single-element matrices and vectors', () => {
|
|
651
|
-
const matrix1x1 = [[5]];
|
|
652
|
-
const vector1 = [3];
|
|
653
|
-
const result = MatrixMultiply(matrix1x1, vector1);
|
|
654
|
-
expect(result).toEqual([15]);
|
|
655
|
-
});
|
|
656
|
-
it('should handle wide and tall rectangular matrices', () => {
|
|
657
|
-
// Wide matrix (1x5)
|
|
658
|
-
const wideMatrix = [[1, 2, 3, 4, 5]];
|
|
659
|
-
const vector5 = [1, 1, 1, 1, 1];
|
|
660
|
-
const wideResult = MatrixMultiply(wideMatrix, vector5);
|
|
661
|
-
expect(wideResult).toEqual([15]);
|
|
662
|
-
// Tall matrix (5x1)
|
|
663
|
-
const tallMatrix = [[1], [2], [3], [4], [5]];
|
|
664
|
-
const vector1 = [2];
|
|
665
|
-
const tallResult = MatrixMultiply(tallMatrix, vector1);
|
|
666
|
-
expect(tallResult).toEqual([2, 4, 6, 8, 10]);
|
|
667
|
-
});
|
|
668
|
-
});
|
|
669
|
-
describe.skip('performance and optimization tests', () => {
|
|
670
|
-
it('should handle optimized small matrix sizes efficiently', () => {
|
|
671
|
-
// Test all optimized sizes: 1x1, 2x2, 3x3, 4x4
|
|
672
|
-
const matrix1 = [[2]];
|
|
673
|
-
const matrix2 = [[1, 2], [3, 4]];
|
|
674
|
-
const matrix3 = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
|
675
|
-
const matrix4 = [
|
|
676
|
-
[1, 0, 0, 0],
|
|
677
|
-
[0, 1, 0, 0],
|
|
678
|
-
[0, 0, 1, 0],
|
|
679
|
-
[0, 0, 0, 1],
|
|
680
|
-
];
|
|
681
|
-
// Test matrix-matrix multiplication for optimized sizes
|
|
682
|
-
const result1 = MatrixMultiply(matrix1, matrix1);
|
|
683
|
-
const result2 = MatrixMultiply(matrix2, matrix2);
|
|
684
|
-
const result3 = MatrixMultiply(matrix3, matrix3);
|
|
685
|
-
const result4 = MatrixMultiply(matrix4, matrix4);
|
|
686
|
-
expect(result1).toEqual([[4]]);
|
|
687
|
-
expect(result2).toEqual([[7, 10], [15, 22]]);
|
|
688
|
-
expect(result3).toEqual(matrix3); // Identity matrix
|
|
689
|
-
expect(result4).toEqual(matrix4); // Identity matrix
|
|
690
|
-
});
|
|
691
|
-
it('should maintain consistency between algorithms', () => {
|
|
692
|
-
// Create a small matrix that would use standard algorithm
|
|
693
|
-
const size = 8;
|
|
694
|
-
const matrix = MatrixCreate(size, size);
|
|
695
|
-
// Fill with known pattern
|
|
696
|
-
for (let i = 0; i < size; i++) {
|
|
697
|
-
const row = matrix[i];
|
|
698
|
-
AssertMatrixRow(row, { rowIndex: i });
|
|
699
|
-
for (let j = 0; j < size; j++) {
|
|
700
|
-
row[j] = (i + 1) * (j + 1);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
// Multiply by identity - should preserve matrix
|
|
704
|
-
const identity = MatrixCreate(size, size);
|
|
705
|
-
for (let i = 0; i < size; i++) {
|
|
706
|
-
const row = identity[i];
|
|
707
|
-
AssertMatrixRow(row, { rowIndex: i });
|
|
708
|
-
for (let j = 0; j < size; j++) {
|
|
709
|
-
row[j] = i === j ? 1 : 0;
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
const result = MatrixMultiply(matrix, identity);
|
|
713
|
-
expect(result).toEqual(matrix);
|
|
714
|
-
});
|
|
715
|
-
it('should handle repeated operations consistently', () => {
|
|
716
|
-
const matrix = [[1, 2], [3, 4]];
|
|
717
|
-
const vector = [1, 1];
|
|
718
|
-
// Perform same operation multiple times
|
|
719
|
-
const results = Array.from({ length: 5 }, () => MatrixMultiply(matrix, vector));
|
|
720
|
-
// All results should be identical
|
|
721
|
-
results.forEach((result) => {
|
|
722
|
-
expect(result).toEqual([3, 7]);
|
|
723
|
-
});
|
|
724
|
-
});
|
|
725
|
-
it('should handle chained multiplications correctly', () => {
|
|
726
|
-
const a = [[1, 2]];
|
|
727
|
-
const b = [[3], [4]];
|
|
728
|
-
const c = [[5, 6]];
|
|
729
|
-
// Test associativity: (A*B)*C = A*(B*C)
|
|
730
|
-
const leftAssoc = MatrixMultiply(MatrixMultiply(a, b), c);
|
|
731
|
-
const rightAssoc = MatrixMultiply(a, MatrixMultiply(b, c));
|
|
732
|
-
expect(leftAssoc).toEqual(rightAssoc);
|
|
733
|
-
});
|
|
734
|
-
});
|
|
735
|
-
});
|
|
736
|
-
describe('MatrixSubmatrix', () => {
|
|
737
|
-
it('should extract 2x2 submatrix from top-left', () => {
|
|
738
|
-
const matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]];
|
|
739
|
-
const result = MatrixSubmatrix(matrix, 0, 0, 2, 2);
|
|
740
|
-
expect(result).toEqual([[1, 2], [5, 6]]);
|
|
741
|
-
});
|
|
742
|
-
it('should extract 2x2 submatrix from center', () => {
|
|
743
|
-
const matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]];
|
|
744
|
-
const result = MatrixSubmatrix(matrix, 1, 1, 2, 2);
|
|
745
|
-
expect(result).toEqual([[6, 7], [10, 11]]);
|
|
746
|
-
});
|
|
747
|
-
it('should extract single element', () => {
|
|
748
|
-
const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
|
749
|
-
const result = MatrixSubmatrix(matrix, 1, 1, 1, 1);
|
|
750
|
-
expect(result).toEqual([[5]]);
|
|
751
|
-
});
|
|
752
|
-
it('should extract full row', () => {
|
|
753
|
-
const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
|
754
|
-
const result = MatrixSubmatrix(matrix, 0, 1, 3, 1);
|
|
755
|
-
expect(result).toEqual([[4, 5, 6]]);
|
|
756
|
-
});
|
|
757
|
-
it('should extract full column', () => {
|
|
758
|
-
const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
|
759
|
-
const result = MatrixSubmatrix(matrix, 1, 0, 1, 3);
|
|
760
|
-
expect(result).toEqual([[2], [5], [8]]);
|
|
761
|
-
});
|
|
762
|
-
it('should handle edge case at matrix boundaries', () => {
|
|
763
|
-
const matrix = [[1, 2], [3, 4]];
|
|
764
|
-
const result = MatrixSubmatrix(matrix, 1, 1, 1, 1);
|
|
765
|
-
expect(result).toEqual([[4]]);
|
|
766
|
-
});
|
|
767
|
-
});
|
|
768
|
-
describe('MatrixPad', () => {
|
|
769
|
-
it('should pad 2x2 matrix to 4x4', () => {
|
|
770
|
-
const matrix = [[1, 2], [3, 4]];
|
|
771
|
-
const result = MatrixPad(matrix, 4, 4);
|
|
772
|
-
expect(result).toEqual([
|
|
773
|
-
[1, 2, 0, 0],
|
|
774
|
-
[3, 4, 0, 0],
|
|
775
|
-
[0, 0, 0, 0],
|
|
776
|
-
[0, 0, 0, 0],
|
|
777
|
-
]);
|
|
778
|
-
});
|
|
779
|
-
it('should pad matrix asymmetrically', () => {
|
|
780
|
-
const matrix = [[1, 2], [3, 4]];
|
|
781
|
-
const result = MatrixPad(matrix, 3, 4);
|
|
782
|
-
expect(result).toEqual([
|
|
783
|
-
[1, 2, 0, 0],
|
|
784
|
-
[3, 4, 0, 0],
|
|
785
|
-
[0, 0, 0, 0],
|
|
786
|
-
]);
|
|
787
|
-
});
|
|
788
|
-
it('should pad single element matrix', () => {
|
|
789
|
-
const matrix = [[5]];
|
|
790
|
-
const result = MatrixPad(matrix, 3, 3);
|
|
791
|
-
expect(result).toEqual([
|
|
792
|
-
[5, 0, 0],
|
|
793
|
-
[0, 0, 0],
|
|
794
|
-
[0, 0, 0],
|
|
795
|
-
]);
|
|
796
|
-
});
|
|
797
|
-
it('should handle padding with same dimensions', () => {
|
|
798
|
-
const matrix = [[1, 2], [3, 4]];
|
|
799
|
-
const result = MatrixPad(matrix, 2, 2);
|
|
800
|
-
expect(result).toEqual([[1, 2], [3, 4]]);
|
|
801
|
-
});
|
|
802
|
-
it('should pad only rows', () => {
|
|
803
|
-
const matrix = [[1, 2, 3], [4, 5, 6]];
|
|
804
|
-
const result = MatrixPad(matrix, 4, 3);
|
|
805
|
-
expect(result).toEqual([
|
|
806
|
-
[1, 2, 3],
|
|
807
|
-
[4, 5, 6],
|
|
808
|
-
[0, 0, 0],
|
|
809
|
-
[0, 0, 0],
|
|
810
|
-
]);
|
|
811
|
-
});
|
|
812
|
-
it('should pad only columns', () => {
|
|
813
|
-
const matrix = [[1, 2], [3, 4], [5, 6]];
|
|
814
|
-
const result = MatrixPad(matrix, 3, 4);
|
|
815
|
-
expect(result).toEqual([
|
|
816
|
-
[1, 2, 0, 0],
|
|
817
|
-
[3, 4, 0, 0],
|
|
818
|
-
[5, 6, 0, 0],
|
|
819
|
-
]);
|
|
820
|
-
});
|
|
821
|
-
});
|
|
822
|
-
describe('MatrixCombine', () => {
|
|
823
|
-
it('should combine four 2x2 matrices into 4x4', () => {
|
|
824
|
-
const c11 = [[1, 2], [3, 4]];
|
|
825
|
-
const c12 = [[5, 6], [7, 8]];
|
|
826
|
-
const c21 = [[9, 10], [11, 12]];
|
|
827
|
-
const c22 = [[13, 14], [15, 16]];
|
|
828
|
-
const result = MatrixCombine(c11, c12, c21, c22);
|
|
829
|
-
expect(result).toEqual([
|
|
830
|
-
[1, 2, 5, 6],
|
|
831
|
-
[3, 4, 7, 8],
|
|
832
|
-
[9, 10, 13, 14],
|
|
833
|
-
[11, 12, 15, 16],
|
|
834
|
-
]);
|
|
835
|
-
});
|
|
836
|
-
it('should combine four 1x1 matrices into 2x2', () => {
|
|
837
|
-
const c11 = [[1]];
|
|
838
|
-
const c12 = [[2]];
|
|
839
|
-
const c21 = [[3]];
|
|
840
|
-
const c22 = [[4]];
|
|
841
|
-
const result = MatrixCombine(c11, c12, c21, c22);
|
|
842
|
-
expect(result).toEqual([
|
|
843
|
-
[1, 2],
|
|
844
|
-
[3, 4],
|
|
845
|
-
]);
|
|
846
|
-
});
|
|
847
|
-
it('should handle matrices with negative numbers', () => {
|
|
848
|
-
const c11 = [[1, -2], [-3, 4]];
|
|
849
|
-
const c12 = [[-5, 6], [7, -8]];
|
|
850
|
-
const c21 = [[9, -10], [-11, 12]];
|
|
851
|
-
const c22 = [[-13, 14], [15, -16]];
|
|
852
|
-
const result = MatrixCombine(c11, c12, c21, c22);
|
|
853
|
-
expect(result).toEqual([
|
|
854
|
-
[1, -2, -5, 6],
|
|
855
|
-
[-3, 4, 7, -8],
|
|
856
|
-
[9, -10, -13, 14],
|
|
857
|
-
[-11, 12, 15, -16],
|
|
858
|
-
]);
|
|
859
|
-
});
|
|
860
|
-
it('should handle matrices with zeros', () => {
|
|
861
|
-
const c11 = [[0, 0], [0, 0]];
|
|
862
|
-
const c12 = [[1, 2], [3, 4]];
|
|
863
|
-
const c21 = [[5, 6], [7, 8]];
|
|
864
|
-
const c22 = [[0, 0], [0, 0]];
|
|
865
|
-
const result = MatrixCombine(c11, c12, c21, c22);
|
|
866
|
-
expect(result).toEqual([
|
|
867
|
-
[0, 0, 1, 2],
|
|
868
|
-
[0, 0, 3, 4],
|
|
869
|
-
[5, 6, 0, 0],
|
|
870
|
-
[7, 8, 0, 0],
|
|
871
|
-
]);
|
|
872
|
-
});
|
|
873
|
-
});
|
|
874
|
-
describe('integration tests', () => {
|
|
875
|
-
it('should perform complex operations sequence', () => {
|
|
876
|
-
// Create two 2x2 matrices
|
|
877
|
-
const a = [[1, 2], [3, 4]];
|
|
878
|
-
const b = [[5, 6], [7, 8]];
|
|
879
|
-
// Add them
|
|
880
|
-
const sum = MatrixAdd(a, b);
|
|
881
|
-
expect(sum).toEqual([[6, 8], [10, 12]]);
|
|
882
|
-
// Multiply result by scalar
|
|
883
|
-
const scaled = MatrixMultiply(sum, 0.5);
|
|
884
|
-
expect(scaled).toEqual([[3, 4], [5, 6]]);
|
|
885
|
-
// Subtract original matrix from result
|
|
886
|
-
const diff = MatrixSubtract(scaled, a);
|
|
887
|
-
expect(diff).toEqual([[2, 2], [2, 2]]);
|
|
888
|
-
});
|
|
889
|
-
it('should work with submatrix operations in Strassen context', () => {
|
|
890
|
-
const matrix = [
|
|
891
|
-
[1, 2, 3, 4],
|
|
892
|
-
[5, 6, 7, 8],
|
|
893
|
-
[9, 10, 11, 12],
|
|
894
|
-
[13, 14, 15, 16],
|
|
895
|
-
];
|
|
896
|
-
// Extract quadrants
|
|
897
|
-
const c11 = MatrixSubmatrix(matrix, 0, 0, 2, 2);
|
|
898
|
-
const c12 = MatrixSubmatrix(matrix, 2, 0, 2, 2);
|
|
899
|
-
const c21 = MatrixSubmatrix(matrix, 0, 2, 2, 2);
|
|
900
|
-
const c22 = MatrixSubmatrix(matrix, 2, 2, 2, 2);
|
|
901
|
-
// Recombine
|
|
902
|
-
const reconstructed = MatrixCombine(c11, c12, c21, c22);
|
|
903
|
-
expect(reconstructed).toEqual(matrix);
|
|
904
|
-
});
|
|
905
|
-
it('should handle padding and submatrix extraction round trip', () => {
|
|
906
|
-
const original = [[1, 2], [3, 4]];
|
|
907
|
-
// Pad to larger size
|
|
908
|
-
const padded = MatrixPad(original, 4, 4);
|
|
909
|
-
// Extract original size back
|
|
910
|
-
const extracted = MatrixSubmatrix(padded, 0, 0, 2, 2);
|
|
911
|
-
expect(extracted).toEqual(original);
|
|
912
|
-
});
|
|
913
|
-
});
|
|
914
|
-
});
|
|
915
|
-
//# sourceMappingURL=arithmetic.spec.js.map
|