@pawells/math-extended 1.1.1 → 3.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 +15 -21
- package/build/angles.d.ts +28 -18
- package/build/angles.d.ts.map +1 -1
- package/build/angles.js +28 -18
- package/build/angles.js.map +1 -1
- package/build/clamp.d.ts +2 -0
- package/build/clamp.d.ts.map +1 -1
- package/build/clamp.js +2 -0
- package/build/clamp.js.map +1 -1
- package/build/core.d.ts +23 -0
- package/build/core.d.ts.map +1 -0
- package/build/core.js +25 -0
- package/build/core.js.map +1 -0
- package/build/index.d.ts +1 -4
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -6
- package/build/index.js.map +1 -1
- package/build/interpolation.d.ts +62 -13
- package/build/interpolation.d.ts.map +1 -1
- package/build/interpolation.js +66 -23
- package/build/interpolation.js.map +1 -1
- package/build/matrices/arithmetic.d.ts +65 -76
- package/build/matrices/arithmetic.d.ts.map +1 -1
- package/build/matrices/arithmetic.js +65 -107
- package/build/matrices/arithmetic.js.map +1 -1
- package/build/matrices/asserts.d.ts +26 -273
- package/build/matrices/asserts.d.ts.map +1 -1
- package/build/matrices/asserts.js +106 -350
- package/build/matrices/asserts.js.map +1 -1
- package/build/matrices/core.d.ts +150 -79
- package/build/matrices/core.d.ts.map +1 -1
- package/build/matrices/core.js +128 -104
- package/build/matrices/core.js.map +1 -1
- package/build/matrices/decompositions.d.ts +41 -44
- package/build/matrices/decompositions.d.ts.map +1 -1
- package/build/matrices/decompositions.js +51 -94
- package/build/matrices/decompositions.js.map +1 -1
- package/build/matrices/index.d.ts +2 -2
- package/build/matrices/index.d.ts.map +1 -1
- package/build/matrices/index.js +2 -2
- package/build/matrices/index.js.map +1 -1
- package/build/matrices/linear-algebra.d.ts +56 -19
- package/build/matrices/linear-algebra.d.ts.map +1 -1
- package/build/matrices/linear-algebra.js +80 -36
- package/build/matrices/linear-algebra.js.map +1 -1
- package/build/matrices/normalization.d.ts +36 -15
- package/build/matrices/normalization.d.ts.map +1 -1
- package/build/matrices/normalization.js +32 -23
- package/build/matrices/normalization.js.map +1 -1
- package/build/matrices/transformations.d.ts +39 -52
- package/build/matrices/transformations.d.ts.map +1 -1
- package/build/matrices/transformations.js +8 -11
- package/build/matrices/transformations.js.map +1 -1
- package/build/matrices/types.d.ts +39 -67
- package/build/matrices/types.d.ts.map +1 -1
- package/build/matrices/types.js +63 -1
- package/build/matrices/types.js.map +1 -1
- package/build/quaternions/asserts.d.ts +114 -15
- package/build/quaternions/asserts.d.ts.map +1 -1
- package/build/quaternions/asserts.js +189 -51
- package/build/quaternions/asserts.js.map +1 -1
- package/build/quaternions/conversions.d.ts +18 -8
- package/build/quaternions/conversions.d.ts.map +1 -1
- package/build/quaternions/conversions.js +14 -4
- package/build/quaternions/conversions.js.map +1 -1
- package/build/quaternions/core.d.ts +31 -2
- package/build/quaternions/core.d.ts.map +1 -1
- package/build/quaternions/core.js +32 -4
- package/build/quaternions/core.js.map +1 -1
- package/build/quaternions/index.d.ts +2 -2
- package/build/quaternions/index.d.ts.map +1 -1
- package/build/quaternions/index.js +3 -2
- package/build/quaternions/index.js.map +1 -1
- package/build/quaternions/interpolation.d.ts +7 -1
- package/build/quaternions/interpolation.d.ts.map +1 -1
- package/build/quaternions/interpolation.js +12 -6
- package/build/quaternions/interpolation.js.map +1 -1
- package/build/quaternions/predefined.d.ts +7 -1
- package/build/quaternions/predefined.d.ts.map +1 -1
- package/build/quaternions/predefined.js +6 -0
- package/build/quaternions/predefined.js.map +1 -1
- package/build/quaternions/types.d.ts +24 -13
- package/build/quaternions/types.d.ts.map +1 -1
- package/build/quaternions/types.js +51 -1
- package/build/quaternions/types.js.map +1 -1
- package/build/random.d.ts +66 -20
- package/build/random.d.ts.map +1 -1
- package/build/random.js +73 -20
- package/build/random.js.map +1 -1
- package/build/vectors/asserts.d.ts +33 -99
- package/build/vectors/asserts.d.ts.map +1 -1
- package/build/vectors/asserts.js +145 -181
- package/build/vectors/asserts.js.map +1 -1
- package/build/vectors/core.d.ts +76 -44
- package/build/vectors/core.d.ts.map +1 -1
- package/build/vectors/core.js +128 -119
- package/build/vectors/core.js.map +1 -1
- package/build/vectors/index.d.ts.map +1 -1
- package/build/vectors/index.js +1 -0
- package/build/vectors/index.js.map +1 -1
- package/build/vectors/interpolation.d.ts +13 -1
- package/build/vectors/interpolation.d.ts.map +1 -1
- package/build/vectors/interpolation.js +48 -47
- package/build/vectors/interpolation.js.map +1 -1
- package/build/vectors/predefined.d.ts +73 -25
- package/build/vectors/predefined.d.ts.map +1 -1
- package/build/vectors/predefined.js +62 -18
- package/build/vectors/predefined.js.map +1 -1
- package/build/vectors/types.d.ts +26 -4
- package/build/vectors/types.d.ts.map +1 -1
- package/build/vectors/types.js +50 -1
- package/build/vectors/types.js.map +1 -1
- package/package.json +4 -3
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { AssertNumber } from '@pawells/typescript-common';
|
|
2
|
-
import {
|
|
3
|
-
import { MatrixCreate,
|
|
4
|
-
import {
|
|
5
|
-
import { AssertVector } from '../vectors/asserts.js';
|
|
2
|
+
import { AssertMatricesCompatible, AssertMatrix, AssertMatrix1, AssertMatrix2, AssertMatrix3, AssertMatrix4, AssertMatrixSquare, MatrixError } from './asserts.js';
|
|
3
|
+
import { MatrixCreate, MatrixSize } from './core.js';
|
|
4
|
+
import { ValidateVector, AssertVector } from '../vectors/asserts.js';
|
|
6
5
|
/**
|
|
7
6
|
* Performs element-wise addition of two matrices.
|
|
8
7
|
*
|
|
@@ -22,7 +21,7 @@ import { AssertVector } from '../vectors/asserts.js';
|
|
|
22
21
|
* **Time Complexity:** O(m×n) where m and n are the matrix dimensions
|
|
23
22
|
* **Space Complexity:** O(m×n) for the result matrix
|
|
24
23
|
*
|
|
25
|
-
* @template T - The matrix type extending
|
|
24
|
+
* @template T - The matrix type extending TMatrix interface
|
|
26
25
|
* @param a - First matrix (addend) - must have same dimensions as b
|
|
27
26
|
* @param b - Second matrix (addend) - must have same dimensions as a
|
|
28
27
|
* @returns {TMatrixResult<T>} A new matrix where each element is the sum of corresponding elements
|
|
@@ -30,41 +29,39 @@ import { AssertVector } from '../vectors/asserts.js';
|
|
|
30
29
|
*
|
|
31
30
|
* @example
|
|
32
31
|
* ```typescript
|
|
32
|
+
* ```typescript
|
|
33
33
|
* // Adding 2×2 matrices
|
|
34
34
|
* MatrixAdd([[1, 2], [3, 4]], [[5, 6], [7, 8]]) // Returns [[6, 8], [10, 12]]
|
|
35
|
-
*
|
|
36
35
|
* // Adding 1×3 row vectors
|
|
37
36
|
* MatrixAdd([[1, 2, 3]], [[4, 5, 6]]) // Returns [[5, 7, 9]]
|
|
38
|
-
*
|
|
39
37
|
* // Type-safe matrix addition with specific matrix types
|
|
40
|
-
* const matrixA:
|
|
41
|
-
* const matrixB:
|
|
42
|
-
* const result:
|
|
38
|
+
* const matrixA: TMatrix2 = [[1, 2], [3, 4]];
|
|
39
|
+
* const matrixB: TMatrix2 = [[5, 6], [7, 8]];
|
|
40
|
+
* const result: TMatrix2 = MatrixAdd(matrixA, matrixB);
|
|
41
|
+
* ```
|
|
43
42
|
* ```
|
|
44
43
|
*/
|
|
45
44
|
export function MatrixAdd(a, b) {
|
|
46
45
|
// Validate matrices have compatible dimensions for addition
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
AssertMatrix(a);
|
|
47
|
+
AssertMatrix(b);
|
|
48
|
+
AssertMatricesCompatible(a, b);
|
|
49
|
+
// Ensure matrices have the same dimensions
|
|
49
50
|
const [arows, acols] = MatrixSize(a);
|
|
51
|
+
// Initialize result matrix with same dimensions as inputs
|
|
50
52
|
const result = MatrixCreate(arows, acols);
|
|
51
53
|
// Perform element-wise addition: C[i,j] = A[i,j] + B[i,j]
|
|
52
54
|
for (let row = 0; row < arows; row++) {
|
|
53
55
|
// Get row references for both input matrices
|
|
54
56
|
const aRow = a[row];
|
|
55
|
-
AssertMatrixRow(aRow);
|
|
56
57
|
const bRow = b[row];
|
|
57
|
-
AssertMatrixRow(bRow);
|
|
58
58
|
// Get reference to result row for efficient access
|
|
59
59
|
const resultRow = result[row];
|
|
60
|
-
AssertMatrixRow(resultRow);
|
|
61
60
|
// Add corresponding elements column by column
|
|
62
61
|
for (let col = 0; col < acols; col++) {
|
|
63
62
|
// Validate and extract values from both matrices
|
|
64
63
|
const aVal = aRow[col];
|
|
65
|
-
AssertMatrixValue(aVal, { rowIndex: row, columnIndex: col });
|
|
66
64
|
const bVal = bRow[col];
|
|
67
|
-
AssertMatrixValue(bVal, { rowIndex: row, columnIndex: col });
|
|
68
65
|
// Store sum in result matrix
|
|
69
66
|
resultRow[col] = aVal + bVal;
|
|
70
67
|
}
|
|
@@ -90,7 +87,7 @@ export function MatrixAdd(a, b) {
|
|
|
90
87
|
* **Time Complexity:** O(m×n) where m and n are the matrix dimensions
|
|
91
88
|
* **Space Complexity:** O(m×n) for the result matrix
|
|
92
89
|
*
|
|
93
|
-
* @template T - The matrix type extending
|
|
90
|
+
* @template T - The matrix type extending TMatrix interface
|
|
94
91
|
* @param a - First matrix (minuend) - the matrix being subtracted from
|
|
95
92
|
* @param b - Second matrix (subtrahend) - the matrix being subtracted
|
|
96
93
|
* @returns {TMatrixResult<T>} A new matrix where each element is the difference of corresponding elements
|
|
@@ -98,20 +95,22 @@ export function MatrixAdd(a, b) {
|
|
|
98
95
|
*
|
|
99
96
|
* @example
|
|
100
97
|
* ```typescript
|
|
98
|
+
* ```typescript
|
|
101
99
|
* // Subtracting 2×2 matrices
|
|
102
100
|
* MatrixSubtract([[10, 8], [6, 4]], [[3, 2], [1, 1]]) // Returns [[7, 6], [5, 3]]
|
|
103
|
-
*
|
|
104
101
|
* // Order matters: A - B ≠ B - A
|
|
105
102
|
* MatrixSubtract([[1, 2]], [[3, 4]]) // Returns [[-2, -2]]
|
|
106
103
|
* MatrixSubtract([[3, 4]], [[1, 2]]) // Returns [[2, 2]]
|
|
107
|
-
*
|
|
108
104
|
* // Self-subtraction produces zero matrix
|
|
109
105
|
* MatrixSubtract([[5, 6]], [[5, 6]]) // Returns [[0, 0]]
|
|
110
106
|
* ```
|
|
107
|
+
* ```
|
|
111
108
|
*/
|
|
112
109
|
export function MatrixSubtract(a, b) {
|
|
113
110
|
// Validate matrices have compatible dimensions for subtraction
|
|
114
|
-
|
|
111
|
+
AssertMatrix(a);
|
|
112
|
+
AssertMatrix(b);
|
|
113
|
+
AssertMatricesCompatible(a, b);
|
|
115
114
|
// Initialize result matrix with same dimensions as inputs
|
|
116
115
|
const [arows, acols] = MatrixSize(a);
|
|
117
116
|
const result = MatrixCreate(arows, acols);
|
|
@@ -119,18 +118,13 @@ export function MatrixSubtract(a, b) {
|
|
|
119
118
|
for (let row = 0; row < arows; row++) {
|
|
120
119
|
// Get row references for both input matrices
|
|
121
120
|
const aRow = a[row];
|
|
122
|
-
AssertMatrixRow(aRow);
|
|
123
121
|
const bRow = b[row];
|
|
124
|
-
AssertMatrixRow(bRow);
|
|
125
122
|
// Get reference to result row for efficient access
|
|
126
123
|
const resultRow = result[row];
|
|
127
|
-
AssertMatrixRow(resultRow);
|
|
128
124
|
// Subtract corresponding elements column by column
|
|
129
125
|
for (let col = 0; col < acols; col++) {
|
|
130
126
|
const aVal = aRow[col];
|
|
131
|
-
AssertMatrixValue(aVal, { rowIndex: row, columnIndex: col });
|
|
132
127
|
const bVal = bRow[col];
|
|
133
|
-
AssertMatrixValue(bVal, { rowIndex: row, columnIndex: col });
|
|
134
128
|
// Store difference in result matrix
|
|
135
129
|
resultRow[col] = aVal - bVal;
|
|
136
130
|
}
|
|
@@ -142,7 +136,7 @@ export function MatrixMultiply(a, b) {
|
|
|
142
136
|
// Route to appropriate multiplication algorithm based on operand type
|
|
143
137
|
if (typeof b === 'number')
|
|
144
138
|
return matrixMultiplyScalar(a, b);
|
|
145
|
-
if (
|
|
139
|
+
if (ValidateVector(b))
|
|
146
140
|
return matrixMultiplyVector(a, b);
|
|
147
141
|
return matrixMultiplyMatrix(a, b);
|
|
148
142
|
}
|
|
@@ -154,13 +148,10 @@ function matrixMultiplyScalar(matrix, scalar) {
|
|
|
154
148
|
// Apply scalar multiplication to each matrix element
|
|
155
149
|
for (let row = 0; row < rows; row++) {
|
|
156
150
|
const matrixRow = matrix[row];
|
|
157
|
-
AssertMatrixRow(matrixRow);
|
|
158
151
|
const resultRow = result[row];
|
|
159
|
-
AssertMatrixRow(resultRow);
|
|
160
152
|
// Multiply each element in the row by the scalar
|
|
161
153
|
for (let col = 0; col < cols; col++) {
|
|
162
154
|
const val = matrixRow[col];
|
|
163
|
-
AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
|
|
164
155
|
resultRow[col] = val * scalar;
|
|
165
156
|
}
|
|
166
157
|
}
|
|
@@ -173,25 +164,21 @@ function matrixMultiplyVector(matrix, vector) {
|
|
|
173
164
|
// Get matrix dimensions
|
|
174
165
|
const [matrixRows, matrixCols] = MatrixSize(matrix);
|
|
175
166
|
// Verify dimensional compatibility: matrix columns must equal vector length
|
|
176
|
-
if (matrixCols !== vector.length)
|
|
167
|
+
if (matrixCols !== vector.length)
|
|
177
168
|
throw new Error(`Matrix-vector multiplication requires matrix columns (${matrixCols}) to equal vector length (${vector.length})`);
|
|
178
|
-
}
|
|
179
169
|
// Initialize result vector with same length as matrix rows
|
|
180
170
|
const result = new Array(matrixRows);
|
|
181
171
|
// Compute each element of the result vector
|
|
182
172
|
for (let row = 0; row < matrixRows; row++) {
|
|
183
173
|
// Get matrix row reference
|
|
184
174
|
const matrixRow = matrix[row];
|
|
185
|
-
AssertMatrixRow(matrixRow);
|
|
186
175
|
// Compute dot product of matrix row with vector
|
|
187
176
|
let dotProduct = 0;
|
|
188
177
|
for (let col = 0; col < matrixCols; col++) {
|
|
189
178
|
// Validate matrix element
|
|
190
179
|
const matrixElement = matrixRow[col];
|
|
191
|
-
AssertMatrixValue(matrixElement, { rowIndex: row, columnIndex: col });
|
|
192
180
|
// Validate vector element
|
|
193
181
|
const vectorElement = vector[col];
|
|
194
|
-
AssertNumber(vectorElement);
|
|
195
182
|
// Add to dot product
|
|
196
183
|
dotProduct += matrixElement * vectorElement;
|
|
197
184
|
}
|
|
@@ -202,13 +189,15 @@ function matrixMultiplyVector(matrix, vector) {
|
|
|
202
189
|
}
|
|
203
190
|
function matrixMultiplyMatrix(a, b) {
|
|
204
191
|
// Validate matrices are compatible for multiplication (a.columns === b.rows)
|
|
205
|
-
|
|
192
|
+
AssertMatrix(a);
|
|
193
|
+
AssertMatrix(b);
|
|
206
194
|
const [arows, acols] = MatrixSize(a);
|
|
207
|
-
const aSquare = MatrixIsSquare(a);
|
|
208
195
|
const [brows, bcols] = MatrixSize(b);
|
|
209
|
-
|
|
196
|
+
if (acols !== brows) {
|
|
197
|
+
throw new MatrixError(`Cannot multiply matrices: [${arows}×${acols}] × [${brows}×${bcols}] - columns of first matrix must equal rows of second matrix`);
|
|
198
|
+
}
|
|
210
199
|
// Use optimized algorithms for specific square matrix sizes
|
|
211
|
-
if (
|
|
200
|
+
if (arows === acols && brows === bcols && arows === brows && acols === bcols) {
|
|
212
201
|
const aSizeSquare = arows;
|
|
213
202
|
if (aSizeSquare === 1) {
|
|
214
203
|
AssertMatrix1(a);
|
|
@@ -241,19 +230,14 @@ function matrixMultiplyMatrix(a, b) {
|
|
|
241
230
|
// Iterate through each position in the result matrix
|
|
242
231
|
for (let row = 0; row < arows; row++) {
|
|
243
232
|
const aRow = a[row];
|
|
244
|
-
AssertMatrixRow(aRow);
|
|
245
233
|
const resultRow = result[row];
|
|
246
|
-
AssertMatrixRow(resultRow);
|
|
247
234
|
for (let col = 0; col < bcols; col++) {
|
|
248
235
|
let sum = 0;
|
|
249
236
|
// Compute dot product of matrix A row with matrix B column
|
|
250
237
|
for (let k = 0; k < acols; k++) {
|
|
251
238
|
const aVal = aRow[k];
|
|
252
|
-
AssertMatrixValue(aVal, { rowIndex: row, columnIndex: k });
|
|
253
239
|
const bRow = b[k];
|
|
254
|
-
AssertMatrixRow(bRow);
|
|
255
240
|
const bVal = bRow[col];
|
|
256
|
-
AssertMatrixValue(bVal, { rowIndex: k, columnIndex: col });
|
|
257
241
|
// Skip multiplication if either operand is zero (performance optimization)
|
|
258
242
|
if (aVal === 0 || bVal === 0)
|
|
259
243
|
continue;
|
|
@@ -283,21 +267,20 @@ function matrixMultiplyMatrix(a, b) {
|
|
|
283
267
|
*
|
|
284
268
|
* @param a - First 1×1 matrix [[a]]
|
|
285
269
|
* @param b - Second 1×1 matrix [[b]]
|
|
286
|
-
* @returns {
|
|
270
|
+
* @returns {TMatrix1} The product as a 1×1 matrix [[a×b]]
|
|
287
271
|
*
|
|
288
272
|
* @example
|
|
289
273
|
* ```typescript
|
|
290
|
-
*
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
*
|
|
300
|
-
* matrixMultiplyMatrix1([[0]], [[999]]) // Returns [[0]]
|
|
274
|
+
* ```typescript
|
|
275
|
+
* // Simple scalar values in matrix form
|
|
276
|
+
* matrixMultiplyMatrix1([[5]], [[3]]) // Returns [[15]]
|
|
277
|
+
* // Decimal multiplication
|
|
278
|
+
* matrixMultiplyMatrix1([[2.5]], [[4]]) // Returns [[10]]
|
|
279
|
+
* // Negative values
|
|
280
|
+
* matrixMultiplyMatrix1([[-3]], [[7]]) // Returns [[-21]]
|
|
281
|
+
* // Zero multiplication
|
|
282
|
+
* matrixMultiplyMatrix1([[0]], [[999]]) // Returns [[0]]
|
|
283
|
+
* ```
|
|
301
284
|
* ```
|
|
302
285
|
*/
|
|
303
286
|
function matrixMultiplyMatrix1(a, b) {
|
|
@@ -328,24 +311,24 @@ function matrixMultiplyMatrix1(a, b) {
|
|
|
328
311
|
*
|
|
329
312
|
* @param a - First 2×2 matrix
|
|
330
313
|
* @param b - Second 2×2 matrix
|
|
331
|
-
* @returns {
|
|
314
|
+
* @returns {TMatrix2} The product as a 2×2 matrix
|
|
332
315
|
* @example
|
|
333
316
|
* ```typescript
|
|
317
|
+
* ```typescript
|
|
334
318
|
* // Standard 2x2 multiplication
|
|
335
319
|
* matrixMultiplyMatrix2([[1, 2], [3, 4]], [[5, 6], [7, 8]])
|
|
336
320
|
* // Returns [[19, 22], [43, 50]]
|
|
337
321
|
* // Calculation:
|
|
338
322
|
* // [1*5+2*7, 1*6+2*8] = [19, 22]
|
|
339
323
|
* // [3*5+4*7, 3*6+4*8] = [43, 50]
|
|
340
|
-
*
|
|
341
324
|
* // 2D rotation by 90 degrees (rotation matrix)
|
|
342
325
|
* matrixMultiplyMatrix2([[0, -1], [1, 0]], [[1, 0], [0, 1]])
|
|
343
326
|
* // Returns [[0, -1], [1, 0]]
|
|
344
|
-
*
|
|
345
327
|
* // Scaling transformation
|
|
346
328
|
* matrixMultiplyMatrix2([[2, 0], [0, 3]], [[1, 2], [3, 4]])
|
|
347
329
|
* // Returns [[2, 4], [9, 12]]
|
|
348
330
|
* ```
|
|
331
|
+
* ```
|
|
349
332
|
*/
|
|
350
333
|
function matrixMultiplyMatrix2(a, b) {
|
|
351
334
|
return [
|
|
@@ -387,22 +370,22 @@ function matrixMultiplyMatrix2(a, b) {
|
|
|
387
370
|
*
|
|
388
371
|
* @param a - First 3×3 matrix
|
|
389
372
|
* @param b - Second 3×3 matrix
|
|
390
|
-
* @returns {
|
|
373
|
+
* @returns {TMatrix3} The product as a 3×3 matrix
|
|
391
374
|
* @example
|
|
392
375
|
* ```typescript
|
|
376
|
+
* ```typescript
|
|
393
377
|
* // 3D rotation matrix multiplication (combining rotations)
|
|
394
378
|
* const rotX = [[1, 0, 0], [0, 0.707, -0.707], [0, 0.707, 0.707]]; // X rotation
|
|
395
379
|
* const rotY = [[0.707, 0, 0.707], [0, 1, 0], [-0.707, 0, 0.707]]; // Y rotation
|
|
396
380
|
* matrixMultiplyMatrix3(rotX, rotY) // Combined X-Y rotation
|
|
397
|
-
*
|
|
398
381
|
* // Identity matrix test
|
|
399
382
|
* matrixMultiplyMatrix3([[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
|
|
400
383
|
* // Returns [[1, 2, 3], [4, 5, 6], [7, 8, 9]] (unchanged)
|
|
401
|
-
*
|
|
402
384
|
* // Scaling transformation
|
|
403
385
|
* matrixMultiplyMatrix3([[2, 0, 0], [0, 3, 0], [0, 0, 4]], [[1, 1, 1], [1, 1, 1], [1, 1, 1]])
|
|
404
386
|
* // Returns [[2, 2, 2], [3, 3, 3], [4, 4, 4]]
|
|
405
387
|
* ```
|
|
388
|
+
* ```
|
|
406
389
|
*/
|
|
407
390
|
function matrixMultiplyMatrix3(a, b) {
|
|
408
391
|
return [
|
|
@@ -459,24 +442,24 @@ function matrixMultiplyMatrix3(a, b) {
|
|
|
459
442
|
*
|
|
460
443
|
* @param a - First 4×4 matrix (typically a transformation matrix)
|
|
461
444
|
* @param b - Second 4×4 matrix (typically another transformation matrix)
|
|
462
|
-
* @returns {
|
|
445
|
+
* @returns {TMatrix4} The product as a 4×4 matrix (combined transformation)
|
|
463
446
|
* @example
|
|
464
447
|
* ```typescript
|
|
448
|
+
* ```typescript
|
|
465
449
|
* // Combine translation and rotation matrices (common in 3D graphics)
|
|
466
450
|
* const translation = [[1,0,0,5], [0,1,0,3], [0,0,1,0], [0,0,0,1]]; // Translate by (5,3,0)
|
|
467
451
|
* const rotation = [[0,-1,0,0], [1,0,0,0], [0,0,1,0], [0,0,0,1]]; // 90° Z rotation
|
|
468
452
|
* matrixMultiplyMatrix4(translation, rotation); // Combined transform
|
|
469
|
-
*
|
|
470
453
|
* // Identity matrix test (should return unchanged matrix)
|
|
471
454
|
* const testMatrix = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]];
|
|
472
455
|
* const identity = [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]];
|
|
473
456
|
* matrixMultiplyMatrix4(testMatrix, identity) // Returns testMatrix unchanged
|
|
474
|
-
*
|
|
475
457
|
* // Perspective projection matrix combination
|
|
476
458
|
* const projection = [[2,0,0,0], [0,2,0,0], [0,0,-1,-1], [0,0,-2,0]];
|
|
477
459
|
* const view = [[1,0,0,0], [0,1,0,0], [0,0,1,-10], [0,0,0,1]];
|
|
478
460
|
* matrixMultiplyMatrix4(projection, view); // Combined projection-view matrix
|
|
479
461
|
* ```
|
|
462
|
+
* ```
|
|
480
463
|
*/
|
|
481
464
|
function matrixMultiplyMatrix4(a, b) {
|
|
482
465
|
return [
|
|
@@ -556,39 +539,39 @@ function matrixMultiplyMatrix4(a, b) {
|
|
|
556
539
|
*
|
|
557
540
|
* @param a - First square matrix (must be same size as b)
|
|
558
541
|
* @param b - Second square matrix (must be same size as a)
|
|
559
|
-
* @returns {
|
|
542
|
+
* @returns {TMatrix} The product matrix with same dimensions as inputs
|
|
560
543
|
* @throws {Error} If matrices are not square or have incompatible dimensions
|
|
561
544
|
*
|
|
562
545
|
* @example
|
|
563
546
|
* ```typescript
|
|
547
|
+
* ```typescript
|
|
564
548
|
* // Large matrix multiplication (automatically used for 32×32 and larger)
|
|
565
549
|
* const size = 256;
|
|
566
550
|
* const largeA = MatrixCreate(size, size); // Create 256×256 matrix
|
|
567
551
|
* const largeB = MatrixCreate(size, size); // Create 256×256 matrix
|
|
568
552
|
* // ... fill matrices with data ...
|
|
569
553
|
* const result = matrixMultiplyStrassen(largeA, largeB); // Uses Strassen algorithm
|
|
570
|
-
*
|
|
571
554
|
* // Performance comparison for large matrices:
|
|
572
555
|
* // Standard O(n³): ~16.8M operations for 256×256
|
|
573
556
|
* // Strassen O(n^2.807): ~11.2M operations for 256×256 (33% reduction)
|
|
574
|
-
*
|
|
575
557
|
* // Odd-sized matrices are automatically handled with padding
|
|
576
558
|
* const oddMatrix = MatrixCreate(127, 127); // Will be padded to 128×128 internally
|
|
577
559
|
* const result2 = matrixMultiplyStrassen(oddMatrix, oddMatrix);
|
|
578
|
-
*
|
|
579
560
|
* // Base case automatically falls back to standard algorithm
|
|
580
561
|
* const small = MatrixCreate(16, 16); // Uses standard algorithm (< 32×32)
|
|
581
562
|
* const result3 = matrixMultiplyStrassen(small, small);
|
|
582
563
|
* ```
|
|
564
|
+
* ```
|
|
583
565
|
*/
|
|
584
566
|
function matrixMultiplyStrassen(a, b) {
|
|
585
|
-
AssertMatrix(a
|
|
586
|
-
|
|
567
|
+
AssertMatrix(a);
|
|
568
|
+
AssertMatrixSquare(a);
|
|
569
|
+
AssertMatrix(b);
|
|
570
|
+
AssertMatrixSquare(b);
|
|
587
571
|
const [arows, _acols] = MatrixSize(a);
|
|
588
572
|
const [brows, _bcols] = MatrixSize(b);
|
|
589
|
-
if (arows !== brows)
|
|
573
|
+
if (arows !== brows)
|
|
590
574
|
throw new Error(`Matrix dimensions incompatible for multiplication: ${arows}×${arows} and ${brows}×${brows}`);
|
|
591
|
-
}
|
|
592
575
|
const n = arows;
|
|
593
576
|
// Base case: use standard multiplication for small matrices to avoid overhead
|
|
594
577
|
if (n < 32) {
|
|
@@ -671,28 +654,24 @@ function matrixMultiplyStrassen(a, b) {
|
|
|
671
654
|
* @param startRow - Starting row index (0-based, inclusive) — note reversed order
|
|
672
655
|
* @param width - Number of columns to extract (must be positive)
|
|
673
656
|
* @param height - Number of rows to extract (must be positive)
|
|
674
|
-
* @returns {
|
|
657
|
+
* @returns {TMatrix} The extracted submatrix with dimensions height×width
|
|
675
658
|
* @throws {Error} If extraction bounds exceed matrix dimensions or contain invalid values
|
|
676
659
|
* @example
|
|
677
660
|
* ```typescript
|
|
661
|
+
* ```typescript
|
|
678
662
|
* const matrix = [
|
|
679
663
|
* [1, 2, 3, 4],
|
|
680
664
|
* [5, 6, 7, 8],
|
|
681
665
|
* [9, 10, 11, 12]
|
|
682
666
|
* ]; // 3×4 matrix
|
|
683
|
-
*
|
|
684
667
|
* // Extract 2×2 submatrix from top-left corner
|
|
685
668
|
* MatrixSubmatrix(matrix, 0, 0, 2, 2) // Returns [[1, 2], [5, 6]]
|
|
686
|
-
*
|
|
687
669
|
* // Extract 2×2 submatrix from center-right region
|
|
688
670
|
* MatrixSubmatrix(matrix, 2, 1, 2, 2) // Returns [[7, 8], [11, 12]]
|
|
689
|
-
*
|
|
690
671
|
* // Extract single column (column vector)
|
|
691
672
|
* MatrixSubmatrix(matrix, 1, 0, 1, 3) // Returns [[2], [6], [10]]
|
|
692
|
-
*
|
|
693
673
|
* // Extract single row (row vector)
|
|
694
674
|
* MatrixSubmatrix(matrix, 0, 1, 4, 1) // Returns [[5, 6, 7, 8]]
|
|
695
|
-
*
|
|
696
675
|
* // Block matrix partitioning for algorithms
|
|
697
676
|
* const large = MatrixCreate(8, 8); // 8×8 matrix
|
|
698
677
|
* const topLeft = MatrixSubmatrix(large, 0, 0, 4, 4); // Top-left 4×4 block
|
|
@@ -700,6 +679,7 @@ function matrixMultiplyStrassen(a, b) {
|
|
|
700
679
|
* const bottomLeft = MatrixSubmatrix(large, 0, 4, 4, 4); // Bottom-left 4×4 block
|
|
701
680
|
* const bottomRight = MatrixSubmatrix(large, 4, 4, 4, 4); // Bottom-right 4×4 block
|
|
702
681
|
* ```
|
|
682
|
+
* ```
|
|
703
683
|
*/
|
|
704
684
|
export function MatrixSubmatrix(matrix, startCol, startRow, width, height) {
|
|
705
685
|
AssertMatrix(matrix);
|
|
@@ -707,12 +687,9 @@ export function MatrixSubmatrix(matrix, startCol, startRow, width, height) {
|
|
|
707
687
|
// Copy elements from specified source region to result matrix
|
|
708
688
|
for (let row = 0; row < height; row++) {
|
|
709
689
|
const sourceRow = matrix[startRow + row];
|
|
710
|
-
AssertMatrixRow(sourceRow);
|
|
711
690
|
const resultRow = result[row];
|
|
712
|
-
AssertMatrixRow(resultRow);
|
|
713
691
|
for (let col = 0; col < width; col++) {
|
|
714
692
|
const val = sourceRow[startCol + col];
|
|
715
|
-
AssertMatrixValue(val, { rowIndex: startRow + row, columnIndex: startCol + col });
|
|
716
693
|
resultRow[col] = val;
|
|
717
694
|
}
|
|
718
695
|
}
|
|
@@ -756,12 +733,12 @@ export function MatrixSubmatrix(matrix, startCol, startRow, width, height) {
|
|
|
756
733
|
* @param matrix - Source matrix to pad
|
|
757
734
|
* @param newRows - Target number of rows (must be ≥ current rows)
|
|
758
735
|
* @param newCols - Target number of columns (must be ≥ current columns)
|
|
759
|
-
* @returns {
|
|
736
|
+
* @returns {TMatrix} The padded matrix with dimensions newRows×newCols
|
|
760
737
|
* @throws {Error} If new dimensions are smaller than current dimensions
|
|
761
738
|
* @example
|
|
762
739
|
* ```typescript
|
|
740
|
+
* ```typescript
|
|
763
741
|
* const matrix = [[1, 2], [3, 4]]; // 2×2 matrix
|
|
764
|
-
*
|
|
765
742
|
* // Pad to 4×4 matrix (symmetric padding)
|
|
766
743
|
* MatrixPad(matrix, 4, 4)
|
|
767
744
|
* // Returns:
|
|
@@ -769,26 +746,23 @@ export function MatrixSubmatrix(matrix, startCol, startRow, width, height) {
|
|
|
769
746
|
* // [3, 4, 0, 0],
|
|
770
747
|
* // [0, 0, 0, 0],
|
|
771
748
|
* // [0, 0, 0, 0]]
|
|
772
|
-
*
|
|
773
749
|
* // Pad to 3×4 matrix (asymmetric padding)
|
|
774
750
|
* MatrixPad(matrix, 3, 4)
|
|
775
751
|
* // Returns:
|
|
776
752
|
* // [[1, 2, 0, 0],
|
|
777
753
|
* // [3, 4, 0, 0],
|
|
778
754
|
* // [0, 0, 0, 0]]
|
|
779
|
-
*
|
|
780
755
|
* // Prepare for power-of-2 algorithm (e.g., FFT-based convolution)
|
|
781
756
|
* const data = [[1, 2, 3], [4, 5, 6]]; // 2×3 matrix
|
|
782
757
|
* const powerOf2 = MatrixPad(data, 4, 4); // Pad to 4×4 for FFT
|
|
783
|
-
*
|
|
784
758
|
* // Batch size alignment in machine learning
|
|
785
759
|
* const features = MatrixCreate(7, 10); // 7 samples, 10 features
|
|
786
760
|
* const aligned = MatrixPad(features, 8, 10); // Align to batch size 8
|
|
787
|
-
*
|
|
788
761
|
* // Image border padding for convolution
|
|
789
762
|
* const image = MatrixCreate(28, 28); // 28×28 image
|
|
790
763
|
* const padded = MatrixPad(image, 32, 32); // Add border for valid convolution
|
|
791
764
|
* ```
|
|
765
|
+
* ```
|
|
792
766
|
*/
|
|
793
767
|
export function MatrixPad(matrix, newRows, newCols) {
|
|
794
768
|
AssertMatrix(matrix);
|
|
@@ -797,12 +771,9 @@ export function MatrixPad(matrix, newRows, newCols) {
|
|
|
797
771
|
// Copy existing values to top-left corner, zero-fill remaining positions
|
|
798
772
|
for (let row = 0; row < Math.min(currentRows, newRows); row++) {
|
|
799
773
|
const sourceRow = matrix[row];
|
|
800
|
-
AssertMatrixRow(sourceRow);
|
|
801
774
|
const resultRow = result[row];
|
|
802
|
-
AssertMatrixRow(resultRow);
|
|
803
775
|
for (let col = 0; col < Math.min(currentCols, newCols); col++) {
|
|
804
776
|
const val = sourceRow[col];
|
|
805
|
-
AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
|
|
806
777
|
resultRow[col] = val;
|
|
807
778
|
}
|
|
808
779
|
}
|
|
@@ -856,31 +827,29 @@ export function MatrixPad(matrix, newRows, newCols) {
|
|
|
856
827
|
* @param c12 - Top-right quadrant (upper-right block)
|
|
857
828
|
* @param c21 - Bottom-left quadrant (lower-left block)
|
|
858
829
|
* @param c22 - Bottom-right quadrant (lower-right block)
|
|
859
|
-
* @returns {
|
|
830
|
+
* @returns {TMatrix} The combined matrix with dimensions 2n×2n (where each input is n×n)
|
|
860
831
|
* @throws {Error} If quadrants have mismatched dimensions or invalid values
|
|
861
832
|
*
|
|
862
833
|
* @example
|
|
863
834
|
* ```typescript
|
|
835
|
+
* ```typescript
|
|
864
836
|
* // Basic 2×2 quadrant combination
|
|
865
837
|
* const topLeft = [[1, 2], [3, 4]];
|
|
866
838
|
* const topRight = [[5, 6], [7, 8]];
|
|
867
839
|
* const bottomLeft = [[9, 10], [11, 12]];
|
|
868
840
|
* const bottomRight = [[13, 14], [15, 16]];
|
|
869
|
-
*
|
|
870
841
|
* MatrixCombine(topLeft, topRight, bottomLeft, bottomRight)
|
|
871
842
|
* // Returns:
|
|
872
843
|
* // [[1, 2, 5, 6],
|
|
873
844
|
* // [3, 4, 7, 8],
|
|
874
845
|
* // [9, 10, 13, 14],
|
|
875
846
|
* // [11,12, 15, 16]]
|
|
876
|
-
*
|
|
877
847
|
* // Strassen algorithm result reconstruction
|
|
878
848
|
* const m1 = computeStrassenProduct1(); // Computed Strassen intermediate results
|
|
879
849
|
* const m2 = computeStrassenProduct2();
|
|
880
850
|
* const m3 = computeStrassenProduct3();
|
|
881
851
|
* const m4 = computeStrassenProduct4();
|
|
882
852
|
* const finalResult = MatrixCombine(m1, m2, m3, m4); // Assemble final result
|
|
883
|
-
*
|
|
884
853
|
* // Image processing: combining processed quadrants
|
|
885
854
|
* const processedTopLeft = processImageQuadrant(imageTopLeft);
|
|
886
855
|
* const processedTopRight = processImageQuadrant(imageTopRight);
|
|
@@ -891,6 +860,7 @@ export function MatrixPad(matrix, newRows, newCols) {
|
|
|
891
860
|
* processedBottomLeft, processedBottomRight
|
|
892
861
|
* );
|
|
893
862
|
* ```
|
|
863
|
+
* ```
|
|
894
864
|
*/
|
|
895
865
|
export function MatrixCombine(c11, c12, c21, c22) {
|
|
896
866
|
AssertMatrix(c11);
|
|
@@ -904,48 +874,36 @@ export function MatrixCombine(c11, c12, c21, c22) {
|
|
|
904
874
|
// Copy c11 to top-left quadrant [0:n, 0:n]
|
|
905
875
|
for (let row = 0; row < halfSize; row++) {
|
|
906
876
|
const sourceRow = c11[row];
|
|
907
|
-
AssertMatrixRow(sourceRow);
|
|
908
877
|
const resultRow = result[row];
|
|
909
|
-
AssertMatrixRow(resultRow);
|
|
910
878
|
for (let col = 0; col < halfSize; col++) {
|
|
911
879
|
const val = sourceRow[col];
|
|
912
|
-
AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
|
|
913
880
|
resultRow[col] = val;
|
|
914
881
|
}
|
|
915
882
|
}
|
|
916
883
|
// Copy c12 to top-right quadrant [0:n, n:2n]
|
|
917
884
|
for (let row = 0; row < halfSize; row++) {
|
|
918
885
|
const sourceRow = c12[row];
|
|
919
|
-
AssertMatrixRow(sourceRow);
|
|
920
886
|
const resultRow = result[row];
|
|
921
|
-
AssertMatrixRow(resultRow);
|
|
922
887
|
for (let col = 0; col < halfSize; col++) {
|
|
923
888
|
const val = sourceRow[col];
|
|
924
|
-
AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
|
|
925
889
|
resultRow[col + halfSize] = val;
|
|
926
890
|
}
|
|
927
891
|
}
|
|
928
892
|
// Copy c21 to bottom-left quadrant [n:2n, 0:n]
|
|
929
893
|
for (let row = 0; row < halfSize; row++) {
|
|
930
894
|
const sourceRow = c21[row];
|
|
931
|
-
AssertMatrixRow(sourceRow);
|
|
932
895
|
const resultRow = result[row + halfSize];
|
|
933
|
-
AssertMatrixRow(resultRow);
|
|
934
896
|
for (let col = 0; col < halfSize; col++) {
|
|
935
897
|
const val = sourceRow[col];
|
|
936
|
-
AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
|
|
937
898
|
resultRow[col] = val;
|
|
938
899
|
}
|
|
939
900
|
}
|
|
940
901
|
// Copy c22 to bottom-right quadrant [n:2n, n:2n]
|
|
941
902
|
for (let row = 0; row < halfSize; row++) {
|
|
942
903
|
const sourceRow = c22[row];
|
|
943
|
-
AssertMatrixRow(sourceRow);
|
|
944
904
|
const resultRow = result[row + halfSize];
|
|
945
|
-
AssertMatrixRow(resultRow);
|
|
946
905
|
for (let col = 0; col < halfSize; col++) {
|
|
947
906
|
const val = sourceRow[col];
|
|
948
|
-
AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
|
|
949
907
|
resultRow[col + halfSize] = val;
|
|
950
908
|
}
|
|
951
909
|
}
|