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