@danielsimonjr/mathts-functions 0.34.0 → 0.35.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.
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Control-theory matrix equations — `dlyap`/`care`/`dare`.
3
+ *
4
+ * These solve the algebraic matrix equations that underlie LQR (linear-
5
+ * quadratic regulator) and Kalman-filter design:
6
+ *
7
+ * - {@link dlyap} — discrete Lyapunov equation `A X Aᵀ − X + Q = 0`, solved
8
+ * directly via the Kronecker-product linear system
9
+ * `(I − A⊗A) vec(X) = vec(Q)` (exact for the small `n` this targets;
10
+ * the codebase's `linsolve` does the O(n²)³ = O(n⁶) dense solve).
11
+ * - {@link care} — continuous algebraic Riccati equation
12
+ * `AᵀX + XA − X B R⁻¹ Bᵀ X + Q = 0`, solved via the **matrix sign
13
+ * function** applied to the Hamiltonian `H = [[A, −BR⁻¹Bᵀ], [−Q, −Aᵀ]]`.
14
+ * This avoids both complex eigenvectors (this codebase's `eig` only
15
+ * returns real eigenvector columns — see `matrix-functions.ts` — so a
16
+ * Hamiltonian-eigenvector approach isn't usable here) and the need for a
17
+ * stabilizing initial gain that a Kleinman/Newton iteration would
18
+ * require (the natural starting point `X₀ = 0` is not stabilizing for
19
+ * e.g. the classic double-integrator `A = [[0,1],[0,0]]`, which is only
20
+ * marginally stable). The sign-function Newton iteration converges
21
+ * unconditionally (given the standard stabilizability/detectability
22
+ * assumptions) directly from `H` itself.
23
+ * - {@link dare} — discrete algebraic Riccati equation
24
+ * `AᵀXA − X − AᵀXB(R + BᵀXB)⁻¹BᵀXA + Q = 0`, solved via the
25
+ * **structure-preserving doubling algorithm** (SDA), the discrete-time
26
+ * analogue of the sign-function method above: it iterates a triple
27
+ * `(Aₖ, Gₖ, Hₖ)` with quadratic convergence and, likewise, needs no
28
+ * stabilizing initial gain.
29
+ *
30
+ * All three return the (numerically symmetrized) stabilizing solution `X`.
31
+ * Both `care`/`dare` require `R` invertible and `(A, B)` stabilizable — the
32
+ * standard LQR well-posedness assumptions.
33
+ *
34
+ * @packageDocumentation
35
+ */
36
+ /**
37
+ * Solve the discrete-time Lyapunov (Stein) equation `A X Aᵀ − X + Q = 0` for
38
+ * `X`, given square `A` and `Q` of the same size.
39
+ *
40
+ * Builds the Kronecker-product linear system `(I − A⊗A) vec(X) = vec(Q)`
41
+ * explicitly (practical for the `n ≲ 20` this targets — the system has
42
+ * `n²` unknowns) and solves it with `linsolve`.
43
+ *
44
+ * @example
45
+ * dlyap([[0.5, 0], [0, 0.5]], [[1, 0], [0, 1]]) // => (4/3) * I (since 0.25x - x + 1 = 0)
46
+ */
47
+ export declare function dlyap(A: number[][], Q: number[][]): number[][];
48
+ /**
49
+ * Solve the continuous-time algebraic Riccati equation (CARE)
50
+ * `AᵀX + XA − X B R⁻¹ Bᵀ X + Q = 0` for the stabilizing symmetric `X`,
51
+ * given `A` (n×n), `B` (n×m), `Q` (n×n, typically PSD), `R` (m×m, invertible).
52
+ *
53
+ * Method: Newton iteration for the **matrix sign function** of the
54
+ * Hamiltonian `H = [[A, −BR⁻¹Bᵀ], [−Q, −Aᵀ]]` (2n×2n):
55
+ *
56
+ * `Zₖ₊₁ = ½(cₖ Zₖ + cₖ⁻¹ Zₖ⁻¹)`, `Z₀ = H`, `cₖ = √(‖Zₖ⁻¹‖₁ / ‖Zₖ‖₁)`
57
+ *
58
+ * converging quadratically to `S = sign(H)`. The projector `P = ½(I − S)`
59
+ * has range equal to `H`'s stable (Re λ < 0) invariant subspace; taking its
60
+ * first `n` columns `U = [U₁; U₂]` (split at the `n`-th row) gives
61
+ * `X = U₂ U₁⁻¹` (real arithmetic throughout — no complex eigenvectors
62
+ * needed, unlike the classical Hamiltonian-eigenvector construction).
63
+ *
64
+ * @example
65
+ * care([[0, 1], [0, 0]], [[0], [1]], [[1, 0], [0, 1]], [[1]])
66
+ * // => [[sqrt(3), 1], [1, sqrt(3)]] (pinned vs scipy.linalg.solve_continuous_are)
67
+ */
68
+ export declare function care(A: number[][], B: number[][], Q: number[][], R: number[][]): number[][];
69
+ /**
70
+ * Solve the discrete-time algebraic Riccati equation (DARE)
71
+ * `AᵀXA − X − AᵀXB(R + BᵀXB)⁻¹BᵀXA + Q = 0` for the stabilizing symmetric
72
+ * `X`, given `A` (n×n), `B` (n×m), `Q` (n×n, typically PSD), `R` (m×m,
73
+ * invertible).
74
+ *
75
+ * Method: the **structure-preserving doubling algorithm** (SDA) — the
76
+ * discrete-time analogue of the sign-function iteration used by {@link care}.
77
+ * Starting from `A₀ = A`, `G₀ = B R⁻¹ Bᵀ`, `H₀ = Q`, it iterates
78
+ *
79
+ * `Aₖ₊₁ = Aₖ(I + GₖHₖ)⁻¹Aₖ`
80
+ * `Gₖ₊₁ = Gₖ + Aₖ(I + GₖHₖ)⁻¹Gₖ Aₖᵀ`
81
+ * `Hₖ₊₁ = Hₖ + Aₖᵀ Hₖ(I + GₖHₖ)⁻¹Aₖ`
82
+ *
83
+ * with `Hₖ → X` quadratically. Like {@link care}'s sign-function method, this
84
+ * needs no stabilizing initial gain (unlike a Kleinman/Newton iteration on
85
+ * the DARE directly) — only the standard stabilizability/detectability
86
+ * assumptions.
87
+ *
88
+ * @example
89
+ * dare([[1, 1], [0, 1]], [[0], [1]], [[1, 0], [0, 1]], [[1]])
90
+ * // => [[2.94712297, 2.36920541], [2.36920541, 4.61313426]]
91
+ * // (pinned vs scipy.linalg.solve_discrete_are)
92
+ */
93
+ export declare function dare(A: number[][], B: number[][], Q: number[][], R: number[][]): number[][];
94
+ //# sourceMappingURL=control-equations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-equations.d.ts","sourceRoot":"","sources":["../../src/numeric/control-equations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAuJH;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAgB9D;AASD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CA6C3F;AAMD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CA+B3F"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Iterative symmetric eigensolver — Lanczos tridiagonalization + Rayleigh-Ritz.
3
+ *
4
+ * For large symmetric problems where the dense `eigs` (full O(n^3)
5
+ * eigendecomposition of the whole matrix) is prohibitive, `eigsh` extracts
6
+ * just the `k` largest or smallest eigenpairs. It builds an orthonormal
7
+ * Krylov basis `V` via the Lanczos iteration (with full reorthogonalization
8
+ * against every prior Lanczos vector, for numerical stability at the small
9
+ * sizes this is exercised at), forming the small tridiagonal projection
10
+ * `T = Vᵀ A V`. `T`'s eigenproblem is solved directly (cyclic Jacobi
11
+ * rotations — `T` is dense-symmetric-small by construction) and lifted back
12
+ * through `V` (Rayleigh-Ritz) to approximate `A`'s eigenpairs. Accepts either
13
+ * a dense matrix or a matvec callback (a linear operator, matching the
14
+ * `krylov.ts` convention) — the matvec form never forms `A` and requires
15
+ * `opts.n` since the dimension can't otherwise be inferred.
16
+ *
17
+ * @packageDocumentation
18
+ */
19
+ /** A symmetric linear operator: either a dense matrix or a matvec callback `x -> A x`. */
20
+ export type EigshOperatorInput = number[][] | ((x: number[]) => number[]);
21
+ /** Options accepted by {@link eigsh}. */
22
+ export interface EigshOptions {
23
+ /** Which end of the spectrum to return: `'LM'` (largest, default) or `'SM'` (smallest). */
24
+ which?: 'LM' | 'SM';
25
+ /** Dimension of `A` — required when `A` is a matvec callback. */
26
+ n?: number;
27
+ /** Convergence tolerance for diagonalizing the small tridiagonal projection (default 1e-10). */
28
+ tol?: number;
29
+ /** Maximum Lanczos steps (default `min(max(2k + 20, 20), n)`). */
30
+ maxIter?: number;
31
+ }
32
+ /**
33
+ * Result of {@link eigsh}.
34
+ *
35
+ * `eigenvectors` is an `n x k` matrix with eigenvectors stored as **columns**:
36
+ * `eigenvectors[i][j]` is the `i`-th component of the `j`-th eigenvector,
37
+ * which corresponds to `eigenvalues[j]`.
38
+ */
39
+ export interface EigshResult {
40
+ /** The `k` selected eigenvalues, ordered by `which` (largest-first for `'LM'`, smallest-first for `'SM'`). */
41
+ eigenvalues: number[];
42
+ /** The `k` corresponding eigenvectors, as columns of an `n x k` matrix. */
43
+ eigenvectors: number[][];
44
+ }
45
+ /**
46
+ * `eigsh` — the `k` largest or smallest eigenpairs of a **symmetric** matrix
47
+ * via the Lanczos iteration, for problems too large for the dense `eigs`.
48
+ *
49
+ * `A` may be a dense `number[][]` or a matvec callback `x => A x` (in which
50
+ * case `opts.n` is required — the dimension can't be inferred from a
51
+ * function). Eigenvectors are returned as **columns** of an `n x k` matrix:
52
+ * `result.eigenvectors[i][j]` is the `i`-th component of the eigenvector for
53
+ * `result.eigenvalues[j]`.
54
+ *
55
+ * @example
56
+ * eigsh([[2, 1, 0], [1, 2, 1], [0, 1, 2]], 1, { which: 'LM' })
57
+ * // => { eigenvalues: [2 + Math.SQRT2], eigenvectors: [[...]] }
58
+ */
59
+ export declare function eigsh(a: EigshOperatorInput, k?: number, opts?: EigshOptions): EigshResult;
60
+ //# sourceMappingURL=eigsh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eigsh.d.ts","sourceRoot":"","sources":["../../src/numeric/eigsh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,0FAA0F;AAC1F,MAAM,MAAM,kBAAkB,GAAG,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC;AAE1E,yCAAyC;AACzC,MAAM,WAAW,YAAY;IAC3B,2FAA2F;IAC3F,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,iEAAiE;IACjE,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,gGAAgG;IAChG,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,8GAA8G;IAC9G,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,EAAE,EAAE,CAAC;CAC1B;AAkKD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,SAAI,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,WAAW,CAmDpF"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Iterative Krylov-subspace linear solvers.
3
+ *
4
+ * For the large sparse systems a dense factorization (`lusolve`, `qr`, …)
5
+ * can't handle — none of these methods ever form or fill in `A`. Each solver
6
+ * accepts either a dense matrix or a matvec callback (a "linear operator" in
7
+ * the SciPy/Trilinos sense), plus an optional preconditioner:
8
+ *
9
+ * - `cg` — Conjugate Gradient, for symmetric positive-definite `A`.
10
+ * - `minres` — MINRES, for symmetric (possibly indefinite) `A`.
11
+ * - `gmres` — restarted GMRES, for general nonsymmetric `A`.
12
+ * - `bicgstab` — BiCGSTAB, for general nonsymmetric `A`.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ /** A linear operator: either a dense matrix or a matvec callback `x -> A x`. */
17
+ export type LinearOperatorInput = number[][] | ((x: number[]) => number[]);
18
+ /** Preconditioner: `'jacobi'` (diagonal, dense-matrix only) or a custom `M⁻¹` callback. */
19
+ export type Preconditioner = 'jacobi' | ((r: number[]) => number[]);
20
+ /** Common options accepted by every solver in this module. */
21
+ export interface KrylovOptions {
22
+ /** Initial guess (default: the zero vector). */
23
+ x0?: number[];
24
+ /** Relative-residual convergence tolerance (default 1e-10). */
25
+ tol?: number;
26
+ /** Maximum iterations (default `min(10 * n, 1000)`). */
27
+ maxIter?: number;
28
+ /** Preconditioner: `'jacobi'` or a custom `(r) => M⁻¹r` callback. */
29
+ preconditioner?: Preconditioner;
30
+ }
31
+ /** Options for {@link gmres}, adding the restart length. */
32
+ export interface GmresOptions extends KrylovOptions {
33
+ /** Restart length (default 30). */
34
+ restart?: number;
35
+ }
36
+ /** Result returned by every solver in this module. */
37
+ export interface KrylovResult {
38
+ /** Approximate solution. */
39
+ x: number[];
40
+ /** Number of iterations performed. */
41
+ iterations: number;
42
+ /** Whether the relative residual dropped below `tol`. */
43
+ converged: boolean;
44
+ /** Final relative residual `‖b − A x‖₂ / ‖b‖₂`. */
45
+ residual: number;
46
+ }
47
+ /**
48
+ * Conjugate Gradient (CG) — for symmetric positive-definite `A`.
49
+ *
50
+ * @example
51
+ * cg([[4, 1], [1, 3]], [1, 2]) // => { x: [1/11, 7/11], converged: true, ... }
52
+ */
53
+ export declare function cg(a: LinearOperatorInput, b: number[], opts?: KrylovOptions): KrylovResult;
54
+ /**
55
+ * MINRES — for symmetric (possibly indefinite) `A`.
56
+ *
57
+ * Builds the preconditioned Lanczos tridiagonalization of `A` and, at each
58
+ * step, solves the growing `(k+1) x k` tridiagonal least-squares problem
59
+ * `min ||beta1 e1 - T_k y||` via a small dense Householder QR. This is the
60
+ * textbook MINRES minimization restated directly (rather than the
61
+ * incrementally-updated Givens-rotation form), which keeps it simple to
62
+ * verify against a closed-form oracle at the cost of some redundant work
63
+ * per iteration — acceptable since `maxIter` is bounded by `min(10n, 1000)`.
64
+ *
65
+ * @example
66
+ * minres([[0, 1], [1, 0]], [1, 2]) // => { x: [2, 1], converged: true, ... }
67
+ */
68
+ export declare function minres(a: LinearOperatorInput, b: number[], opts?: KrylovOptions): KrylovResult;
69
+ /**
70
+ * Restarted GMRES — for general nonsymmetric `A`.
71
+ *
72
+ * @example
73
+ * gmres([[3, 1], [0, 2]], [4, 2]) // => { x: [1, 1], converged: true, ... }
74
+ */
75
+ export declare function gmres(a: LinearOperatorInput, b: number[], opts?: GmresOptions): KrylovResult;
76
+ /**
77
+ * BiCGSTAB — for general nonsymmetric `A`.
78
+ *
79
+ * @example
80
+ * bicgstab([[3, 1], [0, 2]], [4, 2]) // => { x: [1, 1], converged: true, ... }
81
+ */
82
+ export declare function bicgstab(a: LinearOperatorInput, b: number[], opts?: KrylovOptions): KrylovResult;
83
+ //# sourceMappingURL=krylov.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"krylov.d.ts","sourceRoot":"","sources":["../../src/numeric/krylov.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,gFAAgF;AAChF,MAAM,MAAM,mBAAmB,GAAG,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC;AAE3E,2FAA2F;AAC3F,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC;AAEpE,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,4DAA4D;AAC5D,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,CAAC,EAAE,MAAM,EAAE,CAAC;IACZ,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,SAAS,EAAE,OAAO,CAAC;IACnB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAmGD;;;;;GAKG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAwC1F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAyF9F;AA8CD;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,CA2F5F;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAqEhG"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Complex matrix functions — `funm`/`cosm`/`sinm` for a general real matrix.
3
+ *
4
+ * `funm(A, f)` evaluates a scalar analytic function `f` at a square matrix
5
+ * `A`, returning the complex matrix `f(A)`. Unlike `sqrtm`/`matrixLogm`
6
+ * (which only handle real matrices whose spectrum stays on the principal
7
+ * branch — positive reals for sqrt/log), `funm` accepts any real spectrum
8
+ * (negative, complex-conjugate pairs, …) because the result is allowed to be
9
+ * complex-valued.
10
+ *
11
+ * Algorithm (diagonalizable matrices with distinct eigenvalues):
12
+ * - If `A` is diagonal, `f(A)` is exact and trivial: apply `f` to each
13
+ * diagonal entry (handles repeated eigenvalues fine, since a diagonal
14
+ * matrix is always diagonalizable regardless of eigenvalue multiplicity).
15
+ * - Otherwise, compute `A`'s eigenvalues `λ_1, …, λ_n` (via the shared
16
+ * `@danielsimonjr/mathts-matrix` `eig` — Householder + Francis QR) and,
17
+ * when they are all distinct, apply the Lagrange-Sylvester interpolation
18
+ * formula for a diagonalizable matrix with simple spectrum:
19
+ *
20
+ * f(A) = Σ_i f(λ_i) · L_i(A), L_i(A) = Π_{j≠i} (A − λ_j I) / (λ_i − λ_j)
21
+ *
22
+ * evaluated in complex arithmetic (`A` embedded with zero imaginary
23
+ * part). This needs only eigenvalues, not eigenvectors, and is exact for
24
+ * any polynomial or entire function `f` (cos, sin, sqrt, exp, log, …)
25
+ * whenever the spectrum is simple.
26
+ *
27
+ * Limitation (documented, not yet implemented): matrices with repeated (or
28
+ * numerically indistinguishable) eigenvalues that are NOT diagonal — i.e.
29
+ * genuinely defective/non-diagonalizable matrices, or diagonalizable
30
+ * matrices with a repeated eigenvalue and off-diagonal structure — are not
31
+ * supported; `funm` throws rather than silently return a wrong answer. A
32
+ * full Schur-Parlett block recurrence (Higham 2008 Ch. 9) would lift this
33
+ * restriction; that is future work, not required by the current call sites.
34
+ *
35
+ * @packageDocumentation
36
+ */
37
+ /** A complex number as a plain `{re, im}` pair. */
38
+ export interface ComplexValue {
39
+ re: number;
40
+ im: number;
41
+ }
42
+ /** A complex-valued dense matrix, stored as parallel real/imaginary 2-D arrays. */
43
+ export interface ComplexMatrix {
44
+ re: number[][];
45
+ im: number[][];
46
+ }
47
+ /** A scalar analytic function to be applied to a matrix's spectrum. */
48
+ export type ScalarComplexFunction = (z: ComplexValue) => ComplexValue;
49
+ /**
50
+ * Evaluate the matrix function `f(A)` for a square real matrix `A`, returning
51
+ * a complex matrix `{re, im}`.
52
+ *
53
+ * Supports diagonal matrices unconditionally (exact, elementwise), and
54
+ * general diagonalizable matrices whose eigenvalues are pairwise distinct
55
+ * (Lagrange-Sylvester interpolation on the spectrum — see module docs).
56
+ * Throws for matrices with repeated or numerically indistinguishable
57
+ * eigenvalues that are not diagonal (defective / non-diagonalizable case;
58
+ * not yet supported — see module docs for the Schur-Parlett follow-up).
59
+ *
60
+ * @param A - Square real matrix, as a plain 2-D array.
61
+ * @param f - Scalar function to apply to each eigenvalue, e.g. `cos`, `sin`,
62
+ * `sqrt`, `exp`, `log`, extended to complex arguments.
63
+ * @returns `{ re, im }` — the (possibly complex) matrix `f(A)`.
64
+ */
65
+ export declare function funm(A: number[][], f: ScalarComplexFunction): ComplexMatrix;
66
+ /** Complex cosine: `cos(z) = cos(re)cosh(im) - i sin(re)sinh(im)`. */
67
+ export declare function complexCos(z: ComplexValue): ComplexValue;
68
+ /** Complex sine: `sin(z) = sin(re)cosh(im) + i cos(re)sinh(im)`. */
69
+ export declare function complexSin(z: ComplexValue): ComplexValue;
70
+ /** Matrix cosine `cos(A)`, via {@link funm} with {@link complexCos}. */
71
+ export declare function cosm(A: number[][]): ComplexMatrix;
72
+ /** Matrix sine `sin(A)`, via {@link funm} with {@link complexSin}. */
73
+ export declare function sinm(A: number[][]): ComplexMatrix;
74
+ //# sourceMappingURL=matrix-functions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matrix-functions.d.ts","sourceRoot":"","sources":["../../src/numeric/matrix-functions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAIH,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC;IACf,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC;CAChB;AAED,uEAAuE;AACvE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,EAAE,YAAY,KAAK,YAAY,CAAC;AAoHtE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAuD3E;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,CAAC,EAAE,YAAY,GAAG,YAAY,CAKxD;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,CAAC,EAAE,YAAY,GAAG,YAAY,CAKxD;AAED,wEAAwE;AACxE,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,aAAa,CAEjD;AAED,sEAAsE;AACtE,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,aAAa,CAEjD"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Structured and indefinite direct linear solvers.
3
+ *
4
+ * These exploit matrix structure (tridiagonal, banded, Toeplitz, symmetric
5
+ * indefinite) to solve `Ax = b` in less than the O(n^3) a general dense LU
6
+ * (`lusolve`) would cost, or — for `ldl` — to factor matrices `cholesky`
7
+ * cannot handle because they are not positive-definite (e.g. KKT systems):
8
+ *
9
+ * - `thomasSolve` — the Thomas algorithm, O(n) for tridiagonal systems.
10
+ * - `solveBanded` — banded-aware Gaussian elimination (no pivoting; touches
11
+ * only the O(n(l+u)) entries inside the band), for systems with `l` lower
12
+ * and `u` upper nonzero diagonals.
13
+ * - `toeplitzSolve` — the Levinson–Durbin recursion, O(n^2) for a Toeplitz
14
+ * system given only its first row and column.
15
+ * - `ldl` — Bunch–Kaufman-pivoted LDLᵀ factorization of a symmetric
16
+ * (possibly indefinite) matrix, with 1x1/2x2 diagonal blocks.
17
+ *
18
+ * @packageDocumentation
19
+ */
20
+ /**
21
+ * Thomas algorithm — O(n) solve of a tridiagonal system `Ax = d`.
22
+ *
23
+ * `A` is the tridiagonal matrix with subdiagonal `sub` (length n−1),
24
+ * diagonal `diag` (length n), and superdiagonal `sup` (length n−1). No
25
+ * pivoting is performed (as with any tridiagonal Thomas solve); the matrix
26
+ * should be diagonally dominant or otherwise stable without it.
27
+ *
28
+ * @example
29
+ * thomasSolve([-1, -1], [2, 2, 2], [-1, -1], [1, 0, 1]) // => [1, 1, 1]
30
+ */
31
+ export declare function thomasSolve(sub: number[], diag: number[], sup: number[], d: number[]): number[];
32
+ /**
33
+ * Banded-aware Gaussian elimination — solve `Ax = b` for a matrix with `l`
34
+ * nonzero lower diagonals and `u` nonzero upper diagonals (all other entries
35
+ * are assumed zero, though `A` is passed as a full dense matrix). Only the
36
+ * O(n(l+u)) entries inside the band are touched during elimination and
37
+ * back-substitution. No pivoting is performed — as with {@link thomasSolve},
38
+ * the matrix should be diagonally dominant or otherwise stable without it.
39
+ *
40
+ * @example
41
+ * solveBanded(1, 1, [[2, -1, 0], [-1, 2, -1], [0, -1, 2]], [1, 0, 1]) // => [1, 1, 1]
42
+ */
43
+ export declare function solveBanded(l: number, u: number, A: number[][], b: number[]): number[];
44
+ /**
45
+ * Levinson–Durbin recursion — O(n²) solve of a Toeplitz system `Tx = b`
46
+ * given only the first column `c` and first row `r` (`c[0]` must equal
47
+ * `r[0]`, the shared diagonal value). `T[i][j] = c[i-j]` for `i >= j`, else
48
+ * `r[j-i]`.
49
+ *
50
+ * Order-recursively builds the solution together with two auxiliary
51
+ * "predictor" vectors — one for `T`, one for `Tᵀ` (mutually coupled via the
52
+ * persymmetry `J T J = Tᵀ` that every Toeplitz matrix has, `J` the
53
+ * reversal/exchange matrix) — which is what makes a general (non-symmetric)
54
+ * Toeplitz system solvable in O(n²) rather than O(n³).
55
+ *
56
+ * @example
57
+ * toeplitzSolve([2, 1], [2, 1], [1, 2]) // => [0, 1]
58
+ */
59
+ export declare function toeplitzSolve(c: number[], r: number[], b: number[]): number[];
60
+ /** Result of {@link ldl}. */
61
+ export interface LDLResult {
62
+ /** Unit lower-triangular factor. */
63
+ L: number[][];
64
+ /** Block-diagonal factor (1x1 or 2x2 blocks along the diagonal). */
65
+ D: number[][];
66
+ /**
67
+ * Permutation such that `(P A Pᵀ)[i][j] = A[perm[i]][perm[j]]` and
68
+ * `L D Lᵀ = P A Pᵀ`.
69
+ */
70
+ perm: number[];
71
+ }
72
+ /**
73
+ * Bunch–Kaufman-pivoted LDLᵀ factorization of a symmetric (possibly
74
+ * indefinite) matrix `A`, useful for symmetric systems `cholesky` can't
75
+ * handle because they aren't positive-definite (e.g. KKT / saddle-point
76
+ * systems from constrained optimization).
77
+ *
78
+ * Reconstruction identity: `L D Lᵀ = P A Pᵀ`, where `P` is the permutation
79
+ * matrix with `P[i][perm[i]] = 1`, i.e. `(P A Pᵀ)[i][j] = A[perm[i]][perm[j]]`.
80
+ * `L` is unit lower-triangular; `D` is block-diagonal with 1x1 or 2x2 blocks
81
+ * (2x2 blocks appear where a pivot would otherwise be too small relative to
82
+ * the rest of its column, per the standard Bunch–Kaufman pivot selection).
83
+ *
84
+ * @example
85
+ * const { L, D, perm } = ldl([[1, 2, 3], [2, 1, 4], [3, 4, 1]]);
86
+ * // L D L^T reconstructs A with rows/cols permuted by perm.
87
+ */
88
+ export declare function ldl(A: number[][]): LDLResult;
89
+ //# sourceMappingURL=structured-solvers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-solvers.d.ts","sourceRoot":"","sources":["../../src/numeric/structured-solvers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CA+B/F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAwCtF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CA8E7E;AAED,6BAA6B;AAC7B,MAAM,WAAW,SAAS;IACxB,oCAAoC;IACpC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;IACd,oEAAoE;IACpE,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;IACd;;;OAGG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,SAAS,CAwG5C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danielsimonjr/mathts-functions",
3
- "version": "0.34.0",
3
+ "version": "0.35.0",
4
4
  "description": "Mathematical functions for MathTS - arithmetic, algebra, trigonometry, statistics, and more",
5
5
  "author": "Daniel Simon Jr.",
6
6
  "license": "MIT",