@hviana/sema 0.1.5 → 0.1.6

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 (160) hide show
  1. package/AGENTS.md +6 -5
  2. package/CITATION.cff +49 -0
  3. package/HOW_IT_WORKS.md +11 -12
  4. package/README.md +7 -5
  5. package/dist/example/demo.js +25 -25
  6. package/dist/example/train_base.d.ts +19 -21
  7. package/dist/example/train_base.js +1687 -1952
  8. package/dist/src/alphabet.d.ts +3 -3
  9. package/dist/src/alphabet.js +24 -27
  10. package/dist/src/alu/src/alu.d.ts +169 -194
  11. package/dist/src/alu/src/alu.js +374 -414
  12. package/dist/src/alu/src/expr.d.ts +36 -43
  13. package/dist/src/alu/src/expr.js +252 -278
  14. package/dist/src/alu/src/index.d.ts +9 -98
  15. package/dist/src/alu/src/index.js +10 -64
  16. package/dist/src/alu/src/kernel-arith.d.ts +1 -5
  17. package/dist/src/alu/src/kernel-arith.js +195 -285
  18. package/dist/src/alu/src/kernel-bits.d.ts +1 -5
  19. package/dist/src/alu/src/kernel-bits.js +81 -115
  20. package/dist/src/alu/src/kernel-logic.js +33 -63
  21. package/dist/src/alu/src/kernel-nd.js +155 -195
  22. package/dist/src/alu/src/kernel-numeric.d.ts +16 -80
  23. package/dist/src/alu/src/kernel-numeric.js +259 -331
  24. package/dist/src/alu/src/operation.d.ts +112 -132
  25. package/dist/src/alu/src/operation.js +149 -163
  26. package/dist/src/alu/src/parser.d.ts +168 -175
  27. package/dist/src/alu/src/parser.js +382 -421
  28. package/dist/src/alu/src/resonance.d.ts +16 -25
  29. package/dist/src/alu/src/resonance.js +49 -56
  30. package/dist/src/alu/src/text.d.ts +3 -7
  31. package/dist/src/alu/src/text.js +31 -37
  32. package/dist/src/alu/src/value.d.ts +14 -14
  33. package/dist/src/alu/src/value.js +150 -160
  34. package/dist/src/alu/test/alu.test.js +543 -656
  35. package/dist/src/bytes.d.ts +1 -5
  36. package/dist/src/bytes.js +33 -40
  37. package/dist/src/config.d.ts +99 -102
  38. package/dist/src/config.js +78 -83
  39. package/dist/src/derive/src/deduction.d.ts +60 -62
  40. package/dist/src/derive/src/deduction.js +103 -109
  41. package/dist/src/derive/src/index.d.ts +1 -7
  42. package/dist/src/derive/src/priority-queue.d.ts +8 -8
  43. package/dist/src/derive/src/priority-queue.js +57 -61
  44. package/dist/src/derive/src/rewrite.d.ts +15 -18
  45. package/dist/src/derive/src/rewrite.js +59 -67
  46. package/dist/src/derive/src/trie.d.ts +56 -56
  47. package/dist/src/derive/src/trie.js +175 -179
  48. package/dist/src/derive/test/derive.test.js +96 -100
  49. package/dist/src/extension.d.ts +13 -16
  50. package/dist/src/geometry.d.ts +17 -42
  51. package/dist/src/geometry.js +235 -266
  52. package/dist/src/index.d.ts +2 -17
  53. package/dist/src/index.js +2 -12
  54. package/dist/src/ingest-cache.d.ts +25 -30
  55. package/dist/src/ingest-cache.js +108 -127
  56. package/dist/src/mind/articulation.d.ts +1 -5
  57. package/dist/src/mind/articulation.js +77 -112
  58. package/dist/src/mind/attention.d.ts +40 -108
  59. package/dist/src/mind/attention.js +749 -871
  60. package/dist/src/mind/canonical.d.ts +4 -19
  61. package/dist/src/mind/canonical.js +27 -31
  62. package/dist/src/mind/graph-search.d.ts +201 -225
  63. package/dist/src/mind/graph-search.js +742 -821
  64. package/dist/src/mind/index.d.ts +2 -10
  65. package/dist/src/mind/junction.d.ts +31 -58
  66. package/dist/src/mind/junction.js +172 -237
  67. package/dist/src/mind/learning.d.ts +16 -52
  68. package/dist/src/mind/learning.js +143 -165
  69. package/dist/src/mind/match.d.ts +20 -69
  70. package/dist/src/mind/match.js +259 -318
  71. package/dist/src/mind/mechanisms/alu.js +16 -16
  72. package/dist/src/mind/mechanisms/cast.d.ts +9 -13
  73. package/dist/src/mind/mechanisms/cast.js +363 -456
  74. package/dist/src/mind/mechanisms/confluence.d.ts +8 -12
  75. package/dist/src/mind/mechanisms/confluence.js +152 -183
  76. package/dist/src/mind/mechanisms/cover.d.ts +2 -8
  77. package/dist/src/mind/mechanisms/cover.js +148 -210
  78. package/dist/src/mind/mechanisms/extraction.d.ts +8 -34
  79. package/dist/src/mind/mechanisms/extraction.js +234 -288
  80. package/dist/src/mind/mechanisms/recall.d.ts +6 -10
  81. package/dist/src/mind/mechanisms/recall.js +126 -185
  82. package/dist/src/mind/mind.d.ts +129 -154
  83. package/dist/src/mind/mind.js +258 -288
  84. package/dist/src/mind/pipeline-mechanism.d.ts +112 -124
  85. package/dist/src/mind/pipeline-mechanism.js +161 -172
  86. package/dist/src/mind/pipeline.d.ts +4 -14
  87. package/dist/src/mind/pipeline.js +125 -189
  88. package/dist/src/mind/primitives.d.ts +8 -32
  89. package/dist/src/mind/primitives.js +99 -117
  90. package/dist/src/mind/rationale.d.ts +86 -98
  91. package/dist/src/mind/rationale.js +113 -121
  92. package/dist/src/mind/reasoning.d.ts +2 -13
  93. package/dist/src/mind/reasoning.js +129 -166
  94. package/dist/src/mind/recognition.d.ts +1 -4
  95. package/dist/src/mind/recognition.js +183 -208
  96. package/dist/src/mind/resonance.d.ts +5 -22
  97. package/dist/src/mind/resonance.js +0 -0
  98. package/dist/src/mind/trace.d.ts +6 -25
  99. package/dist/src/mind/trace.js +50 -58
  100. package/dist/src/mind/traverse.d.ts +16 -58
  101. package/dist/src/mind/traverse.js +304 -357
  102. package/dist/src/mind/types.d.ts +120 -127
  103. package/dist/src/mind/types.js +60 -69
  104. package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
  105. package/dist/src/rabitq-ivf/src/database.js +201 -0
  106. package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
  107. package/dist/src/{rabitq-hnsw → rabitq-ivf}/src/index.js +1 -3
  108. package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
  109. package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
  110. package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
  111. package/dist/src/rabitq-ivf/src/prng.js +36 -0
  112. package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
  113. package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
  114. package/dist/src/sema.d.ts +9 -13
  115. package/dist/src/sema.js +26 -40
  116. package/dist/src/store-sqlite.d.ts +169 -166
  117. package/dist/src/store-sqlite.js +762 -662
  118. package/dist/src/store.d.ts +586 -630
  119. package/dist/src/store.js +1423 -1581
  120. package/dist/src/vec.d.ts +5 -9
  121. package/dist/src/vec.js +61 -73
  122. package/example/train_base.ts +13 -10
  123. package/package.json +1 -1
  124. package/src/alu/README.md +1 -1
  125. package/src/alu/src/index.ts +1 -1
  126. package/src/config.ts +19 -27
  127. package/src/index.ts +6 -11
  128. package/src/rabitq-ivf/README.md +56 -0
  129. package/src/rabitq-ivf/src/database.ts +276 -0
  130. package/src/{rabitq-hnsw → rabitq-ivf}/src/index.ts +2 -5
  131. package/src/rabitq-ivf/src/ivf.ts +1330 -0
  132. package/src/{rabitq-hnsw → rabitq-ivf}/src/prng.ts +1 -1
  133. package/src/store-sqlite.ts +196 -9
  134. package/src/store.ts +8 -32
  135. package/test/08-storage.test.mjs +3 -3
  136. package/test/14-scaling.test.mjs +2 -2
  137. package/test/35-ivf.test.mjs +263 -0
  138. package/test/36-bloom.test.mjs +123 -0
  139. package/dist/src/rabitq-hnsw/src/database.d.ts +0 -202
  140. package/dist/src/rabitq-hnsw/src/database.js +0 -405
  141. package/dist/src/rabitq-hnsw/src/heap.d.ts +0 -22
  142. package/dist/src/rabitq-hnsw/src/heap.js +0 -94
  143. package/dist/src/rabitq-hnsw/src/hnsw.d.ts +0 -125
  144. package/dist/src/rabitq-hnsw/src/hnsw.js +0 -500
  145. package/dist/src/rabitq-hnsw/src/index.d.ts +0 -15
  146. package/dist/src/rabitq-hnsw/src/prng.d.ts +0 -19
  147. package/dist/src/rabitq-hnsw/src/prng.js +0 -38
  148. package/dist/src/rabitq-hnsw/src/rabitq.d.ts +0 -95
  149. package/dist/src/rabitq-hnsw/src/rabitq.js +0 -299
  150. package/dist/src/rabitq-hnsw/src/store.d.ts +0 -162
  151. package/dist/src/rabitq-hnsw/src/store.js +0 -916
  152. package/dist/src/rabitq-hnsw/test/hnsw.test.d.ts +0 -1
  153. package/dist/src/rabitq-hnsw/test/hnsw.test.js +0 -1197
  154. package/src/rabitq-hnsw/README.md +0 -303
  155. package/src/rabitq-hnsw/src/database.ts +0 -492
  156. package/src/rabitq-hnsw/src/heap.ts +0 -90
  157. package/src/rabitq-hnsw/src/hnsw.ts +0 -514
  158. package/src/rabitq-hnsw/src/store.ts +0 -994
  159. package/src/rabitq-hnsw/test/hnsw.test.ts +0 -1213
  160. /package/src/{rabitq-hnsw → rabitq-ivf}/src/rabitq.ts +0 -0
@@ -39,210 +39,170 @@ import { asBit, asInt, int, isNd, nd } from "./value.js";
39
39
  /** The element list of an nd, or throw — so a structural op called on a non-list
40
40
  * declines (the Alu facade maps the throw to "this rule does not fire"). */
41
41
  function listOf(v) {
42
- if (!isNd(v)) {
43
- throw new Error("nd op: operand is not an n-dimensional value");
44
- }
45
- return v.items;
42
+ if (!isNd(v))
43
+ throw new Error("nd op: operand is not an n-dimensional value");
44
+ return v.items;
46
45
  }
47
46
  /** Resolve an operation-value to a canonical name of the wanted arity, or throw
48
47
  * (decline) when it names no known operation — the higher-order ops' shared
49
48
  * front door, so an unrecognised function argument never silently no-ops. */
50
49
  function resolveFn(ctx, op, arity) {
51
- const name = ctx.resolveOp(op, arity);
52
- if (name === null) {
53
- throw new Error("nd op: unrecognised operation argument");
54
- }
55
- return name;
50
+ const name = ctx.resolveOp(op, arity);
51
+ if (name === null)
52
+ throw new Error("nd op: unrecognised operation argument");
53
+ return name;
56
54
  }
57
55
  /** Register the n-dimensional layer into `r`. All ops are STRUCTURAL. */
58
56
  export function registerNd(r) {
59
- // ── core primitives (the only ops that touch `items`) ────────────────────
60
- // nd: PACK operands into a list. Variadic, so `nd(a, b, c)` = [a, b, c] and
61
- // `nd()` = the empty list. An operand that is itself a list nests (a matrix
62
- // is `nd(row0, row1, …)`), so rank grows by composition, never a new type.
63
- r.prim(
64
- "nd",
65
- "variadic",
66
- ["nd", "list", "vector", "tuple", "array"],
67
- (args) => nd(args.slice()),
68
- { structural: true },
69
- );
70
- // length: the top-level element count, as an exact int.
71
- r.prim(
72
- "length",
73
- 1,
74
- ["length", "size", "len"],
75
- (args) => int(BigInt(listOf(args[0]).length)),
76
- { structural: true },
77
- );
78
- // at: project the i-th element. A negative index counts from the end
79
- // (−1 = last), Python-style; out of range throws (the rule declines).
80
- r.prim("at", 2, ["at", "nth", "elem", "index"], (args) => {
81
- const xs = listOf(args[0]);
82
- let i = Number(asInt(args[1]));
83
- if (i < 0) {
84
- i += xs.length;
85
- }
86
- if (i < 0 || i >= xs.length) {
87
- throw new Error("at: index out of range");
88
- }
89
- return xs[i];
90
- }, { structural: true });
91
- // ── derived: construction ────────────────────────────────────────────────
92
- // range(n) = [0, 1, …, n−1]; range(a, b) = [a, a+1, …, b−1]. The index
93
- // generator map/reduce iterate over when there is no input list yet.
94
- r.derive("range", "variadic", ["range", "iota", "upto"], (args) => {
95
- const lo = args.length >= 2 ? asInt(args[0]) : 0n;
96
- const hi = args.length >= 2 ? asInt(args[1]) : asInt(args[0]);
97
- const out = [];
98
- for (let k = lo; k < hi; k++) {
99
- out.push(int(k));
100
- }
101
- return nd(out);
102
- }, { structural: true });
103
- // ── derived: the higher-order trio (op argument = any existing operation) ──
104
- // map(xs, f): apply the UNARY op f to each element. Built on at/length/nd; f
105
- // is resolved by meaning, so `map(xs, negate)`, `map(xs, sqrt)`, `map(xs,
106
- // inverse)` all work, and (via broadcast) map over a list of lists is fine.
107
- r.derive("map", 2, ["map", "each"], (args, ctx) => {
108
- const xs = listOf(args[0]);
109
- const f = resolveFn(ctx, args[1], 1);
110
- return nd(xs.map((e) => ctx.apply(f, [e])));
111
- }, { structural: true });
112
- // filter(xs, p): keep the elements for which the UNARY predicate p is truthy
113
- // (its result read as a bit). `filter(xs, isprime)`, `filter(xs, >0)`, … —
114
- // any op that returns a truth value is a predicate.
115
- r.derive("filter", 2, ["filter", "where", "keep"], (args, ctx) => {
116
- const xs = listOf(args[0]);
117
- const p = resolveFn(ctx, args[1], 1);
118
- return nd(xs.filter((e) => asBit(ctx.apply(p, [e])) === 1));
119
- }, { structural: true });
120
- // reduce(xs, f) / reduce(xs, f, z): left-fold the BINARY op f across the list,
121
- // optionally from a seed z. `reduce(xs, +)` sums, `reduce(xs, *)` multiplies,
122
- // `reduce(xs, max)` is the maximum, `reduce(xs, or)` is "any", … — the scalar
123
- // kernel's whole binary vocabulary becomes a fold. With no seed an empty list
124
- // declines (nothing to fold); with a seed it returns the seed.
125
- r.derive(
126
- "reduce",
127
- "variadic",
128
- ["reduce", "fold", "accumulate"],
129
- (args, ctx) => {
130
- if (args.length < 2) {
131
- throw new Error("reduce: needs a list and an operation");
132
- }
133
- const xs = listOf(args[0]);
134
- const f = resolveFn(ctx, args[1], 2);
135
- const hasSeed = args.length >= 3;
136
- let acc;
137
- let start;
138
- if (hasSeed) {
139
- acc = args[2];
140
- start = 0;
141
- } else {
142
- if (xs.length === 0) {
143
- throw new Error("reduce: empty list, no seed");
57
+ // ── core primitives (the only ops that touch `items`) ────────────────────
58
+ // nd: PACK operands into a list. Variadic, so `nd(a, b, c)` = [a, b, c] and
59
+ // `nd()` = the empty list. An operand that is itself a list nests (a matrix
60
+ // is `nd(row0, row1, …)`), so rank grows by composition, never a new type.
61
+ r.prim("nd", "variadic", ["nd", "list", "vector", "tuple", "array"], (args) => nd(args.slice()), { structural: true });
62
+ // length: the top-level element count, as an exact int.
63
+ r.prim("length", 1, ["length", "size", "len"], (args) => int(BigInt(listOf(args[0]).length)), { structural: true });
64
+ // at: project the i-th element. A negative index counts from the end
65
+ // (−1 = last), Python-style; out of range throws (the rule declines).
66
+ r.prim("at", 2, ["at", "nth", "elem", "index"], (args) => {
67
+ const xs = listOf(args[0]);
68
+ let i = Number(asInt(args[1]));
69
+ if (i < 0)
70
+ i += xs.length;
71
+ if (i < 0 || i >= xs.length)
72
+ throw new Error("at: index out of range");
73
+ return xs[i];
74
+ }, { structural: true });
75
+ // ── derived: construction ────────────────────────────────────────────────
76
+ // range(n) = [0, 1, …, n−1]; range(a, b) = [a, a+1, …, b−1]. The index
77
+ // generator map/reduce iterate over when there is no input list yet.
78
+ r.derive("range", "variadic", ["range", "iota", "upto"], (args) => {
79
+ const lo = args.length >= 2 ? asInt(args[0]) : 0n;
80
+ const hi = args.length >= 2 ? asInt(args[1]) : asInt(args[0]);
81
+ const out = [];
82
+ for (let k = lo; k < hi; k++)
83
+ out.push(int(k));
84
+ return nd(out);
85
+ }, { structural: true });
86
+ // ── derived: the higher-order trio (op argument = any existing operation) ──
87
+ // map(xs, f): apply the UNARY op f to each element. Built on at/length/nd; f
88
+ // is resolved by meaning, so `map(xs, negate)`, `map(xs, sqrt)`, `map(xs,
89
+ // inverse)` all work, and (via broadcast) map over a list of lists is fine.
90
+ r.derive("map", 2, ["map", "each"], (args, ctx) => {
91
+ const xs = listOf(args[0]);
92
+ const f = resolveFn(ctx, args[1], 1);
93
+ return nd(xs.map((e) => ctx.apply(f, [e])));
94
+ }, { structural: true });
95
+ // filter(xs, p): keep the elements for which the UNARY predicate p is truthy
96
+ // (its result read as a bit). `filter(xs, isprime)`, `filter(xs, >0)`, … —
97
+ // any op that returns a truth value is a predicate.
98
+ r.derive("filter", 2, ["filter", "where", "keep"], (args, ctx) => {
99
+ const xs = listOf(args[0]);
100
+ const p = resolveFn(ctx, args[1], 1);
101
+ return nd(xs.filter((e) => asBit(ctx.apply(p, [e])) === 1));
102
+ }, { structural: true });
103
+ // reduce(xs, f) / reduce(xs, f, z): left-fold the BINARY op f across the list,
104
+ // optionally from a seed z. `reduce(xs, +)` sums, `reduce(xs, *)` multiplies,
105
+ // `reduce(xs, max)` is the maximum, `reduce(xs, or)` is "any", the scalar
106
+ // kernel's whole binary vocabulary becomes a fold. With no seed an empty list
107
+ // declines (nothing to fold); with a seed it returns the seed.
108
+ r.derive("reduce", "variadic", ["reduce", "fold", "accumulate"], (args, ctx) => {
109
+ if (args.length < 2) {
110
+ throw new Error("reduce: needs a list and an operation");
144
111
  }
145
- acc = xs[0];
146
- start = 1;
147
- }
148
- for (let i = start; i < xs.length; i++) {
149
- acc = ctx.apply(f, [acc, xs[i]]);
150
- }
151
- return acc;
152
- },
153
- { structural: true },
154
- );
155
- // find(xs, p): the FIRST element satisfying the unary predicate p, or the
156
- // empty nd when none does (a graph-evidenced "nothing matched", never a guess).
157
- r.derive("find", 2, ["find", "first", "search"], (args, ctx) => {
158
- const xs = listOf(args[0]);
159
- const p = resolveFn(ctx, args[1], 1);
160
- for (const e of xs) {
161
- if (asBit(ctx.apply(p, [e])) === 1) {
162
- return e;
163
- }
164
- }
165
- return nd([]);
166
- }, { structural: true });
167
- // ── derived: shape-preserving plumbing ────────────────────────────────────
168
- // concat(a, b, …): join lists end to end into one list.
169
- r.derive("concat", "variadic", ["concat", "append", "join"], (args) => {
170
- const out = [];
171
- for (const a of args) {
172
- for (const e of listOf(a)) {
173
- out.push(e);
174
- }
175
- }
176
- return nd(out);
177
- }, { structural: true });
178
- // reverse(xs): the list back to front.
179
- r.derive(
180
- "reverse",
181
- 1,
182
- ["reverse", "flip"],
183
- (args) => nd(listOf(args[0]).slice().reverse()),
184
- { structural: true },
185
- );
186
- // flatten(xs): splice one level — each nd element is spliced in, each scalar
187
- // kept. flatten ∘ flatten goes deeper; one level is the primitive step.
188
- r.derive("flatten", 1, ["flatten", "flat"], (args) => {
189
- const out = [];
190
- for (const e of listOf(args[0])) {
191
- if (isNd(e)) {
192
- for (const sub of e.items) {
193
- out.push(sub);
112
+ const xs = listOf(args[0]);
113
+ const f = resolveFn(ctx, args[1], 2);
114
+ const hasSeed = args.length >= 3;
115
+ let acc;
116
+ let start;
117
+ if (hasSeed) {
118
+ acc = args[2];
119
+ start = 0;
194
120
  }
195
- } else {
196
- out.push(e);
197
- }
198
- }
199
- return nd(out);
200
- }, { structural: true });
201
- // zip(a, b, …): the lists braided into a list of tuples; length = the shortest
202
- // input (a ragged braid stops at the short one, never inventing elements).
203
- r.derive("zip", "variadic", ["zip", "braid"], (args) => {
204
- const lists = args.map(listOf);
205
- if (lists.length === 0) {
206
- return nd([]);
207
- }
208
- const m = Math.min(...lists.map((l) => l.length));
209
- const out = [];
210
- for (let i = 0; i < m; i++) {
211
- out.push(nd(lists.map((l) => l[i])));
212
- }
213
- return nd(out);
214
- }, { structural: true });
215
- // rank(v): the nesting DEPTH — 0 for a scalar, 1 + the deepest element's rank
216
- // for a list (so a vector is 1, a matrix 2, ragged depth taken as the max).
217
- r.derive("rank", 1, ["rank", "depth", "ndim"], (args) => {
218
- const rank = (v) => {
219
- if (!isNd(v)) {
220
- return 0n;
221
- }
222
- let m = 0n;
223
- for (const e of v.items) {
224
- const rr = rank(e);
225
- if (rr > m) {
226
- m = rr;
121
+ else {
122
+ if (xs.length === 0)
123
+ throw new Error("reduce: empty list, no seed");
124
+ acc = xs[0];
125
+ start = 1;
227
126
  }
228
- }
229
- return m + 1n;
230
- };
231
- return int(rank(args[0]));
232
- }, { structural: true });
233
- // shape(v): the size along each axis, following the FIRST element down — the
234
- // regular-tensor shape (a ragged list is reported by its top length, the
235
- // recursion only descending the head). Returns a list of ints.
236
- r.derive("shape", 1, ["shape", "dims"], (args) => {
237
- const dims = [];
238
- let cur = args[0];
239
- while (isNd(cur)) {
240
- dims.push(int(BigInt(cur.items.length)));
241
- if (cur.items.length === 0) {
242
- break;
243
- }
244
- cur = cur.items[0];
245
- }
246
- return nd(dims);
247
- }, { structural: true });
127
+ for (let i = start; i < xs.length; i++)
128
+ acc = ctx.apply(f, [acc, xs[i]]);
129
+ return acc;
130
+ }, { structural: true });
131
+ // find(xs, p): the FIRST element satisfying the unary predicate p, or the
132
+ // empty nd when none does (a graph-evidenced "nothing matched", never a guess).
133
+ r.derive("find", 2, ["find", "first", "search"], (args, ctx) => {
134
+ const xs = listOf(args[0]);
135
+ const p = resolveFn(ctx, args[1], 1);
136
+ for (const e of xs)
137
+ if (asBit(ctx.apply(p, [e])) === 1)
138
+ return e;
139
+ return nd([]);
140
+ }, { structural: true });
141
+ // ── derived: shape-preserving plumbing ────────────────────────────────────
142
+ // concat(a, b, …): join lists end to end into one list.
143
+ r.derive("concat", "variadic", ["concat", "append", "join"], (args) => {
144
+ const out = [];
145
+ for (const a of args)
146
+ for (const e of listOf(a))
147
+ out.push(e);
148
+ return nd(out);
149
+ }, { structural: true });
150
+ // reverse(xs): the list back to front.
151
+ r.derive("reverse", 1, ["reverse", "flip"], (args) => nd(listOf(args[0]).slice().reverse()), { structural: true });
152
+ // flatten(xs): splice one level — each nd element is spliced in, each scalar
153
+ // kept. flatten ∘ flatten goes deeper; one level is the primitive step.
154
+ r.derive("flatten", 1, ["flatten", "flat"], (args) => {
155
+ const out = [];
156
+ for (const e of listOf(args[0])) {
157
+ if (isNd(e)) {
158
+ for (const sub of e.items)
159
+ out.push(sub);
160
+ }
161
+ else
162
+ out.push(e);
163
+ }
164
+ return nd(out);
165
+ }, { structural: true });
166
+ // zip(a, b, …): the lists braided into a list of tuples; length = the shortest
167
+ // input (a ragged braid stops at the short one, never inventing elements).
168
+ r.derive("zip", "variadic", ["zip", "braid"], (args) => {
169
+ const lists = args.map(listOf);
170
+ if (lists.length === 0)
171
+ return nd([]);
172
+ const m = Math.min(...lists.map((l) => l.length));
173
+ const out = [];
174
+ for (let i = 0; i < m; i++)
175
+ out.push(nd(lists.map((l) => l[i])));
176
+ return nd(out);
177
+ }, { structural: true });
178
+ // rank(v): the nesting DEPTH — 0 for a scalar, 1 + the deepest element's rank
179
+ // for a list (so a vector is 1, a matrix 2, ragged depth taken as the max).
180
+ r.derive("rank", 1, ["rank", "depth", "ndim"], (args) => {
181
+ const rank = (v) => {
182
+ if (!isNd(v))
183
+ return 0n;
184
+ let m = 0n;
185
+ for (const e of v.items) {
186
+ const rr = rank(e);
187
+ if (rr > m)
188
+ m = rr;
189
+ }
190
+ return m + 1n;
191
+ };
192
+ return int(rank(args[0]));
193
+ }, { structural: true });
194
+ // shape(v): the size along each axis, following the FIRST element down — the
195
+ // regular-tensor shape (a ragged list is reported by its top length, the
196
+ // recursion only descending the head). Returns a list of ints.
197
+ r.derive("shape", 1, ["shape", "dims"], (args) => {
198
+ const dims = [];
199
+ let cur = args[0];
200
+ while (isNd(cur)) {
201
+ dims.push(int(BigInt(cur.items.length)));
202
+ if (cur.items.length === 0)
203
+ break;
204
+ cur = cur.items[0];
205
+ }
206
+ return nd(dims);
207
+ }, { structural: true });
248
208
  }
@@ -3,115 +3,51 @@ import type { OperationRegistry } from "./operation.js";
3
3
  * agree within `tol` (absolute, or relative for large magnitudes), or until
4
4
  * `maxIter` is reached. Returns the last iterate — the refinement's fixed
5
5
  * point. This is the single irreducible operator of the numerical layer. */
6
- export declare function converge(
7
- step: (x: number) => number,
8
- x0: number,
9
- tol: number,
10
- maxIter: number,
11
- ): number;
6
+ export declare function converge(step: (x: number) => number, x0: number, tol: number, maxIter: number): number;
12
7
  /** Numerical derivative f′(a) by a central difference refined as h → 0 — a
13
8
  * `converge` instance over shrinking step sizes (Richardson-style halving). */
14
- export declare function diff(
15
- f: (x: number) => number,
16
- a: number,
17
- tol: number,
18
- maxIter: number,
19
- ): number;
9
+ export declare function diff(f: (x: number) => number, a: number, tol: number, maxIter: number): number;
20
10
  /** A root of f near x0, by Newton's method: converge x − f(x)/f′(x), with f′
21
11
  * from {@link diff}. Falls back to a secant step if the derivative vanishes. */
22
- export declare function solve(
23
- f: (x: number) => number,
24
- x0: number,
25
- tol: number,
26
- maxIter: number,
27
- ): number;
12
+ export declare function solve(f: (x: number) => number, x0: number, tol: number, maxIter: number): number;
28
13
  /** Definite integral of f over [a, b], by composite Simpson refined until the
29
14
  * estimate stops moving — a `converge` over partition count. */
30
- export declare function integrate(
31
- f: (x: number) => number,
32
- a: number,
33
- b: number,
34
- tol: number,
35
- maxIter: number,
36
- ): number;
15
+ export declare function integrate(f: (x: number) => number, a: number, b: number, tol: number, maxIter: number): number;
37
16
  /** e^x by its Taylor series, summed until a term is below tolerance — a
38
17
  * `converge` over partial sums. (Range-reduction-free; adequate for the
39
18
  * arguments a query produces, and exact in the limit.) */
40
- export declare function expSeries(
41
- x: number,
42
- tol: number,
43
- maxIter: number,
44
- ): number;
19
+ export declare function expSeries(x: number, tol: number, maxIter: number): number;
45
20
  /** ln(x), x > 0, as the root of e^t − x = 0 (Newton via {@link solve}, with a
46
21
  * good initial guess from the host log to keep iteration counts low). */
47
- export declare function logNewton(
48
- x: number,
49
- tol: number,
50
- maxIter: number,
51
- ): number;
22
+ export declare function logNewton(x: number, tol: number, maxIter: number): number;
52
23
  /** sin / cos by their Taylor series (a `converge` over partial sums), with
53
24
  * argument reduction into [−π, π] for accuracy. */
54
- export declare function sinSeries(
55
- x: number,
56
- tol: number,
57
- maxIter: number,
58
- ): number;
59
- export declare function cosSeries(
60
- x: number,
61
- tol: number,
62
- maxIter: number,
63
- ): number;
25
+ export declare function sinSeries(x: number, tol: number, maxIter: number): number;
26
+ export declare function cosSeries(x: number, tol: number, maxIter: number): number;
64
27
  /** √x as the positive root of t² − x = 0 (Newton via {@link solve}). */
65
- export declare function sqrtNewton(
66
- x: number,
67
- tol: number,
68
- maxIter: number,
69
- ): number;
28
+ export declare function sqrtNewton(x: number, tol: number, maxIter: number): number;
70
29
  /** A local minimum of f near x0: a root of f′ = 0 (optimize = solve(diff f)). */
71
- export declare function optimize(
72
- f: (x: number) => number,
73
- x0: number,
74
- tol: number,
75
- maxIter: number,
76
- ): number;
30
+ export declare function optimize(f: (x: number) => number, x0: number, tol: number, maxIter: number): number;
77
31
  /** Integrate an ODE y′ = f(t, y) from (t0, y0) to t1 by classical RK4 stepping
78
32
  * — explicit stepping is the layer's other use of refinement (here a fixed
79
33
  * fine step; an implicit step would close with {@link solve}). */
80
- export declare function odeSolve(
81
- f: (t: number, y: number) => number,
82
- t0: number,
83
- y0: number,
84
- t1: number,
85
- steps?: number,
86
- ): number;
34
+ export declare function odeSolve(f: (t: number, y: number) => number, t0: number, y0: number, t1: number, steps?: number): number;
87
35
  /** Least-squares polynomial regression of degree `deg` over (x, y) samples:
88
36
  * build the normal equations and solve them with {@link linsolve} — regression
89
37
  * reduces to structured arithmetic. Returns coefficients constant-first. */
90
- export declare function regress(
91
- xs: number[],
92
- ys: number[],
93
- deg: number,
94
- ): number[] | null;
38
+ export declare function regress(xs: number[], ys: number[], deg: number): number[] | null;
95
39
  /** Linear interpolation of y at `xq` over sorted sample points (xs, ys). */
96
- export declare function interpolate(
97
- xs: number[],
98
- ys: number[],
99
- xq: number,
100
- ): number;
40
+ export declare function interpolate(xs: number[], ys: number[], xq: number): number;
101
41
  /** Dominant eigenpair of a (preferably symmetric) matrix by POWER ITERATION —
102
42
  * the canonical "iteration = converge" of this layer. Returns the eigenvalue
103
43
  * (Rayleigh quotient) and its unit eigenvector. */
104
44
  export declare function powerEig(A: number[][], tol: number, maxIter: number): {
105
- value: number;
106
- vector: number[];
45
+ value: number;
46
+ vector: number[];
107
47
  };
108
48
  /** Largest singular value of A: √(dominant eigenvalue of AᵀA) — power iteration
109
49
  * again, the prototypical `converge`. */
110
- export declare function topSingular(
111
- A: number[][],
112
- tol: number,
113
- maxIter: number,
114
- ): number;
50
+ export declare function topSingular(A: number[][], tol: number, maxIter: number): number;
115
51
  /** Register the scalar transcendentals as ops (they have surface forms). The
116
52
  * matrix routines stay exported functions — there is no infix surface for a
117
53
  * matrix, and auto-firing them from query spans is neither wanted nor safe. */