@pawells/math-extended 1.0.1

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.
Files changed (195) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +319 -0
  3. package/build/angles.d.ts +31 -0
  4. package/build/angles.d.ts.map +1 -0
  5. package/build/angles.js +85 -0
  6. package/build/angles.js.map +1 -0
  7. package/build/angles.spec.d.ts +2 -0
  8. package/build/angles.spec.d.ts.map +1 -0
  9. package/build/angles.spec.js +147 -0
  10. package/build/angles.spec.js.map +1 -0
  11. package/build/clamp.d.ts +17 -0
  12. package/build/clamp.d.ts.map +1 -0
  13. package/build/clamp.js +19 -0
  14. package/build/clamp.js.map +1 -0
  15. package/build/clamp.spec.d.ts +2 -0
  16. package/build/clamp.spec.d.ts.map +1 -0
  17. package/build/clamp.spec.js +19 -0
  18. package/build/clamp.spec.js.map +1 -0
  19. package/build/documentation-validation.spec.d.ts +11 -0
  20. package/build/documentation-validation.spec.d.ts.map +1 -0
  21. package/build/documentation-validation.spec.js +401 -0
  22. package/build/documentation-validation.spec.js.map +1 -0
  23. package/build/index.d.ts +8 -0
  24. package/build/index.d.ts.map +1 -0
  25. package/build/index.js +8 -0
  26. package/build/index.js.map +1 -0
  27. package/build/interpolation.d.ts +175 -0
  28. package/build/interpolation.d.ts.map +1 -0
  29. package/build/interpolation.js +369 -0
  30. package/build/interpolation.js.map +1 -0
  31. package/build/interpolation.spec.d.ts +2 -0
  32. package/build/interpolation.spec.d.ts.map +1 -0
  33. package/build/interpolation.spec.js +480 -0
  34. package/build/interpolation.spec.js.map +1 -0
  35. package/build/matrices/arithmetic.d.ts +411 -0
  36. package/build/matrices/arithmetic.d.ts.map +1 -0
  37. package/build/matrices/arithmetic.js +954 -0
  38. package/build/matrices/arithmetic.js.map +1 -0
  39. package/build/matrices/arithmetic.spec.d.ts +2 -0
  40. package/build/matrices/arithmetic.spec.d.ts.map +1 -0
  41. package/build/matrices/arithmetic.spec.js +915 -0
  42. package/build/matrices/arithmetic.spec.js.map +1 -0
  43. package/build/matrices/asserts.d.ts +306 -0
  44. package/build/matrices/asserts.d.ts.map +1 -0
  45. package/build/matrices/asserts.js +396 -0
  46. package/build/matrices/asserts.js.map +1 -0
  47. package/build/matrices/asserts.spec.d.ts +2 -0
  48. package/build/matrices/asserts.spec.d.ts.map +1 -0
  49. package/build/matrices/asserts.spec.js +565 -0
  50. package/build/matrices/asserts.spec.js.map +1 -0
  51. package/build/matrices/core.d.ts +168 -0
  52. package/build/matrices/core.d.ts.map +1 -0
  53. package/build/matrices/core.js +457 -0
  54. package/build/matrices/core.js.map +1 -0
  55. package/build/matrices/core.spec.d.ts +2 -0
  56. package/build/matrices/core.spec.d.ts.map +1 -0
  57. package/build/matrices/core.spec.js +634 -0
  58. package/build/matrices/core.spec.js.map +1 -0
  59. package/build/matrices/decompositions.d.ts +326 -0
  60. package/build/matrices/decompositions.d.ts.map +1 -0
  61. package/build/matrices/decompositions.js +816 -0
  62. package/build/matrices/decompositions.js.map +1 -0
  63. package/build/matrices/decompositions.spec.d.ts +2 -0
  64. package/build/matrices/decompositions.spec.d.ts.map +1 -0
  65. package/build/matrices/decompositions.spec.js +195 -0
  66. package/build/matrices/decompositions.spec.js.map +1 -0
  67. package/build/matrices/index.d.ts +9 -0
  68. package/build/matrices/index.d.ts.map +1 -0
  69. package/build/matrices/index.js +9 -0
  70. package/build/matrices/index.js.map +1 -0
  71. package/build/matrices/linear-algebra.d.ts +64 -0
  72. package/build/matrices/linear-algebra.d.ts.map +1 -0
  73. package/build/matrices/linear-algebra.js +253 -0
  74. package/build/matrices/linear-algebra.js.map +1 -0
  75. package/build/matrices/linear-algebra.spec.d.ts +2 -0
  76. package/build/matrices/linear-algebra.spec.d.ts.map +1 -0
  77. package/build/matrices/linear-algebra.spec.js +355 -0
  78. package/build/matrices/linear-algebra.spec.js.map +1 -0
  79. package/build/matrices/normalization.d.ts +62 -0
  80. package/build/matrices/normalization.d.ts.map +1 -0
  81. package/build/matrices/normalization.js +167 -0
  82. package/build/matrices/normalization.js.map +1 -0
  83. package/build/matrices/normalization.spec.d.ts +2 -0
  84. package/build/matrices/normalization.spec.d.ts.map +1 -0
  85. package/build/matrices/normalization.spec.js +335 -0
  86. package/build/matrices/normalization.spec.js.map +1 -0
  87. package/build/matrices/transformations.d.ts +484 -0
  88. package/build/matrices/transformations.d.ts.map +1 -0
  89. package/build/matrices/transformations.js +592 -0
  90. package/build/matrices/transformations.js.map +1 -0
  91. package/build/matrices/transformations.spec.d.ts +2 -0
  92. package/build/matrices/transformations.spec.d.ts.map +1 -0
  93. package/build/matrices/transformations.spec.js +755 -0
  94. package/build/matrices/transformations.spec.js.map +1 -0
  95. package/build/matrices/types.d.ts +134 -0
  96. package/build/matrices/types.d.ts.map +1 -0
  97. package/build/matrices/types.js +6 -0
  98. package/build/matrices/types.js.map +1 -0
  99. package/build/quaternions/asserts.d.ts +77 -0
  100. package/build/quaternions/asserts.d.ts.map +1 -0
  101. package/build/quaternions/asserts.js +175 -0
  102. package/build/quaternions/asserts.js.map +1 -0
  103. package/build/quaternions/asserts.spec.d.ts +2 -0
  104. package/build/quaternions/asserts.spec.d.ts.map +1 -0
  105. package/build/quaternions/asserts.spec.js +320 -0
  106. package/build/quaternions/asserts.spec.js.map +1 -0
  107. package/build/quaternions/conversions.d.ts +73 -0
  108. package/build/quaternions/conversions.d.ts.map +1 -0
  109. package/build/quaternions/conversions.js +179 -0
  110. package/build/quaternions/conversions.js.map +1 -0
  111. package/build/quaternions/conversions.spec.d.ts +2 -0
  112. package/build/quaternions/conversions.spec.d.ts.map +1 -0
  113. package/build/quaternions/conversions.spec.js +344 -0
  114. package/build/quaternions/conversions.spec.js.map +1 -0
  115. package/build/quaternions/core.d.ts +203 -0
  116. package/build/quaternions/core.d.ts.map +1 -0
  117. package/build/quaternions/core.js +374 -0
  118. package/build/quaternions/core.js.map +1 -0
  119. package/build/quaternions/core.spec.d.ts +2 -0
  120. package/build/quaternions/core.spec.d.ts.map +1 -0
  121. package/build/quaternions/core.spec.js +294 -0
  122. package/build/quaternions/core.spec.js.map +1 -0
  123. package/build/quaternions/index.d.ts +7 -0
  124. package/build/quaternions/index.d.ts.map +1 -0
  125. package/build/quaternions/index.js +7 -0
  126. package/build/quaternions/index.js.map +1 -0
  127. package/build/quaternions/interpolation.d.ts +54 -0
  128. package/build/quaternions/interpolation.d.ts.map +1 -0
  129. package/build/quaternions/interpolation.js +201 -0
  130. package/build/quaternions/interpolation.js.map +1 -0
  131. package/build/quaternions/interpolation.spec.d.ts +2 -0
  132. package/build/quaternions/interpolation.spec.d.ts.map +1 -0
  133. package/build/quaternions/interpolation.spec.js +64 -0
  134. package/build/quaternions/interpolation.spec.js.map +1 -0
  135. package/build/quaternions/predefined.d.ts +36 -0
  136. package/build/quaternions/predefined.d.ts.map +1 -0
  137. package/build/quaternions/predefined.js +42 -0
  138. package/build/quaternions/predefined.js.map +1 -0
  139. package/build/quaternions/predefined.spec.d.ts +2 -0
  140. package/build/quaternions/predefined.spec.d.ts.map +1 -0
  141. package/build/quaternions/predefined.spec.js +35 -0
  142. package/build/quaternions/predefined.spec.js.map +1 -0
  143. package/build/quaternions/types.d.ts +55 -0
  144. package/build/quaternions/types.d.ts.map +1 -0
  145. package/build/quaternions/types.js +7 -0
  146. package/build/quaternions/types.js.map +1 -0
  147. package/build/random.d.ts +66 -0
  148. package/build/random.d.ts.map +1 -0
  149. package/build/random.js +115 -0
  150. package/build/random.js.map +1 -0
  151. package/build/random.spec.d.ts +2 -0
  152. package/build/random.spec.d.ts.map +1 -0
  153. package/build/random.spec.js +267 -0
  154. package/build/random.spec.js.map +1 -0
  155. package/build/vectors/asserts.d.ts +182 -0
  156. package/build/vectors/asserts.d.ts.map +1 -0
  157. package/build/vectors/asserts.js +285 -0
  158. package/build/vectors/asserts.js.map +1 -0
  159. package/build/vectors/asserts.spec.d.ts +2 -0
  160. package/build/vectors/asserts.spec.d.ts.map +1 -0
  161. package/build/vectors/asserts.spec.js +260 -0
  162. package/build/vectors/asserts.spec.js.map +1 -0
  163. package/build/vectors/core.d.ts +507 -0
  164. package/build/vectors/core.d.ts.map +1 -0
  165. package/build/vectors/core.js +825 -0
  166. package/build/vectors/core.js.map +1 -0
  167. package/build/vectors/core.spec.d.ts +2 -0
  168. package/build/vectors/core.spec.d.ts.map +1 -0
  169. package/build/vectors/core.spec.js +343 -0
  170. package/build/vectors/core.spec.js.map +1 -0
  171. package/build/vectors/index.d.ts +6 -0
  172. package/build/vectors/index.d.ts.map +1 -0
  173. package/build/vectors/index.js +6 -0
  174. package/build/vectors/index.js.map +1 -0
  175. package/build/vectors/interpolation.d.ts +404 -0
  176. package/build/vectors/interpolation.d.ts.map +1 -0
  177. package/build/vectors/interpolation.js +585 -0
  178. package/build/vectors/interpolation.js.map +1 -0
  179. package/build/vectors/interpolation.spec.d.ts +2 -0
  180. package/build/vectors/interpolation.spec.d.ts.map +1 -0
  181. package/build/vectors/interpolation.spec.js +378 -0
  182. package/build/vectors/interpolation.spec.js.map +1 -0
  183. package/build/vectors/predefined.d.ts +191 -0
  184. package/build/vectors/predefined.d.ts.map +1 -0
  185. package/build/vectors/predefined.js +191 -0
  186. package/build/vectors/predefined.js.map +1 -0
  187. package/build/vectors/predefined.spec.d.ts +2 -0
  188. package/build/vectors/predefined.spec.d.ts.map +1 -0
  189. package/build/vectors/predefined.spec.js +333 -0
  190. package/build/vectors/predefined.spec.js.map +1 -0
  191. package/build/vectors/types.d.ts +62 -0
  192. package/build/vectors/types.d.ts.map +1 -0
  193. package/build/vectors/types.js +6 -0
  194. package/build/vectors/types.js.map +1 -0
  195. package/package.json +75 -0
@@ -0,0 +1,954 @@
1
+ import { AssertNumber } from '@pawells/typescript-common';
2
+ import { AssertMatrices, AssertMatrix, AssertMatrix1, AssertMatrix2, AssertMatrix3, AssertMatrix4, AssertMatrixRow, AssertMatrixValue } from './asserts.js';
3
+ import { MatrixCreate, MatrixIsSquare, MatrixSize } from './core.js';
4
+ import { VectorIsValid } from '../vectors/core.js';
5
+ import { AssertVector } from '../vectors/asserts.js';
6
+ /**
7
+ * Performs element-wise addition of two matrices.
8
+ *
9
+ * This function implements matrix addition using the standard mathematical definition:
10
+ * `C[i,j] = A[i,j] + B[i,j]` for all valid indices i,j
11
+ *
12
+ * The operation requires both matrices to have identical dimensions and produces
13
+ * a new matrix without modifying the input matrices. Matrix addition is both
14
+ * commutative (A + B = B + A) and associative ((A + B) + C = A + (B + C)).
15
+ *
16
+ * **Properties:**
17
+ * - Commutative: A + B = B + A
18
+ * - Associative: (A + B) + C = A + (B + C)
19
+ * - Identity element: A + 0 = A (where 0 is the zero matrix)
20
+ * - Inverse element: A + (-A) = 0
21
+ *
22
+ * **Time Complexity:** O(m×n) where m and n are the matrix dimensions
23
+ * **Space Complexity:** O(m×n) for the result matrix
24
+ *
25
+ * @template T - The matrix type extending IMatrix interface
26
+ * @param a - First matrix (addend) - must have same dimensions as b
27
+ * @param b - Second matrix (addend) - must have same dimensions as a
28
+ * @returns {TMatrixResult<T>} A new matrix where each element is the sum of corresponding elements
29
+ * @throws {Error} If matrices have different dimensions or contain invalid values
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * // Adding 2×2 matrices
34
+ * MatrixAdd([[1, 2], [3, 4]], [[5, 6], [7, 8]]) // Returns [[6, 8], [10, 12]]
35
+ *
36
+ * // Adding 1×3 row vectors
37
+ * MatrixAdd([[1, 2, 3]], [[4, 5, 6]]) // Returns [[5, 7, 9]]
38
+ *
39
+ * // Type-safe matrix addition with specific matrix types
40
+ * const matrixA: IMatrix2 = [[1, 2], [3, 4]];
41
+ * const matrixB: IMatrix2 = [[5, 6], [7, 8]];
42
+ * const result: IMatrix2 = MatrixAdd(matrixA, matrixB);
43
+ * ```
44
+ */
45
+ export function MatrixAdd(a, b) {
46
+ // Validate matrices have compatible dimensions for addition
47
+ AssertMatrices(a, b);
48
+ // Initialize result matrix with same dimensions as inputs
49
+ const [arows, acols] = MatrixSize(a);
50
+ const result = MatrixCreate(arows, acols);
51
+ // Perform element-wise addition: C[i,j] = A[i,j] + B[i,j]
52
+ for (let row = 0; row < arows; row++) {
53
+ // Get row references for both input matrices
54
+ const aRow = a[row];
55
+ AssertMatrixRow(aRow);
56
+ const bRow = b[row];
57
+ AssertMatrixRow(bRow);
58
+ // Get reference to result row for efficient access
59
+ const resultRow = result[row];
60
+ AssertMatrixRow(resultRow);
61
+ // Add corresponding elements column by column
62
+ for (let col = 0; col < acols; col++) {
63
+ // Validate and extract values from both matrices
64
+ const aVal = aRow[col];
65
+ AssertMatrixValue(aVal, { rowIndex: row, columnIndex: col });
66
+ const bVal = bRow[col];
67
+ AssertMatrixValue(bVal, { rowIndex: row, columnIndex: col });
68
+ // Store sum in result matrix
69
+ resultRow[col] = aVal + bVal;
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+ /**
75
+ * Performs element-wise subtraction of two matrices (a - b).
76
+ *
77
+ * This function implements matrix subtraction using the standard mathematical definition:
78
+ * `C[i,j] = A[i,j] - B[i,j]` for all valid indices i,j
79
+ *
80
+ * The operation requires both matrices to have identical dimensions and produces
81
+ * a new matrix without modifying the input matrices. Note that matrix subtraction
82
+ * is **not commutative**: A - B ≠ B - A in general.
83
+ *
84
+ * **Properties:**
85
+ * - Non-commutative: A - B ≠ B - A (in general)
86
+ * - Non-associative: (A - B) - C ≠ A - (B - C) (in general)
87
+ * - Relationship to addition: A - B = A + (-B)
88
+ * - Self-subtraction: A - A = 0 (zero matrix)
89
+ *
90
+ * **Time Complexity:** O(m×n) where m and n are the matrix dimensions
91
+ * **Space Complexity:** O(m×n) for the result matrix
92
+ *
93
+ * @template T - The matrix type extending IMatrix interface
94
+ * @param a - First matrix (minuend) - the matrix being subtracted from
95
+ * @param b - Second matrix (subtrahend) - the matrix being subtracted
96
+ * @returns {TMatrixResult<T>} A new matrix where each element is the difference of corresponding elements
97
+ * @throws {Error} If matrices have different dimensions or contain invalid values
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * // Subtracting 2×2 matrices
102
+ * MatrixSubtract([[10, 8], [6, 4]], [[3, 2], [1, 1]]) // Returns [[7, 6], [5, 3]]
103
+ *
104
+ * // Order matters: A - B ≠ B - A
105
+ * MatrixSubtract([[1, 2]], [[3, 4]]) // Returns [[-2, -2]]
106
+ * MatrixSubtract([[3, 4]], [[1, 2]]) // Returns [[2, 2]]
107
+ *
108
+ * // Self-subtraction produces zero matrix
109
+ * MatrixSubtract([[5, 6]], [[5, 6]]) // Returns [[0, 0]]
110
+ * ```
111
+ */
112
+ export function MatrixSubtract(a, b) {
113
+ // Validate matrices have compatible dimensions for subtraction
114
+ AssertMatrices(a, b);
115
+ // Initialize result matrix with same dimensions as inputs
116
+ const [arows, acols] = MatrixSize(a);
117
+ const result = MatrixCreate(arows, acols);
118
+ // Perform element-wise subtraction: C[i,j] = A[i,j] - B[i,j]
119
+ for (let row = 0; row < arows; row++) {
120
+ // Get row references for both input matrices
121
+ const aRow = a[row];
122
+ AssertMatrixRow(aRow);
123
+ const bRow = b[row];
124
+ AssertMatrixRow(bRow);
125
+ // Get reference to result row for efficient access
126
+ const resultRow = result[row];
127
+ AssertMatrixRow(resultRow);
128
+ // Subtract corresponding elements column by column
129
+ for (let col = 0; col < acols; col++) {
130
+ const aVal = aRow[col];
131
+ AssertMatrixValue(aVal, { rowIndex: row, columnIndex: col });
132
+ const bVal = bRow[col];
133
+ AssertMatrixValue(bVal, { rowIndex: row, columnIndex: col });
134
+ // Store difference in result matrix
135
+ resultRow[col] = aVal - bVal;
136
+ }
137
+ }
138
+ return result;
139
+ }
140
+ export function MatrixMultiply(a, b) {
141
+ AssertMatrix(a);
142
+ // Route to appropriate multiplication algorithm based on operand type
143
+ if (typeof b === 'number')
144
+ return matrixMultiplyScalar(a, b);
145
+ if (VectorIsValid(b))
146
+ return matrixMultiplyVector(a, b);
147
+ return matrixMultiplyMatrix(a, b);
148
+ }
149
+ function matrixMultiplyScalar(matrix, scalar) {
150
+ AssertMatrix(matrix);
151
+ AssertNumber(scalar, { finite: true }, { message: 'Scalar multiplier must be a valid number' });
152
+ const [rows, cols] = MatrixSize(matrix);
153
+ const result = MatrixCreate(rows, cols);
154
+ // Apply scalar multiplication to each matrix element
155
+ for (let row = 0; row < rows; row++) {
156
+ const matrixRow = matrix[row];
157
+ AssertMatrixRow(matrixRow);
158
+ const resultRow = result[row];
159
+ AssertMatrixRow(resultRow);
160
+ // Multiply each element in the row by the scalar
161
+ for (let col = 0; col < cols; col++) {
162
+ const val = matrixRow[col];
163
+ AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
164
+ resultRow[col] = val * scalar;
165
+ }
166
+ }
167
+ return result;
168
+ }
169
+ function matrixMultiplyVector(matrix, vector) {
170
+ // Validate inputs
171
+ AssertMatrix(matrix);
172
+ AssertVector(vector);
173
+ // Get matrix dimensions
174
+ const [matrixRows, matrixCols] = MatrixSize(matrix);
175
+ // Verify dimensional compatibility: matrix columns must equal vector length
176
+ if (matrixCols !== vector.length) {
177
+ throw new Error(`Matrix-vector multiplication requires matrix columns (${matrixCols}) to equal vector length (${vector.length})`);
178
+ }
179
+ // Initialize result vector with same length as matrix rows
180
+ const result = new Array(matrixRows);
181
+ // Compute each element of the result vector
182
+ for (let row = 0; row < matrixRows; row++) {
183
+ // Get matrix row reference
184
+ const matrixRow = matrix[row];
185
+ AssertMatrixRow(matrixRow);
186
+ // Compute dot product of matrix row with vector
187
+ let dotProduct = 0;
188
+ for (let col = 0; col < matrixCols; col++) {
189
+ // Validate matrix element
190
+ const matrixElement = matrixRow[col];
191
+ AssertMatrixValue(matrixElement, { rowIndex: row, columnIndex: col });
192
+ // Validate vector element
193
+ const vectorElement = vector[col];
194
+ AssertNumber(vectorElement);
195
+ // Add to dot product
196
+ dotProduct += matrixElement * vectorElement;
197
+ }
198
+ // Store result
199
+ result[row] = dotProduct;
200
+ }
201
+ return result;
202
+ }
203
+ function matrixMultiplyMatrix(a, b) {
204
+ // Validate matrices are compatible for multiplication (a.columns === b.rows)
205
+ AssertMatrices(a, b, { transposition: true });
206
+ const [arows, acols] = MatrixSize(a);
207
+ const aSquare = MatrixIsSquare(a);
208
+ const [brows, bcols] = MatrixSize(b);
209
+ const bSquare = MatrixIsSquare(b);
210
+ // Use optimized algorithms for specific square matrix sizes
211
+ if (aSquare && bSquare && arows === brows && acols === bcols) {
212
+ const aSizeSquare = arows;
213
+ if (aSizeSquare === 1) {
214
+ AssertMatrix1(a);
215
+ AssertMatrix1(b);
216
+ return matrixMultiplyMatrix1(a, b);
217
+ }
218
+ else if (aSizeSquare === 2) {
219
+ AssertMatrix2(a);
220
+ AssertMatrix2(b);
221
+ return matrixMultiplyMatrix2(a, b);
222
+ }
223
+ else if (aSizeSquare === 3) {
224
+ AssertMatrix3(a);
225
+ AssertMatrix3(b);
226
+ return matrixMultiplyMatrix3(a, b);
227
+ }
228
+ else if (aSizeSquare === 4) {
229
+ AssertMatrix4(a);
230
+ AssertMatrix4(b);
231
+ return matrixMultiplyMatrix4(a, b);
232
+ }
233
+ else if (aSizeSquare >= 32) {
234
+ // Use Strassen algorithm for large square matrices (≥32×32)
235
+ // Provides better asymptotic performance O(n^2.807) vs O(n³)
236
+ return matrixMultiplyStrassen(a, b);
237
+ }
238
+ }
239
+ // Standard O(n³) algorithm for general case: C[i,j] = Σ(A[i,k] × B[k,j])
240
+ const result = MatrixCreate(arows, bcols);
241
+ // Iterate through each position in the result matrix
242
+ for (let row = 0; row < arows; row++) {
243
+ const aRow = a[row];
244
+ AssertMatrixRow(aRow);
245
+ const resultRow = result[row];
246
+ AssertMatrixRow(resultRow);
247
+ for (let col = 0; col < bcols; col++) {
248
+ let sum = 0;
249
+ // Compute dot product of matrix A row with matrix B column
250
+ for (let k = 0; k < acols; k++) {
251
+ const aVal = aRow[k];
252
+ AssertMatrixValue(aVal, { rowIndex: row, columnIndex: k });
253
+ const bRow = b[k];
254
+ AssertMatrixRow(bRow);
255
+ const bVal = bRow[col];
256
+ AssertMatrixValue(bVal, { rowIndex: k, columnIndex: col });
257
+ // Skip multiplication if either operand is zero (performance optimization)
258
+ if (aVal === 0 || bVal === 0)
259
+ continue;
260
+ sum += aVal * bVal;
261
+ }
262
+ resultRow[col] = sum;
263
+ }
264
+ }
265
+ return result;
266
+ }
267
+ /**
268
+ * Optimized multiplication for 1×1 matrices.
269
+ *
270
+ * For 1×1 matrices, multiplication reduces to simple scalar multiplication of the
271
+ * two single elements. This optimization completely avoids the overhead of nested
272
+ * loops and provides the fastest possible execution for this trivial case.
273
+ *
274
+ * **Mathematical formula:** `[[a]] × [[b]] = [[a×b]]`
275
+ *
276
+ * This function is primarily used as a base case in recursive algorithms and for
277
+ * completeness in the optimization hierarchy. While seemingly trivial, it provides
278
+ * measurable performance benefits in recursive divide-and-conquer algorithms like
279
+ * Strassen multiplication.
280
+ *
281
+ * **Time Complexity:** O(1) - constant time operation
282
+ * **Space Complexity:** O(1) - single element allocation
283
+ *
284
+ * @param a - First 1×1 matrix [[a]]
285
+ * @param b - Second 1×1 matrix [[b]]
286
+ * @returns {IMatrix1} The product as a 1×1 matrix [[a×b]]
287
+ *
288
+ * @example
289
+ * ```typescript
290
+ * // Simple scalar values in matrix form
291
+ * matrixMultiplyMatrix1([[5]], [[3]]) // Returns [[15]]
292
+ *
293
+ * // Decimal multiplication
294
+ * matrixMultiplyMatrix1([[2.5]], [[4]]) // Returns [[10]]
295
+ *
296
+ * // Negative values
297
+ * matrixMultiplyMatrix1([[-3]], [[7]]) // Returns [[-21]]
298
+ *
299
+ * // Zero multiplication
300
+ * matrixMultiplyMatrix1([[0]], [[999]]) // Returns [[0]]
301
+ * ```
302
+ */
303
+ function matrixMultiplyMatrix1(a, b) {
304
+ return [[a[0][0] * b[0][0]]];
305
+ }
306
+ /**
307
+ * Optimized multiplication for 2×2 matrices.
308
+ *
309
+ * This function implements hardcoded 2×2 matrix multiplication using direct
310
+ * element calculations, completely avoiding loop overhead. This optimization
311
+ * is particularly valuable since 2×2 matrices are commonly used in 2D graphics,
312
+ * rotation transformations, and as building blocks in recursive algorithms.
313
+ *
314
+ * Mathematical expansion of C = A × B:
315
+ * C[0,0] = A[0,0]×B[0,0] + A[0,1]×B[1,0]
316
+ * C[0,1] = A[0,0]×B[0,1] + A[0,1]×B[1,1]
317
+ * C[1,0] = A[1,0]×B[0,0] + A[1,1]×B[1,0]
318
+ * C[1,1] = A[1,0]×B[0,1] + A[1,1]×B[1,1]
319
+ *
320
+ * Applications:
321
+ * - 2D rotation and scaling transformations
322
+ * - Linear system solutions (2x2 case)
323
+ * - Recursive matrix algorithms (Strassen base case)
324
+ * - Computer graphics operations
325
+ *
326
+ * Time Complexity: O(1) - exactly 8 multiplications and 4 additions
327
+ * Space Complexity: O(1) - fixed 2×2 result allocation
328
+ *
329
+ * @param a - First 2×2 matrix
330
+ * @param b - Second 2×2 matrix
331
+ * @returns {IMatrix2} The product as a 2×2 matrix
332
+ * @example
333
+ * ```typescript
334
+ * // Standard 2x2 multiplication
335
+ * matrixMultiplyMatrix2([[1, 2], [3, 4]], [[5, 6], [7, 8]])
336
+ * // Returns [[19, 22], [43, 50]]
337
+ * // Calculation:
338
+ * // [1*5+2*7, 1*6+2*8] = [19, 22]
339
+ * // [3*5+4*7, 3*6+4*8] = [43, 50]
340
+ *
341
+ * // 2D rotation by 90 degrees (rotation matrix)
342
+ * matrixMultiplyMatrix2([[0, -1], [1, 0]], [[1, 0], [0, 1]])
343
+ * // Returns [[0, -1], [1, 0]]
344
+ *
345
+ * // Scaling transformation
346
+ * matrixMultiplyMatrix2([[2, 0], [0, 3]], [[1, 2], [3, 4]])
347
+ * // Returns [[2, 4], [9, 12]]
348
+ * ```
349
+ */
350
+ function matrixMultiplyMatrix2(a, b) {
351
+ return [
352
+ [
353
+ (a[0][0] * b[0][0]) + (a[0][1] * b[1][0]), // C[0,0]
354
+ (a[0][0] * b[0][1]) + (a[0][1] * b[1][1]), // C[0,1]
355
+ ],
356
+ [
357
+ (a[1][0] * b[0][0]) + (a[1][1] * b[1][0]), // C[1,0]
358
+ (a[1][0] * b[0][1]) + (a[1][1] * b[1][1]), // C[1,1]
359
+ ],
360
+ ];
361
+ }
362
+ /**
363
+ * Optimized multiplication for 3×3 matrices.
364
+ *
365
+ * This function implements hardcoded 3×3 matrix multiplication using direct
366
+ * element calculations. 3×3 matrices are extensively used in 3D computer graphics
367
+ * for representing rotations, scaling, shearing, and other linear transformations
368
+ * in homogeneous coordinate systems.
369
+ *
370
+ * Mathematical expansion: Each element C[i,j] = Σ(A[i,k] × B[k,j]) for k=0,1,2
371
+ *
372
+ * Applications:
373
+ * - 3D rotation matrices (Euler angles, axis-angle representations)
374
+ * - 3D scaling and shearing transformations
375
+ * - Camera transformations in computer graphics
376
+ * - Crystallography and materials science calculations
377
+ * - Robotic arm kinematics (rotation components)
378
+ *
379
+ * Performance Benefits:
380
+ * - Eliminates loop overhead with direct calculations
381
+ * - 27 hardcoded multiplications and 18 additions
382
+ * - Optimal cache usage with predictable memory access
383
+ * - Compiler can optimize register allocation
384
+ *
385
+ * Time Complexity: O(1) - exactly 27 multiplications and 18 additions
386
+ * Space Complexity: O(1) - fixed 3×3 result allocation
387
+ *
388
+ * @param a - First 3×3 matrix
389
+ * @param b - Second 3×3 matrix
390
+ * @returns {IMatrix3} The product as a 3×3 matrix
391
+ * @example
392
+ * ```typescript
393
+ * // 3D rotation matrix multiplication (combining rotations)
394
+ * const rotX = [[1, 0, 0], [0, 0.707, -0.707], [0, 0.707, 0.707]]; // X rotation
395
+ * const rotY = [[0.707, 0, 0.707], [0, 1, 0], [-0.707, 0, 0.707]]; // Y rotation
396
+ * matrixMultiplyMatrix3(rotX, rotY) // Combined X-Y rotation
397
+ *
398
+ * // Identity matrix test
399
+ * matrixMultiplyMatrix3([[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
400
+ * // Returns [[1, 2, 3], [4, 5, 6], [7, 8, 9]] (unchanged)
401
+ *
402
+ * // Scaling transformation
403
+ * matrixMultiplyMatrix3([[2, 0, 0], [0, 3, 0], [0, 0, 4]], [[1, 1, 1], [1, 1, 1], [1, 1, 1]])
404
+ * // Returns [[2, 2, 2], [3, 3, 3], [4, 4, 4]]
405
+ * ```
406
+ */
407
+ function matrixMultiplyMatrix3(a, b) {
408
+ return [
409
+ [
410
+ // Row 0: [a00*b00 + a01*b10 + a02*b20, a00*b01 + a01*b11 + a02*b21, a00*b02 + a01*b12 + a02*b22]
411
+ (a[0][0] * b[0][0]) + (a[0][1] * b[1][0]) + (a[0][2] * b[2][0]),
412
+ (a[0][0] * b[0][1]) + (a[0][1] * b[1][1]) + (a[0][2] * b[2][1]),
413
+ (a[0][0] * b[0][2]) + (a[0][1] * b[1][2]) + (a[0][2] * b[2][2]),
414
+ ],
415
+ [
416
+ // Row 1: [a10*b00 + a11*b10 + a12*b20, a10*b01 + a11*b11 + a12*b21, a10*b02 + a11*b12 + a12*b22]
417
+ (a[1][0] * b[0][0]) + (a[1][1] * b[1][0]) + (a[1][2] * b[2][0]),
418
+ (a[1][0] * b[0][1]) + (a[1][1] * b[1][1]) + (a[1][2] * b[2][1]),
419
+ (a[1][0] * b[0][2]) + (a[1][1] * b[1][2]) + (a[1][2] * b[2][2]),
420
+ ],
421
+ [
422
+ // Row 2: [a20*b00 + a21*b10 + a22*b20, a20*b01 + a21*b11 + a22*b21, a20*b02 + a21*b12 + a22*b22]
423
+ (a[2][0] * b[0][0]) + (a[2][1] * b[1][0]) + (a[2][2] * b[2][0]),
424
+ (a[2][0] * b[0][1]) + (a[2][1] * b[1][1]) + (a[2][2] * b[2][1]),
425
+ (a[2][0] * b[0][2]) + (a[2][1] * b[1][2]) + (a[2][2] * b[2][2]),
426
+ ],
427
+ ];
428
+ }
429
+ /**
430
+ * Optimized multiplication for 4×4 matrices.
431
+ *
432
+ * This function implements hardcoded 4×4 matrix multiplication using direct
433
+ * element calculations. 4×4 matrices are the cornerstone of 3D computer graphics,
434
+ * enabling homogeneous coordinate transformations that can represent translation,
435
+ * rotation, scaling, and perspective projection in a unified mathematical framework.
436
+ *
437
+ * Mathematical expansion: Each element C[i,j] = Σ(A[i,k] × B[k,j]) for k=0,1,2,3
438
+ *
439
+ * Applications:
440
+ * - 3D graphics transformation pipelines (model-view-projection matrices)
441
+ * - Homogeneous coordinate transformations (translation + rotation + scaling)
442
+ * - Perspective and orthographic projection matrices
443
+ * - Camera transformations and view matrices
444
+ * - Skeletal animation bone transformations
445
+ * - Virtual reality and augmented reality systems
446
+ *
447
+ * Homogeneous Coordinates Structure:
448
+ * [Rotation/Scale | Translation]
449
+ * [ 0 | 1 ]
450
+ *
451
+ * Performance Benefits:
452
+ * - Eliminates loop overhead with 64 direct calculations
453
+ * - Optimal for graphics transformation chains
454
+ * - Predictable memory access patterns
455
+ * - Compiler-optimizable register allocation
456
+ *
457
+ * Time Complexity: O(1) - exactly 64 multiplications and 48 additions
458
+ * Space Complexity: O(1) - fixed 4×4 result allocation
459
+ *
460
+ * @param a - First 4×4 matrix (typically a transformation matrix)
461
+ * @param b - Second 4×4 matrix (typically another transformation matrix)
462
+ * @returns {IMatrix4} The product as a 4×4 matrix (combined transformation)
463
+ * @example
464
+ * ```typescript
465
+ * // Combine translation and rotation matrices (common in 3D graphics)
466
+ * const translation = [[1,0,0,5], [0,1,0,3], [0,0,1,0], [0,0,0,1]]; // Translate by (5,3,0)
467
+ * const rotation = [[0,-1,0,0], [1,0,0,0], [0,0,1,0], [0,0,0,1]]; // 90° Z rotation
468
+ * matrixMultiplyMatrix4(translation, rotation); // Combined transform
469
+ *
470
+ * // Identity matrix test (should return unchanged matrix)
471
+ * const testMatrix = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]];
472
+ * const identity = [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]];
473
+ * matrixMultiplyMatrix4(testMatrix, identity) // Returns testMatrix unchanged
474
+ *
475
+ * // Perspective projection matrix combination
476
+ * const projection = [[2,0,0,0], [0,2,0,0], [0,0,-1,-1], [0,0,-2,0]];
477
+ * const view = [[1,0,0,0], [0,1,0,0], [0,0,1,-10], [0,0,0,1]];
478
+ * matrixMultiplyMatrix4(projection, view); // Combined projection-view matrix
479
+ * ```
480
+ */
481
+ function matrixMultiplyMatrix4(a, b) {
482
+ return [
483
+ [
484
+ // Row 0: Transform of basis vector [1,0,0,0]
485
+ (a[0][0] * b[0][0]) + (a[0][1] * b[1][0]) + (a[0][2] * b[2][0]) + (a[0][3] * b[3][0]),
486
+ (a[0][0] * b[0][1]) + (a[0][1] * b[1][1]) + (a[0][2] * b[2][1]) + (a[0][3] * b[3][1]),
487
+ (a[0][0] * b[0][2]) + (a[0][1] * b[1][2]) + (a[0][2] * b[2][2]) + (a[0][3] * b[3][2]),
488
+ (a[0][0] * b[0][3]) + (a[0][1] * b[1][3]) + (a[0][2] * b[2][3]) + (a[0][3] * b[3][3]),
489
+ ],
490
+ [
491
+ // Row 1: Transform of basis vector [0,1,0,0]
492
+ (a[1][0] * b[0][0]) + (a[1][1] * b[1][0]) + (a[1][2] * b[2][0]) + (a[1][3] * b[3][0]),
493
+ (a[1][0] * b[0][1]) + (a[1][1] * b[1][1]) + (a[1][2] * b[2][1]) + (a[1][3] * b[3][1]),
494
+ (a[1][0] * b[0][2]) + (a[1][1] * b[1][2]) + (a[1][2] * b[2][2]) + (a[1][3] * b[3][2]),
495
+ (a[1][0] * b[0][3]) + (a[1][1] * b[1][3]) + (a[1][2] * b[2][3]) + (a[1][3] * b[3][3]),
496
+ ],
497
+ [
498
+ // Row 2: Transform of basis vector [0,0,1,0]
499
+ (a[2][0] * b[0][0]) + (a[2][1] * b[1][0]) + (a[2][2] * b[2][0]) + (a[2][3] * b[3][0]),
500
+ (a[2][0] * b[0][1]) + (a[2][1] * b[1][1]) + (a[2][2] * b[2][1]) + (a[2][3] * b[3][1]),
501
+ (a[2][0] * b[0][2]) + (a[2][1] * b[1][2]) + (a[2][2] * b[2][2]) + (a[2][3] * b[3][2]),
502
+ (a[2][0] * b[0][3]) + (a[2][1] * b[1][3]) + (a[2][2] * b[2][3]) + (a[2][3] * b[3][3]),
503
+ ],
504
+ [
505
+ // Row 3: Transform of basis vector [0,0,0,1] (usually homogeneous coordinates)
506
+ (a[3][0] * b[0][0]) + (a[3][1] * b[1][0]) + (a[3][2] * b[2][0]) + (a[3][3] * b[3][0]),
507
+ (a[3][0] * b[0][1]) + (a[3][1] * b[1][1]) + (a[3][2] * b[2][1]) + (a[3][3] * b[3][1]),
508
+ (a[3][0] * b[0][2]) + (a[3][1] * b[1][2]) + (a[3][2] * b[2][2]) + (a[3][3] * b[3][2]),
509
+ (a[3][0] * b[0][3]) + (a[3][1] * b[1][3]) + (a[3][2] * b[2][3]) + (a[3][3] * b[3][3]),
510
+ ],
511
+ ];
512
+ }
513
+ /**
514
+ * Performs matrix multiplication using Strassen's algorithm for improved performance on large matrices.
515
+ *
516
+ * Strassen's algorithm is a divide-and-conquer approach that reduces the computational
517
+ * complexity of matrix multiplication from O(n³) to approximately O(n^2.807) by using
518
+ * clever algebraic manipulations. Instead of computing 8 submatrix products as in the
519
+ * naive block approach, Strassen's method computes only 7 products through strategic
520
+ * addition and subtraction operations.
521
+ *
522
+ * **Algorithm Overview:**
523
+ * 1. Recursively partition each n×n matrix into four (n/2)×(n/2) submatrices
524
+ * 2. Compute 7 specific intermediate products (M1-M7) using Strassen's formulas
525
+ * 3. Combine these products using addition/subtraction to form result quadrants
526
+ * 4. Recursively apply until reaching base case (n ≤ 32) where standard multiplication is used
527
+ *
528
+ * **Strassen's Seven Products:**
529
+ * - M1 = (A11 + A22)(B11 + B22)
530
+ * - M2 = (A21 + A22)B11
531
+ * - M3 = A11(B12 - B22)
532
+ * - M4 = A22(B21 - B11)
533
+ * - M5 = (A11 + A12)B22
534
+ * - M6 = (A21 - A11)(B11 + B12)
535
+ * - M7 = (A12 - A22)(B21 + B22)
536
+ *
537
+ * **Result Reconstruction:**
538
+ * - C11 = M1 + M4 - M5 + M7
539
+ * - C12 = M3 + M5
540
+ * - C21 = M2 + M4
541
+ * - C22 = M1 + M3 - M2 + M6
542
+ *
543
+ * **Performance Characteristics:**
544
+ * - Asymptotic complexity: O(n^2.807) vs O(n³) for standard algorithm
545
+ * - Crossover point: typically beneficial for matrices ≥ 32×32
546
+ * - Memory overhead: recursive calls and temporary matrices
547
+ * - Numerical stability: slightly less stable due to more floating-point operations
548
+ *
549
+ * **Automatic Optimizations:**
550
+ * - Base case optimization: switches to standard algorithm for small matrices
551
+ * - Padding handling: automatically pads odd-sized matrices with zeros
552
+ * - Memory management: efficient temporary matrix allocation and cleanup
553
+ *
554
+ * **Time Complexity:** O(n^2.807) average case, O(n³) worst case (small matrices)
555
+ * **Space Complexity:** O(n²) for recursive call stack and temporary matrices
556
+ *
557
+ * @param a - First square matrix (must be same size as b)
558
+ * @param b - Second square matrix (must be same size as a)
559
+ * @returns {IMatrix} The product matrix with same dimensions as inputs
560
+ * @throws {Error} If matrices are not square or have incompatible dimensions
561
+ *
562
+ * @example
563
+ * ```typescript
564
+ * // Large matrix multiplication (automatically used for 32×32 and larger)
565
+ * const size = 256;
566
+ * const largeA = MatrixCreate(size, size); // Create 256×256 matrix
567
+ * const largeB = MatrixCreate(size, size); // Create 256×256 matrix
568
+ * // ... fill matrices with data ...
569
+ * const result = matrixMultiplyStrassen(largeA, largeB); // Uses Strassen algorithm
570
+ *
571
+ * // Performance comparison for large matrices:
572
+ * // Standard O(n³): ~16.8M operations for 256×256
573
+ * // Strassen O(n^2.807): ~11.2M operations for 256×256 (33% reduction)
574
+ *
575
+ * // Odd-sized matrices are automatically handled with padding
576
+ * const oddMatrix = MatrixCreate(127, 127); // Will be padded to 128×128 internally
577
+ * const result2 = matrixMultiplyStrassen(oddMatrix, oddMatrix);
578
+ *
579
+ * // Base case automatically falls back to standard algorithm
580
+ * const small = MatrixCreate(16, 16); // Uses standard algorithm (< 32×32)
581
+ * const result3 = matrixMultiplyStrassen(small, small);
582
+ * ```
583
+ */
584
+ function matrixMultiplyStrassen(a, b) {
585
+ AssertMatrix(a, { square: true });
586
+ AssertMatrix(b, { square: true });
587
+ const [arows, _acols] = MatrixSize(a);
588
+ const [brows, _bcols] = MatrixSize(b);
589
+ if (arows !== brows) {
590
+ throw new Error(`Matrix dimensions incompatible for multiplication: ${arows}×${arows} and ${brows}×${brows}`);
591
+ }
592
+ const n = arows;
593
+ // Base case: use standard multiplication for small matrices to avoid overhead
594
+ if (n < 32) {
595
+ return matrixMultiplyMatrix(a, b);
596
+ }
597
+ // Ensure matrix size is even for clean partitioning into quadrants
598
+ if (n % 2 !== 0) {
599
+ // Pad matrices to next even size with zeros
600
+ const paddedSize = n + 1;
601
+ const aPadded = MatrixPad(a, paddedSize, paddedSize);
602
+ const bPadded = MatrixPad(b, paddedSize, paddedSize);
603
+ const resultPadded = matrixMultiplyStrassen(aPadded, bPadded);
604
+ // Extract original size result (remove padding)
605
+ return MatrixSubmatrix(resultPadded, 0, 0, n, n);
606
+ }
607
+ const halfSize = n / 2;
608
+ // Partition matrices into 2×2 blocks: A=[A11 A12; A21 A22], B=[B11 B12; B21 B22]
609
+ const a11 = MatrixSubmatrix(a, 0, 0, halfSize, halfSize);
610
+ const a12 = MatrixSubmatrix(a, halfSize, 0, halfSize, halfSize);
611
+ const a21 = MatrixSubmatrix(a, 0, halfSize, halfSize, halfSize);
612
+ const a22 = MatrixSubmatrix(a, halfSize, halfSize, halfSize, halfSize);
613
+ const b11 = MatrixSubmatrix(b, 0, 0, halfSize, halfSize);
614
+ const b12 = MatrixSubmatrix(b, halfSize, 0, halfSize, halfSize);
615
+ const b21 = MatrixSubmatrix(b, 0, halfSize, halfSize, halfSize);
616
+ const b22 = MatrixSubmatrix(b, halfSize, halfSize, halfSize, halfSize);
617
+ // Calculate the 7 Strassen products (reduces 8 multiplications to 7)
618
+ // These specific combinations enable efficient result reconstruction
619
+ const m1 = matrixMultiplyStrassen(MatrixAdd(a11, a22), MatrixAdd(b11, b22)); // (A11+A22)(B11+B22)
620
+ const m2 = matrixMultiplyStrassen(MatrixAdd(a21, a22), b11); // (A21+A22)B11
621
+ const m3 = matrixMultiplyStrassen(a11, MatrixSubtract(b12, b22)); // A11(B12-B22)
622
+ const m4 = matrixMultiplyStrassen(a22, MatrixSubtract(b21, b11)); // A22(B21-B11)
623
+ const m5 = matrixMultiplyStrassen(MatrixAdd(a11, a12), b22); // (A11+A12)B22
624
+ const m6 = matrixMultiplyStrassen(MatrixSubtract(a21, a11), MatrixAdd(b11, b12)); // (A21-A11)(B11+B12)
625
+ const m7 = matrixMultiplyStrassen(MatrixSubtract(a12, a22), MatrixAdd(b21, b22)); // (A12-A22)(B21+B22)
626
+ // Reconstruct result quadrants using Strassen's combination formulas
627
+ const c11 = MatrixAdd(MatrixSubtract(MatrixAdd(m1, m4), m5), m7); // M1 + M4 - M5 + M7
628
+ const c12 = MatrixAdd(m3, m5); // M3 + M5
629
+ const c21 = MatrixAdd(m2, m4); // M2 + M4
630
+ const c22 = MatrixAdd(MatrixSubtract(MatrixAdd(m1, m3), m2), m6); // M1 + M3 - M2 + M6
631
+ // Combine quadrants into final result matrix
632
+ return MatrixCombine(c11, c12, c21, c22);
633
+ }
634
+ /**
635
+ * Extracts a rectangular submatrix from a larger matrix.
636
+ *
637
+ * This function creates a new matrix containing a specified rectangular region from
638
+ * the source matrix. It performs a deep copy of the selected elements, ensuring the
639
+ * original matrix remains unmodified. This operation is fundamental for matrix
640
+ * partitioning algorithms, block operations, and data analysis workflows.
641
+ *
642
+ * Coordinate System:
643
+ * - startRow, startCol: Top-left corner of the extraction region (0-based, inclusive)
644
+ * - width, height: Dimensions of the region to extract
645
+ * - Extraction bounds: [startRow, startRow+height) × [startCol, startCol+width)
646
+ *
647
+ * NOTE: parameter order is (startCol, startRow) — reversed from typical convention
648
+ *
649
+ * Applications:
650
+ * - Block matrix algorithms (Strassen, block LU decomposition)
651
+ * - Image processing (extracting regions of interest)
652
+ * - Data analysis (extracting subsets of datasets)
653
+ * - Sparse matrix operations (extracting dense blocks)
654
+ * - Machine learning (feature selection, data windowing)
655
+ *
656
+ * Bounds Checking:
657
+ * - Validates that extraction region fits within source matrix
658
+ * - Ensures all parameters are non-negative integers
659
+ * - Checks for valid matrix structure and element values
660
+ *
661
+ * Memory Efficiency:
662
+ * - Creates new matrix with minimal required size
663
+ * - Performs element-by-element copying with validation
664
+ * - No unnecessary memory allocation or copying
665
+ *
666
+ * Time Complexity: O(width × height) - linear in extracted region size
667
+ * Space Complexity: O(width × height) - size of extracted submatrix
668
+ *
669
+ * @param matrix - Source matrix to extract from
670
+ * @param startCol - Starting column index (0-based, inclusive) — note reversed order
671
+ * @param startRow - Starting row index (0-based, inclusive) — note reversed order
672
+ * @param width - Number of columns to extract (must be positive)
673
+ * @param height - Number of rows to extract (must be positive)
674
+ * @returns {IMatrix} The extracted submatrix with dimensions height×width
675
+ * @throws {Error} If extraction bounds exceed matrix dimensions or contain invalid values
676
+ * @example
677
+ * ```typescript
678
+ * const matrix = [
679
+ * [1, 2, 3, 4],
680
+ * [5, 6, 7, 8],
681
+ * [9, 10, 11, 12]
682
+ * ]; // 3×4 matrix
683
+ *
684
+ * // Extract 2×2 submatrix from top-left corner
685
+ * MatrixSubmatrix(matrix, 0, 0, 2, 2) // Returns [[1, 2], [5, 6]]
686
+ *
687
+ * // Extract 2×2 submatrix from center-right region
688
+ * MatrixSubmatrix(matrix, 2, 1, 2, 2) // Returns [[7, 8], [11, 12]]
689
+ *
690
+ * // Extract single column (column vector)
691
+ * MatrixSubmatrix(matrix, 1, 0, 1, 3) // Returns [[2], [6], [10]]
692
+ *
693
+ * // Extract single row (row vector)
694
+ * MatrixSubmatrix(matrix, 0, 1, 4, 1) // Returns [[5, 6, 7, 8]]
695
+ *
696
+ * // Block matrix partitioning for algorithms
697
+ * const large = MatrixCreate(8, 8); // 8×8 matrix
698
+ * const topLeft = MatrixSubmatrix(large, 0, 0, 4, 4); // Top-left 4×4 block
699
+ * const topRight = MatrixSubmatrix(large, 4, 0, 4, 4); // Top-right 4×4 block
700
+ * const bottomLeft = MatrixSubmatrix(large, 0, 4, 4, 4); // Bottom-left 4×4 block
701
+ * const bottomRight = MatrixSubmatrix(large, 4, 4, 4, 4); // Bottom-right 4×4 block
702
+ * ```
703
+ */
704
+ export function MatrixSubmatrix(matrix, startCol, startRow, width, height) {
705
+ AssertMatrix(matrix);
706
+ const result = MatrixCreate(height, width);
707
+ // Copy elements from specified source region to result matrix
708
+ for (let row = 0; row < height; row++) {
709
+ const sourceRow = matrix[startRow + row];
710
+ AssertMatrixRow(sourceRow);
711
+ const resultRow = result[row];
712
+ AssertMatrixRow(resultRow);
713
+ for (let col = 0; col < width; col++) {
714
+ const val = sourceRow[startCol + col];
715
+ AssertMatrixValue(val, { rowIndex: startRow + row, columnIndex: startCol + col });
716
+ resultRow[col] = val;
717
+ }
718
+ }
719
+ return result;
720
+ }
721
+ /**
722
+ * Pads a matrix with zeros to reach the specified dimensions.
723
+ *
724
+ * This function extends a matrix by adding rows and/or columns filled with zeros,
725
+ * preserving the original matrix content in the top-left corner. This operation
726
+ * is essential for algorithms that require matrices of specific sizes or when
727
+ * preparing matrices for operations that need dimension alignment.
728
+ *
729
+ * Padding Strategy:
730
+ * - Original content remains in top-left corner at [0,0]
731
+ * - Additional rows/columns are filled with zeros
732
+ * - New dimensions must be greater than or equal to current dimensions
733
+ * - Supports both symmetric and asymmetric padding
734
+ *
735
+ * Common Use Cases:
736
+ * - Algorithm requirements (power-of-2 sizes for FFT-based algorithms)
737
+ * - Block matrix operations (ensuring uniform block sizes)
738
+ * - Strassen algorithm (handling odd-sized matrices)
739
+ * - Image processing (border padding for convolution operations)
740
+ * - Signal processing (zero-padding for frequency domain analysis)
741
+ * - Machine learning (batch size alignment, tensor operations)
742
+ *
743
+ * Padding Preservation Property:
744
+ * If A is the original matrix and A' is the padded matrix, then:
745
+ * A'[i,j] = A[i,j] for all valid i,j in A
746
+ * A'[i,j] = 0 for all other positions
747
+ *
748
+ * Memory Efficiency:
749
+ * - Creates new matrix only of the target size
750
+ * - Copies only existing elements (no redundant operations)
751
+ * - Zero-fills remaining positions efficiently
752
+ *
753
+ * Time Complexity: O(newRows × newCols) - must initialize entire new matrix
754
+ * Space Complexity: O(newRows × newCols) - size of padded result
755
+ *
756
+ * @param matrix - Source matrix to pad
757
+ * @param newRows - Target number of rows (must be ≥ current rows)
758
+ * @param newCols - Target number of columns (must be ≥ current columns)
759
+ * @returns {IMatrix} The padded matrix with dimensions newRows×newCols
760
+ * @throws {Error} If new dimensions are smaller than current dimensions
761
+ * @example
762
+ * ```typescript
763
+ * const matrix = [[1, 2], [3, 4]]; // 2×2 matrix
764
+ *
765
+ * // Pad to 4×4 matrix (symmetric padding)
766
+ * MatrixPad(matrix, 4, 4)
767
+ * // Returns:
768
+ * // [[1, 2, 0, 0],
769
+ * // [3, 4, 0, 0],
770
+ * // [0, 0, 0, 0],
771
+ * // [0, 0, 0, 0]]
772
+ *
773
+ * // Pad to 3×4 matrix (asymmetric padding)
774
+ * MatrixPad(matrix, 3, 4)
775
+ * // Returns:
776
+ * // [[1, 2, 0, 0],
777
+ * // [3, 4, 0, 0],
778
+ * // [0, 0, 0, 0]]
779
+ *
780
+ * // Prepare for power-of-2 algorithm (e.g., FFT-based convolution)
781
+ * const data = [[1, 2, 3], [4, 5, 6]]; // 2×3 matrix
782
+ * const powerOf2 = MatrixPad(data, 4, 4); // Pad to 4×4 for FFT
783
+ *
784
+ * // Batch size alignment in machine learning
785
+ * const features = MatrixCreate(7, 10); // 7 samples, 10 features
786
+ * const aligned = MatrixPad(features, 8, 10); // Align to batch size 8
787
+ *
788
+ * // Image border padding for convolution
789
+ * const image = MatrixCreate(28, 28); // 28×28 image
790
+ * const padded = MatrixPad(image, 32, 32); // Add border for valid convolution
791
+ * ```
792
+ */
793
+ export function MatrixPad(matrix, newRows, newCols) {
794
+ AssertMatrix(matrix);
795
+ const [currentRows, currentCols] = MatrixSize(matrix);
796
+ const result = MatrixCreate(newRows, newCols);
797
+ // Copy existing values to top-left corner, zero-fill remaining positions
798
+ for (let row = 0; row < Math.min(currentRows, newRows); row++) {
799
+ const sourceRow = matrix[row];
800
+ AssertMatrixRow(sourceRow);
801
+ const resultRow = result[row];
802
+ AssertMatrixRow(resultRow);
803
+ for (let col = 0; col < Math.min(currentCols, newCols); col++) {
804
+ const val = sourceRow[col];
805
+ AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
806
+ resultRow[col] = val;
807
+ }
808
+ }
809
+ return result;
810
+ }
811
+ /**
812
+ * Combines four square submatrices into a single matrix (2×2 block structure).
813
+ *
814
+ * This function reconstructs a larger matrix from four quadrant submatrices using
815
+ * a 2×2 block structure. It serves as the inverse operation of matrix partitioning
816
+ * and is essential for divide-and-conquer algorithms like Strassen multiplication,
817
+ * block matrix operations, and hierarchical matrix constructions.
818
+ *
819
+ * **Block Matrix Structure:**
820
+ * ```
821
+ * Result = [C11 C12] where each Cij is an n×n submatrix
822
+ * [C21 C22]
823
+ * ```
824
+ *
825
+ * The resulting matrix has dimensions 2n×2n when each input quadrant is n×n.
826
+ *
827
+ * **Quadrant Placement:**
828
+ * - c11 (top-left): positioned at [0:n, 0:n]
829
+ * - c12 (top-right): positioned at [0:n, n:2n]
830
+ * - c21 (bottom-left): positioned at [n:2n, 0:n]
831
+ * - c22 (bottom-right): positioned at [n:2n, n:2n]
832
+ *
833
+ * **Applications:**
834
+ * - Strassen algorithm result reconstruction
835
+ * - Block matrix operations and algebra
836
+ * - Hierarchical matrix assembly (multigrid methods)
837
+ * - Sparse matrix construction from dense blocks
838
+ * - Parallel matrix computation result merging
839
+ * - Image processing (combining processed image quadrants)
840
+ * - Scientific computing (domain decomposition methods)
841
+ *
842
+ * **Validation Requirements:**
843
+ * - All four input matrices must be square
844
+ * - All four input matrices must have identical dimensions
845
+ * - All elements must be valid numbers
846
+ * - No null or undefined matrices allowed
847
+ *
848
+ * **Memory Layout:**
849
+ * The function performs efficient copying by iterating through each quadrant
850
+ * sequentially, minimizing cache misses and ensuring optimal memory access patterns.
851
+ *
852
+ * **Time Complexity:** O(n²) where n is the dimension of each input quadrant
853
+ * **Space Complexity:** O(4n²) for the combined result matrix
854
+ *
855
+ * @param c11 - Top-left quadrant (upper-left block)
856
+ * @param c12 - Top-right quadrant (upper-right block)
857
+ * @param c21 - Bottom-left quadrant (lower-left block)
858
+ * @param c22 - Bottom-right quadrant (lower-right block)
859
+ * @returns {IMatrix} The combined matrix with dimensions 2n×2n (where each input is n×n)
860
+ * @throws {Error} If quadrants have mismatched dimensions or invalid values
861
+ *
862
+ * @example
863
+ * ```typescript
864
+ * // Basic 2×2 quadrant combination
865
+ * const topLeft = [[1, 2], [3, 4]];
866
+ * const topRight = [[5, 6], [7, 8]];
867
+ * const bottomLeft = [[9, 10], [11, 12]];
868
+ * const bottomRight = [[13, 14], [15, 16]];
869
+ *
870
+ * MatrixCombine(topLeft, topRight, bottomLeft, bottomRight)
871
+ * // Returns:
872
+ * // [[1, 2, 5, 6],
873
+ * // [3, 4, 7, 8],
874
+ * // [9, 10, 13, 14],
875
+ * // [11,12, 15, 16]]
876
+ *
877
+ * // Strassen algorithm result reconstruction
878
+ * const m1 = computeStrassenProduct1(); // Computed Strassen intermediate results
879
+ * const m2 = computeStrassenProduct2();
880
+ * const m3 = computeStrassenProduct3();
881
+ * const m4 = computeStrassenProduct4();
882
+ * const finalResult = MatrixCombine(m1, m2, m3, m4); // Assemble final result
883
+ *
884
+ * // Image processing: combining processed quadrants
885
+ * const processedTopLeft = processImageQuadrant(imageTopLeft);
886
+ * const processedTopRight = processImageQuadrant(imageTopRight);
887
+ * const processedBottomLeft = processImageQuadrant(imageBottomLeft);
888
+ * const processedBottomRight = processImageQuadrant(imageBottomRight);
889
+ * const reconstructedImage = MatrixCombine(
890
+ * processedTopLeft, processedTopRight,
891
+ * processedBottomLeft, processedBottomRight
892
+ * );
893
+ * ```
894
+ */
895
+ export function MatrixCombine(c11, c12, c21, c22) {
896
+ AssertMatrix(c11);
897
+ AssertMatrix(c12);
898
+ AssertMatrix(c21);
899
+ AssertMatrix(c22);
900
+ const [qrows, _qcols] = MatrixSize(c11);
901
+ const halfSize = qrows;
902
+ const fullSize = halfSize * 2;
903
+ const result = MatrixCreate(fullSize, fullSize);
904
+ // Copy c11 to top-left quadrant [0:n, 0:n]
905
+ for (let row = 0; row < halfSize; row++) {
906
+ const sourceRow = c11[row];
907
+ AssertMatrixRow(sourceRow);
908
+ const resultRow = result[row];
909
+ AssertMatrixRow(resultRow);
910
+ for (let col = 0; col < halfSize; col++) {
911
+ const val = sourceRow[col];
912
+ AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
913
+ resultRow[col] = val;
914
+ }
915
+ }
916
+ // Copy c12 to top-right quadrant [0:n, n:2n]
917
+ for (let row = 0; row < halfSize; row++) {
918
+ const sourceRow = c12[row];
919
+ AssertMatrixRow(sourceRow);
920
+ const resultRow = result[row];
921
+ AssertMatrixRow(resultRow);
922
+ for (let col = 0; col < halfSize; col++) {
923
+ const val = sourceRow[col];
924
+ AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
925
+ resultRow[col + halfSize] = val;
926
+ }
927
+ }
928
+ // Copy c21 to bottom-left quadrant [n:2n, 0:n]
929
+ for (let row = 0; row < halfSize; row++) {
930
+ const sourceRow = c21[row];
931
+ AssertMatrixRow(sourceRow);
932
+ const resultRow = result[row + halfSize];
933
+ AssertMatrixRow(resultRow);
934
+ for (let col = 0; col < halfSize; col++) {
935
+ const val = sourceRow[col];
936
+ AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
937
+ resultRow[col] = val;
938
+ }
939
+ }
940
+ // Copy c22 to bottom-right quadrant [n:2n, n:2n]
941
+ for (let row = 0; row < halfSize; row++) {
942
+ const sourceRow = c22[row];
943
+ AssertMatrixRow(sourceRow);
944
+ const resultRow = result[row + halfSize];
945
+ AssertMatrixRow(resultRow);
946
+ for (let col = 0; col < halfSize; col++) {
947
+ const val = sourceRow[col];
948
+ AssertMatrixValue(val, { rowIndex: row, columnIndex: col });
949
+ resultRow[col + halfSize] = val;
950
+ }
951
+ }
952
+ return result;
953
+ }
954
+ //# sourceMappingURL=arithmetic.js.map