numbl 0.4.18 → 0.4.21

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 (72) hide show
  1. package/dist-browser/browser.js +1 -1
  2. package/dist-browser/numbl-core/executors/jit/callExecutor.d.ts +7 -1
  3. package/dist-browser/numbl-core/executors/jit/loopExecutor.d.ts +12 -7
  4. package/dist-browser/numbl-core/executors/jit/topLevelExecutor.d.ts +3 -0
  5. package/dist-browser/numbl-core/executors/jit/valueAdapter.d.ts +9 -2
  6. package/dist-browser/numbl-core/executors/registry.d.ts +8 -0
  7. package/dist-browser/numbl-core/helpers/sparse-direct.d.ts +107 -0
  8. package/dist-browser/numbl-core/helpers/warn.d.ts +9 -0
  9. package/dist-browser/numbl-core/interpreter/builtins/index.d.ts +1 -0
  10. package/dist-browser/numbl-core/interpreter/builtins/sparse-solvers.d.ts +16 -0
  11. package/dist-browser/numbl-core/interpreter/interpreter.d.ts +11 -0
  12. package/dist-browser/numbl-core/jit/builtins/runtime/system/cscalar.d.ts +4 -4
  13. package/dist-browser/numbl-core/jit/codegen/emitIndex.d.ts +1 -1
  14. package/dist-browser/numbl-core/jit/compileSpec.d.ts +4 -0
  15. package/dist-browser/numbl-core/jit/lowering/lower.d.ts +13 -0
  16. package/dist-browser/numbl-core/jitDeclineDiagnostics.d.ts +6 -0
  17. package/dist-browser/numbl-core/native/lapack-bridge.d.ts +29 -1
  18. package/dist-browser/numbl-core/native/ts-lapack-eig-hermitian.d.ts +33 -0
  19. package/dist-browser/numbl-core/runtime/types.d.ts +12 -0
  20. package/dist-browser/numbl-core/version.d.ts +1 -1
  21. package/dist-browser/ts-lapack/src/BLAS/dsymv.d.ts +1 -0
  22. package/dist-browser/ts-lapack/src/BLAS/dsyr2.d.ts +1 -0
  23. package/dist-browser/ts-lapack/src/SRC/dlae2.d.ts +4 -0
  24. package/dist-browser/ts-lapack/src/SRC/dlaev2.d.ts +6 -0
  25. package/dist-browser/ts-lapack/src/SRC/dlanst.d.ts +1 -0
  26. package/dist-browser/ts-lapack/src/SRC/dlansy.d.ts +1 -0
  27. package/dist-browser/ts-lapack/src/SRC/dlasrt.d.ts +1 -0
  28. package/dist-browser/ts-lapack/src/SRC/dorgtr.d.ts +1 -0
  29. package/dist-browser/ts-lapack/src/SRC/dsteqr.d.ts +4 -0
  30. package/dist-browser/ts-lapack/src/SRC/dsyev.d.ts +1 -0
  31. package/dist-browser/ts-lapack/src/SRC/dsytd2.d.ts +1 -0
  32. package/dist-cli/cli.js +3824 -280
  33. package/dist-lib/lib.js +3636 -113
  34. package/dist-lib/numbl-core/executors/jit/callExecutor.d.ts +7 -1
  35. package/dist-lib/numbl-core/executors/jit/loopExecutor.d.ts +12 -7
  36. package/dist-lib/numbl-core/executors/jit/topLevelExecutor.d.ts +3 -0
  37. package/dist-lib/numbl-core/executors/jit/valueAdapter.d.ts +9 -2
  38. package/dist-lib/numbl-core/executors/registry.d.ts +8 -0
  39. package/dist-lib/numbl-core/helpers/sparse-direct.d.ts +107 -0
  40. package/dist-lib/numbl-core/helpers/warn.d.ts +9 -0
  41. package/dist-lib/numbl-core/interpreter/builtins/index.d.ts +1 -0
  42. package/dist-lib/numbl-core/interpreter/builtins/sparse-solvers.d.ts +16 -0
  43. package/dist-lib/numbl-core/interpreter/interpreter.d.ts +11 -0
  44. package/dist-lib/numbl-core/jit/builtins/runtime/system/cscalar.d.ts +4 -4
  45. package/dist-lib/numbl-core/jit/codegen/emitIndex.d.ts +1 -1
  46. package/dist-lib/numbl-core/jit/compileSpec.d.ts +4 -0
  47. package/dist-lib/numbl-core/jit/lowering/lower.d.ts +13 -0
  48. package/dist-lib/numbl-core/jitDeclineDiagnostics.d.ts +6 -0
  49. package/dist-lib/numbl-core/native/lapack-bridge.d.ts +29 -1
  50. package/dist-lib/numbl-core/native/ts-lapack-eig-hermitian.d.ts +33 -0
  51. package/dist-lib/numbl-core/runtime/types.d.ts +12 -0
  52. package/dist-lib/numbl-core/version.d.ts +1 -1
  53. package/dist-lib/ts-lapack/src/BLAS/dsymv.d.ts +1 -0
  54. package/dist-lib/ts-lapack/src/BLAS/dsyr2.d.ts +1 -0
  55. package/dist-lib/ts-lapack/src/SRC/dlae2.d.ts +4 -0
  56. package/dist-lib/ts-lapack/src/SRC/dlaev2.d.ts +6 -0
  57. package/dist-lib/ts-lapack/src/SRC/dlanst.d.ts +1 -0
  58. package/dist-lib/ts-lapack/src/SRC/dlansy.d.ts +1 -0
  59. package/dist-lib/ts-lapack/src/SRC/dlasrt.d.ts +1 -0
  60. package/dist-lib/ts-lapack/src/SRC/dorgtr.d.ts +1 -0
  61. package/dist-lib/ts-lapack/src/SRC/dsteqr.d.ts +4 -0
  62. package/dist-lib/ts-lapack/src/SRC/dsyev.d.ts +1 -0
  63. package/dist-lib/ts-lapack/src/SRC/dsytd2.d.ts +1 -0
  64. package/dist-site-viewer/assets/index-DrtkDG_M.js +4832 -0
  65. package/dist-site-viewer/assets/numbl-worker-Dz_Z8B9u.js +5327 -0
  66. package/dist-site-viewer/index.html +1 -1
  67. package/native/lapack_eig.cpp +156 -0
  68. package/native/numbl_addon.cpp +7 -1
  69. package/native/numbl_addon_common.h +14 -0
  70. package/package.json +1 -1
  71. package/dist-site-viewer/assets/index-34LVPucU.js +0 -4831
  72. package/dist-site-viewer/assets/numbl-worker-BCMSGYEy.js +0 -5339
@@ -25,7 +25,10 @@
25
25
  * - **Loop-depth gate.** Declines when `interp.loopDepth > 0` so a
26
26
  * hot loop iterating function calls doesn't pay per-call JIT
27
27
  * propose / spec-cache overhead. Once an outer call is JIT'd, its
28
- * loops run inside mtoc2's compiled code anyway.
28
+ * loops run inside mtoc2's compiled code anyway. The gate lifts when
29
+ * every enclosing loop was itself declined: nothing above will be
30
+ * compiled then, and an expensive callee would otherwise run
31
+ * interpreted all the way down (`Interpreter.jitDeclinedLoopDepth`).
29
32
  */
30
33
  import type { Executor } from "../types.js";
31
34
  import { type JitType } from "../../jitTypes.js";
@@ -40,6 +43,9 @@ interface JitCallData {
40
43
  }
41
44
  interface CompiledArtifact {
42
45
  readonly specFn: (...args: unknown[]) => unknown;
46
+ /** The spec's declared output types — needed to convert a returned
47
+ * struct back (an untagged JS object otherwise). */
48
+ readonly outputTypes: ReadonlyArray<CompilerType>;
43
49
  }
44
50
  export declare const jitCallExecutor: Executor<JitCallData, CompiledArtifact | null>;
45
51
  export {};
@@ -9,13 +9,15 @@
9
9
  * that the synthetic body is a single-element `[loopStmt]` instead of
10
10
  * a whole script body.
11
11
  *
12
- * Loop-depth gate: only fires when `interp.loopDepth === 0`. A loop
13
- * dispatched while the interpreter is iterating an enclosing
14
- * loop-body would pay per-iter propose/cache overhead with no
15
- * speedup, because the *outer* loop is the natural JIT entry point
16
- * (it captures the inner loop's body and runs it natively in mtoc2-
17
- * emitted code). When the outer loop fires its own JIT, the inner
18
- * loop never reaches the interpreter dispatcher at all.
12
+ * Loop-depth gate: fires when `interp.loopDepth === 0`, or when every
13
+ * enclosing loop has been declined by the JIT. A loop dispatched while the
14
+ * interpreter iterates an enclosing loop-body would pay per-iter
15
+ * propose/cache overhead with no speedup, because the *outer* loop is the
16
+ * natural JIT entry point (it captures the inner loop's body and runs it
17
+ * natively in mtoc2-emitted code) — but that only holds when the outer loop
18
+ * actually compiles. If it declined, the interpreter is walking its body and
19
+ * this loop is the outermost thing still compilable, so the gate lifts
20
+ * (`Interpreter.jitDeclinedLoopDepth`).
19
21
  */
20
22
  import type { Executor } from "../types.js";
21
23
  import { type JitType } from "../../jitTypes.js";
@@ -36,6 +38,9 @@ interface JitLoopData {
36
38
  }
37
39
  interface CompiledArtifact {
38
40
  readonly specFn: (...args: unknown[]) => unknown;
41
+ /** The synthetic spec's output types, so a struct written back into the
42
+ * env is rebuilt as a struct (the emitted value is an untagged object). */
43
+ readonly outputTypes: ReadonlyArray<CompilerType>;
39
44
  }
40
45
  export declare const jitLoopExecutor: Executor<JitLoopData, CompiledArtifact | null>;
41
46
  export {};
@@ -31,6 +31,9 @@ interface JitTopLevelData {
31
31
  interface CompiledArtifact {
32
32
  readonly specFn: (...args: unknown[]) => unknown;
33
33
  readonly nargout: number;
34
+ /** The synthetic spec's output types, so a struct written back into the
35
+ * env is rebuilt as a struct (the emitted value is an untagged object). */
36
+ readonly outputTypes: ReadonlyArray<CompilerType>;
34
37
  }
35
38
  export declare const jitTopLevelExecutor: Executor<JitTopLevelData, CompiledArtifact | null>;
36
39
  export {};
@@ -43,8 +43,15 @@ import type { Type } from "../../jit/index.js";
43
43
  * complex-typed body reads `.re`/`.im`, so a bare number must be
44
44
  * boxed into `{re, im:0}`. */
45
45
  export declare function numblToJit(v: RuntimeValue, paramType?: Type): unknown;
46
- /** mtoc2 emit-JS return value → numbl RuntimeValue. */
47
- export declare function jitToNumbl(v: unknown): RuntimeValue;
46
+ /** mtoc2 emit-JS return value → numbl RuntimeValue.
47
+ *
48
+ * `retType` is the compiler type the spec declares for this output. It is
49
+ * only consulted for plain untagged objects, which is how the emitted code
50
+ * represents both a struct and a class instance — the value alone cannot
51
+ * tell them apart, so a struct is only rebuilt when the type says Struct
52
+ * and anything else untagged is rejected (the executor then bails and the
53
+ * interpreter, which has full class semantics, re-runs the call). */
54
+ export declare function jitToNumbl(v: unknown, retType?: Type): RuntimeValue;
48
55
  /** True if `e` is the grow-bail sentinel thrown by the emitted JS
49
56
  * store helpers (`mtoc2_idx_*_grow_js` in `scalar_index.js`) — an
50
57
  * indexed store whose index exceeds the runtime extent, which would
@@ -110,6 +110,14 @@ export declare class Registry {
110
110
  * pure overhead.
111
111
  */
112
112
  dispatch(siblings: readonly Stmt[], i: number, ctx: DispatchContext): DispatchResult;
113
+ /** Run one stmt on the AST interpreter.
114
+ *
115
+ * When that stmt is a loop, the interpreter is about to walk its body,
116
+ * which invalidates the "an enclosing loop will capture me" assumption
117
+ * behind the executors' `loopDepth` gate. `jitDeclinedLoopDepth` records
118
+ * that for the duration of the body so nested loops and calls can bid for
119
+ * themselves instead of running interpreted all the way down. */
120
+ private interpretFallback;
113
121
  private runStmtCandidate;
114
122
  /** Cache lookup + compile-on-miss + run + bail handling. Returns
115
123
  * the executor's success RunResult, or null when the candidate
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Sparse direct solvers on the CSC representation (real arithmetic):
3
+ * Kronecker product, structural triangularity checks, triangular solves,
4
+ * up-looking sparse Cholesky, left-looking sparse LU with partial pivoting
5
+ * (Gilbert-Peierls), permutations, fill-reducing orderings (minimum degree,
6
+ * reverse Cuthill-McKee), and the `A \ b` driver used by mldivide.
7
+ *
8
+ * Complex sparse matrices are not handled here; callers fall back to the
9
+ * dense path for them.
10
+ */
11
+ import { type RuntimeSparseMatrix, type RuntimeTensor, type SparseTriInfo } from "../runtime/types.js";
12
+ type Sp = RuntimeSparseMatrix;
13
+ export declare const SINGULAR_WARNING = "Matrix is singular to working precision.";
14
+ /** Convert a dense tensor to CSC (dropping zeros). */
15
+ export declare function denseToSparse(t: RuntimeTensor): Sp;
16
+ /** Build CSC from column-major dense data, dropping zeros. */
17
+ export declare function denseDataToSparse(data: Float64Array, m: number, n: number): Sp;
18
+ /** Sparse permutation matrix P with P(k, p[k]) = 1, so (P*A)(k,:) = A(p[k],:). */
19
+ export declare function permutationMatrix(p: Int32Array | number[]): Sp;
20
+ /** 1-based row vector from a 0-based permutation. */
21
+ export declare function permVectorTensor(p: Int32Array): RuntimeTensor;
22
+ export declare function invertPerm(p: Int32Array): Int32Array;
23
+ /** C = A(p, q) for 0-based permutations p (rows) and q (columns). */
24
+ export declare function sparsePermute(A: Sp, p: Int32Array, q: Int32Array): Sp;
25
+ export declare function sparseKron(A: Sp, B: Sp): Sp;
26
+ /**
27
+ * One O(nnz) pass over the pattern: is the matrix upper / lower triangular
28
+ * (explicitly stored zeros ignored), and where is each diagonal entry. The
29
+ * result is cached on the matrix object.
30
+ */
31
+ export declare function triangularInfo(S: Sp): SparseTriInfo;
32
+ /** True if every stored nonzero lies on or above the diagonal. */
33
+ export declare function sparseIsUpper(S: Sp): boolean;
34
+ /** True if every stored nonzero lies on or below the diagonal. */
35
+ export declare function sparseIsLower(S: Sp): boolean;
36
+ /** Exact numerical symmetry (A == A'), real sparse only. */
37
+ export declare function sparseIsSymmetric(S: Sp): boolean;
38
+ /** Solve R * X = B for upper-triangular R (n×n), B column-major n×nrhs.
39
+ * Returns the solution in a fresh array and whether a zero pivot was hit. */
40
+ export declare function sparseSolveUpper(R: Sp, B: Float64Array, nrhs: number): {
41
+ x: Float64Array;
42
+ singular: boolean;
43
+ };
44
+ /** Solve L * X = B for lower-triangular L (n×n). */
45
+ export declare function sparseSolveLower(L: Sp, B: Float64Array, nrhs: number): {
46
+ x: Float64Array;
47
+ singular: boolean;
48
+ };
49
+ export interface CholResult {
50
+ /** Lower factor with L * L' = A (only when ok). */
51
+ L: Sp;
52
+ ok: boolean;
53
+ /** 0 on success, otherwise the 1-based column at which the pivot failed. */
54
+ p: number;
55
+ }
56
+ /**
57
+ * Cholesky factorization of a symmetric positive definite sparse matrix.
58
+ * Only the upper triangle of A is read; symmetry is not checked. On failure
59
+ * returns the leading (p-1)×(p-1) factor computed so far.
60
+ */
61
+ export declare function sparseChol(A: Sp): CholResult;
62
+ export interface LuResult {
63
+ /** Unit lower triangular, m × min(m,n), rows in pivot order. */
64
+ L: Sp;
65
+ /** Upper triangular, min(m,n) × n. */
66
+ U: Sp;
67
+ /** Row permutation: row k of P*A*Q is row p[k] of A. */
68
+ p: Int32Array;
69
+ /** Column permutation: column k of P*A*Q is column q[k] of A. */
70
+ q: Int32Array;
71
+ singular: boolean;
72
+ }
73
+ /**
74
+ * LU factorization P*A*Q = L*U of a real sparse matrix with threshold
75
+ * partial pivoting (tol = 1 is plain partial pivoting; smaller values prefer
76
+ * the diagonal entry when it is at least tol times the largest candidate).
77
+ */
78
+ export declare function sparseLu(A: Sp, q: Int32Array | null, tol: number): LuResult;
79
+ export declare function identityPerm(n: number): Int32Array;
80
+ /**
81
+ * Minimum degree ordering on the pattern of A + A', computed on an explicit
82
+ * elimination graph. Returns a 0-based permutation p such that A(p,p) tends
83
+ * to have a sparser Cholesky factor. This is a plain minimum-degree
84
+ * ordering, not MATLAB's approximate minimum degree, so the permutation
85
+ * differs from MATLAB's `amd` while serving the same purpose.
86
+ */
87
+ export declare function minimumDegreeOrdering(A: Sp): Int32Array;
88
+ /**
89
+ * Reverse Cuthill-McKee ordering on the pattern of A + A'. Returns a 0-based
90
+ * permutation that tends to reduce the bandwidth of A(p,p).
91
+ */
92
+ export declare function reverseCuthillMcKee(A: Sp): Int32Array;
93
+ /** Column ordering for LU: minimum degree on the pattern of A'*A. */
94
+ export declare function columnOrdering(A: Sp): Int32Array;
95
+ /**
96
+ * Solve A * X = B for square real sparse A and dense B (n × nrhs,
97
+ * column-major). Returns null when the caller should use the dense path
98
+ * (non-square, complex, or nearly full A).
99
+ */
100
+ export declare function sparseSolve(A: Sp, B: Float64Array, nrhs: number): Float64Array | null;
101
+ /** Solve with precomputed LU factors: X = Q * U \ (L \ (P * B)). */
102
+ export declare function luSolve(lu: LuResult, B: Float64Array, nrhs: number): Float64Array;
103
+ /** Solve with LU factors of A for the transposed system A' * X = B. */
104
+ export declare function luSolveTransposed(lu: LuResult, B: Float64Array, nrhs: number): Float64Array;
105
+ /** Inverse of a square real sparse matrix, returned sparse. */
106
+ export declare function sparseInverse(A: Sp): Sp;
107
+ export {};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * MATLAB-style warnings from helper code that has no Runtime handle.
3
+ *
4
+ * The Runtime installs a sink that routes messages through its output
5
+ * channel ("Warning: <msg>"); before a Runtime exists, messages fall back
6
+ * to console.warn.
7
+ */
8
+ export declare function setWarningSink(fn: (msg: string) => void): void;
9
+ export declare function emitWarning(msg: string): void;
@@ -27,6 +27,7 @@ import "./cell-struct.js";
27
27
  import "./time-system.js";
28
28
  import "./datetime.js";
29
29
  import "./sparse.js";
30
+ import "./sparse-solvers.js";
30
31
  import "./graph.js";
31
32
  import "./gallery.js";
32
33
  import "./special-math.js";
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Sparse direct-solver builtins: fill-reducing orderings (symrcm, amd,
3
+ * colamd), random sparse matrices (sprand, sprandn, sprandsym), and the
4
+ * `decomposition` object that stores factors for repeated solves.
5
+ *
6
+ * The factorizations themselves live in helpers/sparse-direct.ts; chol, lu,
7
+ * kron, inv and the operators `\` and `/` dispatch to them from
8
+ * linear-algebra.ts and helpers/arithmetic.ts.
9
+ */
10
+ import type { RuntimeValue } from "../../runtime/types.js";
11
+ /**
12
+ * Hook for the mldivide / mrdivide operator builtins: `dA \ B` and `B / dA`
13
+ * with a decomposition object. Returns undefined when neither operand is a
14
+ * decomposition so the ordinary operator runs.
15
+ */
16
+ export declare function tryDecompositionDivide(name: "mldivide" | "mrdivide", a: RuntimeValue, b: RuntimeValue): RuntimeValue | undefined;
@@ -54,6 +54,17 @@ export declare class Interpreter {
54
54
  * interpreter never sees them, so this gate only fires on calls
55
55
  * that genuinely happen at the interpreter level inside a loop. */
56
56
  loopDepth: number;
57
+ /** @internal Number of those enclosing loops that the JIT *declined*, so
58
+ * the interpreter is walking their bodies statement by statement. The
59
+ * `loopDepth > 0` gate above assumes an enclosing loop will be compiled
60
+ * and will swallow whatever is nested inside it; when that loop was
61
+ * declined instead, the assumption is false and everything below it would
62
+ * run interpreted however expensive it is. The executors therefore gate on
63
+ * `loopDepth > 0 && jitDeclinedLoopDepth === 0`: still no per-iteration JIT
64
+ * attempts underneath a loop that is about to be compiled, but a nested
65
+ * loop or call under a declined one gets its own chance. Bumped by the
66
+ * registry around the interpreter fallback for a loop stmt. */
67
+ jitDeclinedLoopDepth: number;
57
68
  /** @internal Number of enclosing conditional blocks (`if` / `switch` /
58
69
  * `try`) whose bodies the interpreter is currently executing. Used by
59
70
  * the loop classifier: when a loop is dispatched with `condBlockDepth >
@@ -34,7 +34,7 @@ export function mtoc2_cpow(a: any, b: any): {
34
34
  im: number;
35
35
  };
36
36
  export function mtoc2_csqrt(z: any): {
37
- re: number;
37
+ re: any;
38
38
  im: number;
39
39
  };
40
40
  export function mtoc2_cexp(z: any): {
@@ -42,15 +42,15 @@ export function mtoc2_cexp(z: any): {
42
42
  im: number;
43
43
  };
44
44
  export function mtoc2_clog(z: any): {
45
- re: number;
45
+ re: any;
46
46
  im: number;
47
47
  };
48
48
  export function mtoc2_clog2(z: any): {
49
- re: number;
49
+ re: any;
50
50
  im: number;
51
51
  };
52
52
  export function mtoc2_clog10(z: any): {
53
- re: number;
53
+ re: any;
54
54
  im: number;
55
55
  };
56
56
  export function mtoc2_csin(z: any): {
@@ -38,7 +38,7 @@ export declare function emitNdScalarOffset(state: RuntimeState, indices: Readonl
38
38
  * the precomputed source-index buffer). The caller is expected to
39
39
  * emit these lines immediately after closing the slot iteration
40
40
  * loops and before the GCC statement-expression's yield expression. */
41
- export declare function emitSliceSlotSetup(state: RuntimeState, lines: string[], indent: string, slotsTyped: ReadonlyArray<IndexSliceArg>, baseCName: string, cleanups?: string[]): string[];
41
+ export declare function emitSliceSlotSetup(state: RuntimeState, lines: string[], indent: string, slotsTyped: ReadonlyArray<IndexSliceArg>, baseCName: string, cleanups?: string[], grow?: boolean): string[];
42
42
  /** Emit an `IndexSlice` as a C statement-expression-style block that
43
43
  * allocates the result tensor, fills it, and evaluates to the result
44
44
  * via a comma expression. The result is consumed at an owned consume
@@ -79,6 +79,10 @@ export interface CompileSpecResult {
79
79
  source: string;
80
80
  /** Names of runtime snippets activated by emit. Diagnostic only. */
81
81
  activatedSnippets: ReadonlyArray<string>;
82
+ /** The spec's output types, in order. The host needs them to convert
83
+ * returned values back: a struct and a class instance are both plain
84
+ * JS objects in the emitted code, so only the type says which is which. */
85
+ outputTypes: ReadonlyArray<Type>;
82
86
  }
83
87
  export declare function compileSpec(args: CompileSpecArgs): CompileSpecResult;
84
88
  export {};
@@ -225,6 +225,19 @@ export declare class Lowerer {
225
225
  recordAssignment(name: string, expr: IRExpr, span: Span): Assign;
226
226
  private lowerIf;
227
227
  private lowerElseChain;
228
+ /** MATLAB `switch` lowered to the equivalent if/elseif chain.
229
+ *
230
+ * The subject is evaluated once — hoisted to a temp unless it is already a
231
+ * plain variable — and each case label becomes an equality test against it:
232
+ * `strcmp` for text, `==` for numbers. A `case {a, b}` list is the OR of
233
+ * the individual tests. Everything after that is `lowerIf`'s problem, which
234
+ * means switch inherits its branch-env merging and cond folding.
235
+ *
236
+ * Declined (leaving the unit to the interpreter, as before this existed):
237
+ * a subject that is neither a scalar number nor text, a label whose kind
238
+ * does not match the subject's, and an empty `case {}`.
239
+ */
240
+ private lowerSwitch;
228
241
  private lowerWhile;
229
242
  private lowerFor;
230
243
  lowerExpr(e: Expr): IRExpr;
@@ -23,6 +23,12 @@ export interface JitDecline {
23
23
  kind: string;
24
24
  /** Which executor declined: "jit-top-level" | "jit-call" | "jit-loop". */
25
25
  where: string;
26
+ /** Source position of the offending construct, when the thrown error
27
+ * carried one. Only used for diagnostics. */
28
+ at?: {
29
+ file: string;
30
+ start: number;
31
+ };
26
32
  }
27
33
  /** Record a swallowed JIT decline reason (called from executor catch blocks). */
28
34
  export declare function recordJitDecline(d: JitDecline): void;
@@ -18,7 +18,7 @@
18
18
  * Expected native addon version. Bump this whenever the C++ addon API changes
19
19
  * (must match ADDON_VERSION in numbl_addon.cpp).
20
20
  */
21
- export declare const NATIVE_ADDON_EXPECTED_VERSION = 8;
21
+ export declare const NATIVE_ADDON_EXPECTED_VERSION = 9;
22
22
  export interface LapackBridge {
23
23
  /** Returns the native addon's version number. */
24
24
  addonVersion?(): number;
@@ -207,6 +207,34 @@ export interface LapackBridge {
207
207
  VL?: Float64Array;
208
208
  VR?: Float64Array;
209
209
  };
210
+ /**
211
+ * Eigenvalue decomposition of an n×n real *symmetric* matrix stored in
212
+ * column-major order. Uses LAPACK dsyev (only the lower triangle is read).
213
+ * Unlike `eig`, the eigenvalues are real and returned in ascending order and
214
+ * the eigenvectors are orthonormal, including across repeated eigenvalues.
215
+ * @param data Column-major Float64Array of length n*n (not modified).
216
+ * @param n Matrix dimension.
217
+ * @param computeV true → also compute the orthonormal eigenvectors.
218
+ * @returns Object with w (ascending eigenvalues) and optionally V.
219
+ */
220
+ eigSym?(data: Float64Array, n: number, computeV: boolean): {
221
+ w: Float64Array;
222
+ V?: Float64Array;
223
+ };
224
+ /**
225
+ * Eigenvalue decomposition of an n×n complex *Hermitian* matrix stored in
226
+ * column-major order. Uses LAPACK zheev (only the lower triangle is read).
227
+ * @param dataRe Real parts — column-major Float64Array of length n*n.
228
+ * @param dataIm Imaginary parts — column-major Float64Array of length n*n.
229
+ * @param n Matrix dimension.
230
+ * @param computeV true → also compute the unitary eigenvector basis.
231
+ * @returns Object with w (real, ascending) and optionally VRe/VIm.
232
+ */
233
+ eigHerm?(dataRe: Float64Array, dataIm: Float64Array, n: number, computeV: boolean): {
234
+ w: Float64Array;
235
+ VRe?: Float64Array;
236
+ VIm?: Float64Array;
237
+ };
210
238
  /**
211
239
  * Eigenvalue decomposition of an n×n complex matrix stored in column-major order.
212
240
  * Uses LAPACK zgeev.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Pure-TypeScript Hermitian eigensolver — a zheev-equivalent for the ts-lapack
3
+ * bridge (browser path, no native LAPACK addon).
4
+ *
5
+ * Ported from the netlib LAPACK reference (zheev → zhetd2 / zungtr → zsteqr).
6
+ * One structural deviation: zsteqr accumulates the QL/QR rotations directly
7
+ * into the complex matrix Q, whereas here DSTEQR is run with COMPZ = 'I' to
8
+ * get the real orthogonal eigenvector matrix S of the tridiagonal, and the
9
+ * back-transformation V = Q * S is done as one complex-times-real matrix
10
+ * product afterwards. Both are O(n^3); this way the tridiagonal QL/QR lives in
11
+ * exactly one place (src/ts-lapack/src/SRC/dsteqr.ts) instead of two.
12
+ *
13
+ * Because zlarfg produces a real beta, the tridiagonal form is real symmetric,
14
+ * so DSTEQR applies unchanged.
15
+ *
16
+ * Eigenvalues come back real and in ascending order; eigenvectors form a
17
+ * unitary basis (V^H * V = I), matching dsyev/zheev and MATLAB.
18
+ *
19
+ * All matrices are column-major with leading dimension n, split into parallel
20
+ * real/imag Float64Arrays — matching the bridge's eigHerm I/O shape.
21
+ */
22
+ /**
23
+ * ZHEEV-equivalent. `dataRe`/`dataIm` hold the full n×n Hermitian matrix in
24
+ * column-major order (only the lower triangle is read); they are not modified.
25
+ *
26
+ * Returns the eigenvalues in ascending order, plus a unitary eigenvector basis
27
+ * when `computeV` is set.
28
+ */
29
+ export declare function eigHermTs(dataRe: Float64Array, dataIm: Float64Array, n: number, computeV: boolean): {
30
+ w: Float64Array;
31
+ VRe?: Float64Array;
32
+ VIm?: Float64Array;
33
+ };
@@ -173,6 +173,15 @@ export declare class RuntimeStructArray extends Refcounted {
173
173
  }
174
174
  /** Sparse matrix in CSC (Compressed Sparse Column) format, matching MATLAB's
175
175
  * internal representation. */
176
+ /** Cached structural analysis of a sparse matrix (see helpers/sparse-direct). */
177
+ export interface SparseTriInfo {
178
+ upper: boolean;
179
+ lower: boolean;
180
+ /** Index into ir/pr of the diagonal entry of each column, or -1. */
181
+ diagPos: Int32Array;
182
+ /** Diagonal values (0 where absent). */
183
+ diag: Float64Array;
184
+ }
176
185
  export declare class RuntimeSparseMatrix extends Refcounted {
177
186
  readonly kind: "sparse_matrix";
178
187
  m: number;
@@ -181,6 +190,9 @@ export declare class RuntimeSparseMatrix extends Refcounted {
181
190
  jc: Int32Array;
182
191
  pr: Float64Array;
183
192
  pi: Float64Array | undefined;
193
+ /** Lazily computed by triangularInfo(); valid because sparse matrices are
194
+ * never mutated in place (indexed assignment builds a new matrix). */
195
+ _triInfo: SparseTriInfo | undefined;
184
196
  constructor(m: number, n: number, ir: Int32Array, jc: Int32Array, pr: Float64Array, pi?: Float64Array);
185
197
  }
186
198
  /** Dictionary mapping unique keys to values (MATLAB R2022b+). */
@@ -1,2 +1,2 @@
1
1
  /** Numbl version, used for JIT disk cache invalidation. */
2
- export declare const NUMBL_VERSION = "0.4.18";
2
+ export declare const NUMBL_VERSION = "0.4.21";
@@ -0,0 +1 @@
1
+ export declare function dsymv(uplo: number, n: number, alpha: number, a: Float64Array, aOff: number, lda: number, x: Float64Array, xOff: number, incx: number, beta: number, y: Float64Array, yOff: number, incy: number): void;
@@ -0,0 +1 @@
1
+ export declare function dsyr2(uplo: number, n: number, alpha: number, x: Float64Array, xOff: number, incx: number, y: Float64Array, yOff: number, incy: number, a: Float64Array, aOff: number, lda: number): void;
@@ -0,0 +1,4 @@
1
+ export declare function dlae2(a: number, b: number, c: number): {
2
+ rt1: number;
3
+ rt2: number;
4
+ };
@@ -0,0 +1,6 @@
1
+ export declare function dlaev2(a: number, b: number, c: number): {
2
+ rt1: number;
3
+ rt2: number;
4
+ cs1: number;
5
+ sn1: number;
6
+ };
@@ -0,0 +1 @@
1
+ export declare function dlanst(norm: number, n: number, d: Float64Array, dOff: number, e: Float64Array, eOff: number): number;
@@ -0,0 +1 @@
1
+ export declare function dlansy(norm: number, uplo: number, n: number, a: Float64Array, aOff: number, lda: number, work: Float64Array, workOff: number): number;
@@ -0,0 +1 @@
1
+ export declare function dlasrt(id: number, n: number, d: Float64Array, dOff: number): number;
@@ -0,0 +1 @@
1
+ export declare function dorgtr(uplo: number, n: number, a: Float64Array, aOff: number, lda: number, tau: Float64Array, tauOff: number): number;
@@ -0,0 +1,4 @@
1
+ export declare const COMPZ_N = 0;
2
+ export declare const COMPZ_V = 1;
3
+ export declare const COMPZ_I = 2;
4
+ export declare function dsteqr(compz: number, n: number, d: Float64Array, dOff: number, e: Float64Array, eOff: number, z: Float64Array, zOff: number, ldz: number, work: Float64Array, workOff: number): number;
@@ -0,0 +1 @@
1
+ export declare function dsyev(wantz: boolean, uplo: number, n: number, a: Float64Array, aOff: number, lda: number, w: Float64Array, wOff: number): number;
@@ -0,0 +1 @@
1
+ export declare function dsytd2(uplo: number, n: number, a: Float64Array, aOff: number, lda: number, d: Float64Array, dOff: number, e: Float64Array, eOff: number, tau: Float64Array, tauOff: number): number;