0
# Matrix Operations and Linear Algebra
1
2
This document covers Math.js's comprehensive matrix operations and linear algebra capabilities. Math.js supports both dense and sparse matrices with a rich set of operations for matrix creation, manipulation, decomposition, and linear system solving.
3
4
## Import
5
6
```typescript
7
import {
8
// Matrix creation
9
matrix, sparse, identity, ones, zeros, diag, range,
10
// Matrix properties
11
size, transpose, trace, det, inv, rank,
12
// Matrix operations
13
multiply, add, subtract, dot, cross, kron,
14
// Decompositions
15
lup, qr, slu, eigs, schur,
16
// Linear systems
17
lusolve, lsolve, usolve, sylvester, lyap,
18
// Matrix functions
19
expm, sqrtm,
20
// Manipulation
21
reshape, resize, squeeze, flatten, concat, subset,
22
// Functional operations
23
map, forEach, filter, sort
24
} from 'mathjs'
25
```
26
27
## Matrix Creation
28
29
### Creating Matrices from Data
30
31
```typescript
32
matrix(data: MathArray | Matrix, format?: 'dense' | 'sparse', dataType?: string): Matrix
33
```
34
{ .api }
35
36
```typescript
37
// From nested arrays
38
const A = matrix([[1, 2], [3, 4]])
39
const B = matrix([1, 2, 3, 4]) // 1D array becomes column vector
40
41
// Specify format
42
const dense = matrix([[1, 2], [3, 4]], 'dense')
43
const sparse = matrix([[1, 0, 0], [0, 2, 0], [0, 0, 3]], 'sparse')
44
45
// With data type
46
const int32Matrix = matrix([[1, 2], [3, 4]], 'dense', 'int32')
47
const complexMatrix = matrix([[complex(1,2), complex(3,4)]])
48
```
49
50
### Sparse Matrices
51
52
```typescript
53
sparse(data?: MathArray, dataType?: string): Matrix
54
```
55
{ .api }
56
57
```typescript
58
// Create sparse matrix
59
const sparseA = sparse([[1, 0, 0], [0, 2, 0], [0, 0, 3]])
60
61
// Efficient for matrices with many zeros
62
const largeSparse = sparse()
63
largeSparse.set([0, 0], 5)
64
largeSparse.set([100, 100], 10) // Only non-zero elements stored
65
```
66
67
### Special Matrices
68
69
```typescript
70
identity(size: number | number[], format?: 'dense' | 'sparse'): Matrix
71
ones(size: number | number[], format?: 'dense' | 'sparse'): Matrix
72
zeros(size: number | number[], format?: 'dense' | 'sparse'): Matrix
73
```
74
{ .api }
75
76
```typescript
77
// Identity matrices
78
identity(3) // 3x3 identity matrix
79
identity([2, 3]) // 2x3 rectangular "identity" (ones on diagonal)
80
81
// Matrices of ones and zeros
82
ones(3) // 3x3 matrix of ones
83
ones([2, 4]) // 2x4 matrix of ones
84
zeros([3, 2]) // 3x2 matrix of zeros
85
86
// Sparse versions (memory efficient for large matrices)
87
identity(1000, 'sparse') // 1000x1000 sparse identity
88
```
89
90
### Diagonal Matrices
91
92
```typescript
93
diag(X: MathCollection, k?: number, format?: 'dense' | 'sparse'): Matrix
94
```
95
{ .api }
96
97
```typescript
98
// Create diagonal matrix from vector
99
diag([1, 2, 3]) // Matrix with 1,2,3 on main diagonal
100
101
// Extract diagonal from matrix
102
const A = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
103
diag(A) // [1, 5, 9] - main diagonal
104
diag(A, 1) // [2, 6] - super-diagonal
105
diag(A, -1) // [4, 8] - sub-diagonal
106
107
// Create matrix with offset diagonal
108
diag([1, 2], 1) // Super-diagonal matrix
109
```
110
111
### Range and Sequences
112
113
```typescript
114
range(start: MathType, end: MathType, step?: MathType, includeEnd?: boolean): Matrix
115
```
116
{ .api }
117
118
```typescript
119
// Create ranges (useful for indexing and plotting)
120
range(0, 10) // [0, 1, 2, ..., 9] (excludeEnd by default)
121
range(0, 10, true) // [0, 1, 2, ..., 10] (includeEnd)
122
range(0, 10, 2) // [0, 2, 4, 6, 8]
123
range(10, 0, -1) // [10, 9, 8, ..., 1]
124
125
// With different number types
126
range(bignumber('0'), bignumber('5')) // BigNumber range
127
range(0, 2*pi, pi/4) // Useful for trigonometric functions
128
```
129
130
## Matrix Properties and Information
131
132
### Size and Dimensions
133
134
```typescript
135
size(x: MathCollection): number[]
136
```
137
{ .api }
138
139
```typescript
140
const A = matrix([[1, 2, 3], [4, 5, 6]])
141
size(A) // [2, 3] - 2 rows, 3 columns
142
143
const vector = matrix([1, 2, 3, 4])
144
size(vector) // [4] - 1D array/vector
145
146
const scalar = 5
147
size(scalar) // [] - scalar has no dimensions
148
```
149
150
### Transpose
151
152
```typescript
153
transpose(x: MathCollection): MathCollection
154
```
155
{ .api }
156
157
```typescript
158
const A = matrix([[1, 2, 3], [4, 5, 6]])
159
transpose(A) // [[1, 4], [2, 5], [3, 6]]
160
161
// Conjugate transpose for complex matrices
162
const C = matrix([[complex(1, 2), complex(3, 4)]])
163
transpose(C) // Conjugate transpose: [[complex(1, -2)], [complex(3, -4)]]
164
```
165
166
### Determinant
167
168
```typescript
169
det(x: MathCollection): MathType
170
```
171
{ .api }
172
173
```typescript
174
const A = matrix([[1, 2], [3, 4]])
175
det(A) // -2
176
177
const B = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
178
det(B) // 0 (singular matrix)
179
180
// Works with any square matrix size
181
const large = identity(100)
182
det(large) // 1
183
```
184
185
### Trace
186
187
```typescript
188
trace(x: MathCollection): MathType
189
```
190
{ .api }
191
192
```typescript
193
const A = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
194
trace(A) // 1 + 5 + 9 = 15 (sum of diagonal elements)
195
196
trace(identity(3)) // 3
197
```
198
199
### Matrix Inverse
200
201
```typescript
202
inv(x: MathCollection): MathCollection
203
```
204
{ .api }
205
206
```typescript
207
const A = matrix([[1, 2], [3, 4]])
208
const Ainv = inv(A) // [[-2, 1], [1.5, -0.5]]
209
210
// Verify: A * A^(-1) = I
211
multiply(A, Ainv) // ≈ [[1, 0], [0, 1]]
212
213
// Throws error for singular matrices
214
const singular = matrix([[1, 2], [2, 4]])
215
// inv(singular) // Error: Matrix is not invertible
216
```
217
218
### Pseudoinverse
219
220
```typescript
221
pinv(x: MathCollection): MathCollection
222
```
223
{ .api }
224
225
```typescript
226
// Moore-Penrose pseudoinverse (works for non-square matrices)
227
const A = matrix([[1, 2], [3, 4], [5, 6]]) // 3x2 matrix
228
const Aplus = pinv(A) // 2x3 pseudoinverse
229
230
// For full-rank matrices: A^+ = (A'A)^(-1)A'
231
// Useful for least-squares solutions
232
```
233
234
## Matrix Operations
235
236
### Matrix Multiplication
237
238
```typescript
239
multiply(x: MathCollection, y: MathCollection): MathCollection
240
```
241
{ .api }
242
243
```typescript
244
const A = matrix([[1, 2], [3, 4]])
245
const B = matrix([[5, 6], [7, 8]])
246
247
multiply(A, B) // [[19, 22], [43, 50]] - matrix multiplication
248
249
// Matrix-vector multiplication
250
const v = matrix([1, 2])
251
multiply(A, v) // [5, 11] - A * v
252
253
// Scalar multiplication
254
multiply(A, 2) // [[2, 4], [6, 8]]
255
```
256
257
### Element-wise Operations
258
See [Arithmetic Operations](arithmetic.md) for `dotMultiply`, `dotDivide`, `dotPow`.
259
260
### Dot and Cross Products
261
262
```typescript
263
dot(x: MathCollection, y: MathCollection): MathType
264
cross(x: MathCollection, y: MathCollection): MathCollection
265
```
266
{ .api }
267
268
```typescript
269
// Dot product (inner product)
270
const u = [1, 2, 3]
271
const v = [4, 5, 6]
272
dot(u, v) // 1*4 + 2*5 + 3*6 = 32
273
274
// Cross product (3D vectors only)
275
const a = [1, 0, 0]
276
const b = [0, 1, 0]
277
cross(a, b) // [0, 0, 1]
278
279
// Cross product properties
280
cross(a, a) // [0, 0, 0] (parallel vectors)
281
cross(a, b) === multiply(-1, cross(b, a)) // Anti-commutative
282
```
283
284
### Kronecker Product
285
286
```typescript
287
kron(x: MathCollection, y: MathCollection): MathCollection
288
```
289
{ .api }
290
291
```typescript
292
const A = matrix([[1, 2], [3, 4]])
293
const B = matrix([[5, 6], [7, 8]])
294
295
// Kronecker product A ⊗ B
296
kron(A, B)
297
// [[5, 6, 10, 12],
298
// [7, 8, 14, 16],
299
// [15, 18, 20, 24],
300
// [21, 24, 28, 32]]
301
302
// Useful for solving matrix equations
303
```
304
305
## Matrix Decompositions
306
307
### LU Decomposition with Pivoting
308
309
```typescript
310
lup(A: MathCollection): { L: Matrix, U: Matrix, p: number[] }
311
```
312
{ .api }
313
314
```typescript
315
const A = matrix([[2, 1, 1], [4, 3, 3], [8, 7, 9]])
316
const { L, U, p } = lup(A)
317
318
// L: Lower triangular, U: Upper triangular, p: permutation vector
319
// P*A = L*U where P is permutation matrix from p
320
321
// Verify decomposition
322
const P = zeros(3, 3)
323
p.forEach((row, col) => P.set([row, col], 1))
324
// multiply(P, A) ≈ multiply(L, U)
325
```
326
327
### QR Decomposition
328
329
```typescript
330
qr(A: MathCollection): { Q: Matrix, R: Matrix }
331
```
332
{ .api }
333
334
```typescript
335
const A = matrix([[1, 2], [3, 4], [5, 6]]) // 3x2 matrix
336
const { Q, R } = qr(A)
337
338
// Q: Orthogonal matrix (3x2), R: Upper triangular (2x2)
339
// A = Q * R
340
341
// Q has orthonormal columns
342
// dot(Q.column(0), Q.column(1)) ≈ 0 (orthogonal)
343
```
344
345
### Sparse LU Decomposition
346
347
```typescript
348
slu(A: Matrix, order: number, threshold: number): { L: Matrix, U: Matrix, p: number[], q: number[] }
349
```
350
{ .api }
351
352
```typescript
353
const A = sparse([[2, 1, 0], [1, 2, 1], [0, 1, 2]])
354
const { L, U, p, q } = slu(A, 1, 0.001)
355
356
// Optimized for sparse matrices
357
// P*A*Q = L*U with row and column permutations
358
```
359
360
### Eigenvalue Decomposition
361
362
```typescript
363
eigs(x: MathCollection, options?: { precision?: number | BigNumber, eigenvectors?: boolean }):
364
{ values: MathCollection, eigenvectors?: Array<{value: MathType, vector: MathCollection}> }
365
```
366
{ .api }
367
368
```typescript
369
interface EigsOptions {
370
eigenvectors?: boolean // default: true
371
precision?: number // default: 1e-12
372
maxIterations?: number // default: 100
373
}
374
```
375
376
```typescript
377
const A = matrix([[1, 2], [2, 1]])
378
const { values, vectors } = eigs(A)
379
380
// values: eigenvalues [3, -1]
381
// vectors: eigenvectors as columns [[0.707, 0.707], [0.707, -0.707]]
382
383
// Verify: A * v = λ * v
384
const v1 = column(vectors, 0)
385
const lambda1 = values.get([0])
386
// multiply(A, v1) ≈ multiply(lambda1, v1)
387
```
388
389
### Schur Decomposition
390
391
```typescript
392
schur(A: MathCollection): { T: Matrix, Z: Matrix }
393
```
394
{ .api }
395
396
```typescript
397
const A = matrix([[1, 2, 3], [0, 4, 5], [0, 0, 6]])
398
const { T, Z } = schur(A)
399
400
// T: Upper triangular (Schur form)
401
// Z: Orthogonal matrix
402
// A = Z * T * Z'
403
```
404
405
## Linear System Solving
406
407
### General Linear Systems
408
409
```typescript
410
lusolve(A: MathCollection, b: MathCollection, order?: number, threshold?: number): MathCollection
411
```
412
{ .api }
413
414
```typescript
415
// Solve A*x = b
416
const A = matrix([[2, 1], [1, 1]])
417
const b = matrix([3, 2])
418
419
const x = lusolve(A, b) // [1, 1]
420
421
// Verify solution
422
multiply(A, x) // Should equal b
423
424
// Multiple right-hand sides
425
const B = matrix([[3, 5], [2, 3]]) // Each column is a RHS
426
const X = lusolve(A, B) // Each column is a solution
427
```
428
429
### Triangular Systems
430
431
```typescript
432
lsolve(L: MathCollection, b: MathCollection): MathCollection // Lower triangular
433
usolve(U: MathCollection, b: MathCollection): MathCollection // Upper triangular
434
```
435
{ .api }
436
437
```typescript
438
// Lower triangular system L*x = b
439
const L = matrix([[1, 0], [2, 1]])
440
const b = matrix([1, 3])
441
const x = lsolve(L, b) // [1, 1]
442
443
// Upper triangular system U*x = b
444
const U = matrix([[1, 2], [0, 1]])
445
const y = usolve(U, b) // [-1, 3]
446
```
447
448
### Sylvester Equation
449
450
```typescript
451
sylvester(A: MathCollection, B: MathCollection, C: MathCollection): MathCollection
452
```
453
{ .api }
454
455
```typescript
456
// Solve A*X + X*B = C
457
const A = matrix([[1, 2], [3, 4]])
458
const B = matrix([[1, 1], [0, 1]])
459
const C = matrix([[1, 0], [0, 1]])
460
461
const X = sylvester(A, B, C)
462
// Verify: add(multiply(A, X), multiply(X, B)) ≈ C
463
```
464
465
### Lyapunov Equation
466
467
```typescript
468
lyap(A: MathCollection, Q: MathCollection): MathCollection
469
```
470
{ .api }
471
472
```typescript
473
// Solve A*P + P*A' = Q (continuous-time Lyapunov equation)
474
const A = matrix([[-1, 2], [0, -3]])
475
const Q = matrix([[1, 0], [0, 1]])
476
477
const P = lyap(A, Q)
478
// Used in control theory and stability analysis
479
```
480
481
## Matrix Functions
482
483
### Matrix Exponential
484
485
```typescript
486
expm(x: MathCollection): MathCollection
487
```
488
{ .api }
489
490
```typescript
491
// Matrix exponential: e^A = I + A + A^2/2! + A^3/3! + ...
492
const A = matrix([[0, 1], [-1, 0]]) // Rotation matrix generator
493
494
const eA = expm(A) // Matrix exponential
495
// For this A, expm(A) is a rotation matrix
496
497
// Properties:
498
// expm(0) = I
499
// expm(A + B) = expm(A) * expm(B) if A and B commute
500
```
501
502
### Matrix Square Root
503
504
```typescript
505
sqrtm(x: MathCollection): MathCollection
506
```
507
{ .api }
508
509
```typescript
510
// Matrix square root: sqrtm(A)^2 = A
511
const A = matrix([[4, 2], [2, 4]])
512
const sqrtA = sqrtm(A)
513
514
multiply(sqrtA, sqrtA) // Should equal A
515
516
// Note: Matrix square root is not unique
517
// sqrtm returns the principal square root
518
```
519
520
## Matrix Manipulation
521
522
### Reshaping and Resizing
523
524
```typescript
525
reshape(x: MathCollection, sizes: number[]): MathCollection
526
resize(x: MathCollection, size: number[], defaultValue?: MathType): MathCollection
527
```
528
{ .api }
529
530
```typescript
531
const A = matrix([1, 2, 3, 4, 5, 6])
532
533
// Reshape (total elements must match)
534
reshape(A, [2, 3]) // [[1, 2, 3], [4, 5, 6]]
535
reshape(A, [3, 2]) // [[1, 2], [3, 4], [5, 6]]
536
537
// Resize (can change total size)
538
resize(A, [2, 4]) // Pad with zeros: [[1, 2, 3, 4], [5, 6, 0, 0]]
539
resize(A, [2, 2]) // Truncate: [[1, 2], [3, 4]]
540
resize(A, [3, 3], 'x') // Pad with 'x': [[1, 2, 3], [4, 5, 6], ['x', 'x', 'x']]
541
```
542
543
### Squeezing and Flattening
544
545
```typescript
546
squeeze(x: MathCollection): MathCollection
547
flatten(x: MathCollection): Matrix
548
```
549
{ .api }
550
551
```typescript
552
// Remove singleton dimensions
553
const A = matrix([[[1], [2], [3]]]) // Shape: [1, 3, 1]
554
squeeze(A) // Shape: [3] - removed singleton dims
555
556
// Flatten to 1D
557
const B = matrix([[1, 2], [3, 4]])
558
flatten(B) // [1, 2, 3, 4]
559
```
560
561
### Concatenation
562
563
```typescript
564
concat(...arrays: MathCollection[]): MathCollection
565
```
566
{ .api }
567
568
```typescript
569
const A = matrix([[1, 2], [3, 4]])
570
const B = matrix([[5, 6], [7, 8]])
571
572
// Concatenate along first dimension (rows)
573
concat(A, B) // [[1, 2], [3, 4], [5, 6], [7, 8]]
574
575
// Concatenate along second dimension (columns)
576
concat(A, B, 1) // [[1, 2, 5, 6], [3, 4, 7, 8]]
577
```
578
579
### Indexing and Subsets
580
581
```typescript
582
subset(matrix: MathCollection, index: Index, replacement?: MathType, defaultValue?: MathType): MathCollection | MathType
583
```
584
{ .api }
585
586
```typescript
587
const A = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
588
589
// Get subset
590
subset(A, index(1, 2)) // 6 (element at row 1, col 2)
591
subset(A, index(range(0, 2), 1)) // [2, 5] (column 1, rows 0-1)
592
593
// Set subset
594
subset(A, index(1, 1), 99) // Replace A[1,1] with 99
595
subset(A, index(range(0, 2), range(0, 2)), zeros(2, 2)) // Replace 2x2 block
596
```
597
598
## Functional Operations on Matrices
599
600
### Mapping Functions
601
602
```typescript
603
map(array: MathCollection, callback: (value: MathType, index: number[], matrix: MathCollection) => MathType): MathCollection
604
```
605
{ .api }
606
607
```typescript
608
const A = matrix([[1, 2], [3, 4]])
609
610
// Apply function to each element
611
map(A, (x) => multiply(x, x)) // [[1, 4], [9, 16]]
612
map(A, (x, index) => add(x, index[0] + index[1])) // Add row+col to each element
613
614
// With index information
615
map(A, (value, [row, col]) => row === col ? value : 0) // Keep only diagonal
616
```
617
618
### Iterating Over Elements
619
620
```typescript
621
forEach(array: MathCollection, callback: (value: MathType, index: number[], matrix: MathCollection) => void): void
622
```
623
{ .api }
624
625
```typescript
626
const A = matrix([[1, 2], [3, 4]])
627
628
forEach(A, (value, index) => {
629
console.log(`A[${index.join(',')}] = ${value}`)
630
})
631
// Output:
632
// A[0,0] = 1
633
// A[0,1] = 2
634
// A[1,0] = 3
635
// A[1,1] = 4
636
```
637
638
### Filtering Elements
639
640
```typescript
641
filter(array: MathCollection, test: (value: MathType, index: number[], matrix: MathCollection) => boolean): MathCollection
642
```
643
{ .api }
644
645
```typescript
646
const A = matrix([1, -2, 3, -4, 5])
647
648
// Keep only positive elements
649
filter(A, (x) => larger(x, 0)) // [1, 3, 5]
650
651
// Filter 2D matrix
652
const B = matrix([[1, -2], [3, -4]])
653
filter(B, (x) => larger(x, 0)) // [1, 3] (flattened result)
654
```
655
656
### Sorting Arrays
657
658
```typescript
659
sort(array: MathCollection, compare?: (a: MathType, b: MathType) => number): MathCollection
660
```
661
{ .api }
662
663
```typescript
664
const A = matrix([3, 1, 4, 1, 5, 9, 2, 6])
665
666
sort(A) // [1, 1, 2, 3, 4, 5, 6, 9] (ascending)
667
668
// Custom comparison
669
sort(A, (a, b) => subtract(b, a)) // [9, 6, 5, 4, 3, 2, 1, 1] (descending)
670
671
// Sort complex numbers by magnitude
672
const C = matrix([complex(3, 4), complex(1, 1), complex(0, 2)])
673
sort(C, (a, b) => subtract(abs(a), abs(b))) // Sort by magnitude
674
```
675
676
### Partition Select (Quickselect)
677
678
```typescript
679
partitionSelect(array: MathCollection, k: number, compare?: (a: MathType, b: MathType) => number): MathType
680
```
681
{ .api }
682
683
```typescript
684
const A = matrix([3, 1, 4, 1, 5, 9, 2, 6])
685
686
// Find k-th smallest element (0-indexed)
687
partitionSelect(A, 0) // 1 (minimum)
688
partitionSelect(A, 3) // 3 (4th smallest)
689
partitionSelect(A, 7) // 9 (maximum, i.e., 8th smallest)
690
691
// Find median
692
const n = size(A)[0]
693
partitionSelect(A, floor(n/2)) // Median for odd-length arrays
694
```
695
696
## Working with Slices
697
698
```typescript
699
// Extract rows, columns, or sub-matrices
700
function getColumn(matrix, col) {
701
return subset(matrix, index(range(0, size(matrix)[0]), col))
702
}
703
704
function getRow(matrix, row) {
705
return subset(matrix, index(row, range(0, size(matrix)[1])))
706
}
707
708
function getBlock(matrix, rows, cols) {
709
return subset(matrix, index(rows, cols))
710
}
711
712
const A = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
713
getColumn(A, 1) // [2, 5, 8]
714
getRow(A, 0) // [1, 2, 3]
715
getBlock(A, range(0, 2), range(1, 3)) // [[2, 3], [5, 6]]
716
```
717
718
## Performance Considerations
719
720
### Dense vs Sparse Matrices
721
```typescript
722
// Use sparse for matrices with >80% zeros
723
const dense = matrix(largeDenseArray) // Better for dense data
724
const sparse = sparse(largeSparseArray) // Better for sparse data
725
726
// Sparse operations are optimized
727
const result = multiply(sparseA, sparseB) // Efficient sparse multiplication
728
```
729
730
### Memory Management
731
```typescript
732
// Clone matrices when needed to avoid side effects
733
const A = matrix([[1, 2], [3, 4]])
734
const B = clone(A) // Independent copy
735
736
// Use views when possible (subset operations)
737
const view = subset(A, index(range(0, 2), range(0, 2))) // May return view
738
```
739
740
### Batch Operations
741
```typescript
742
// Process multiple matrices efficiently
743
const matrices = [A, B, C]
744
const results = matrices.map(M => multiply(M, commonMatrix))
745
746
// Use vectorized operations
747
map(A, x => multiply(x, 2)) // Faster than element-by-element loops
748
```
749
750
## Common Linear Algebra Patterns
751
752
### Solving Linear Least Squares
753
```typescript
754
// Solve min ||Ax - b||² (overdetermined system)
755
function leastSquares(A, b) {
756
// Normal equation: A'Ax = A'b
757
const AtA = multiply(transpose(A), A)
758
const Atb = multiply(transpose(A), b)
759
return lusolve(AtA, Atb)
760
}
761
762
// Or using pseudoinverse
763
function leastSquaresPseudo(A, b) {
764
return multiply(pinv(A), b)
765
}
766
```
767
768
### Matrix Norms and Condition Numbers
769
```typescript
770
import { norm } from 'mathjs'
771
772
const A = matrix([[1, 2], [3, 4]])
773
774
// Matrix norms
775
norm(A) // Frobenius norm (default)
776
norm(A, 'fro') // Frobenius norm
777
norm(A, 1) // 1-norm (max column sum)
778
norm(A, Infinity) // ∞-norm (max row sum)
779
780
// Condition number (for numerical stability)
781
const condA = multiply(norm(A), norm(inv(A))) // cond(A) = ||A|| * ||A^(-1)||
782
```
783
784
### Gram-Schmidt Orthogonalization
785
```typescript
786
// Orthogonalize columns of matrix
787
function gramSchmidt(A) {
788
const [m, n] = size(A)
789
const Q = zeros(m, n)
790
791
for (let j = 0; j < n; j++) {
792
let v = subset(A, index(range(0, m), j))
793
794
// Subtract projections onto previous columns
795
for (let i = 0; i < j; i++) {
796
const qi = subset(Q, index(range(0, m), i))
797
const proj = multiply(dot(v, qi), qi)
798
v = subtract(v, proj)
799
}
800
801
// Normalize
802
const qj = divide(v, norm(v))
803
Q = subset(Q, index(range(0, m), j), qj, undefined)
804
}
805
806
return Q
807
}
808
```