@hviana/sema 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/example/demo.d.ts +1 -0
  2. package/dist/example/demo.js +39 -0
  3. package/dist/example/train_base.d.ts +87 -0
  4. package/dist/example/train_base.js +2252 -0
  5. package/dist/src/alphabet.d.ts +7 -0
  6. package/dist/src/alphabet.js +33 -0
  7. package/dist/src/alu/src/alu.d.ts +185 -0
  8. package/dist/src/alu/src/alu.js +440 -0
  9. package/dist/src/alu/src/expr.d.ts +61 -0
  10. package/dist/src/alu/src/expr.js +318 -0
  11. package/dist/src/alu/src/index.d.ts +11 -0
  12. package/dist/src/alu/src/index.js +19 -0
  13. package/dist/src/alu/src/kernel-arith.d.ts +16 -0
  14. package/dist/src/alu/src/kernel-arith.js +264 -0
  15. package/dist/src/alu/src/kernel-bits.d.ts +19 -0
  16. package/dist/src/alu/src/kernel-bits.js +152 -0
  17. package/dist/src/alu/src/kernel-logic.d.ts +4 -0
  18. package/dist/src/alu/src/kernel-logic.js +60 -0
  19. package/dist/src/alu/src/kernel-nd.d.ts +3 -0
  20. package/dist/src/alu/src/kernel-nd.js +208 -0
  21. package/dist/src/alu/src/kernel-numeric.d.ts +54 -0
  22. package/dist/src/alu/src/kernel-numeric.js +366 -0
  23. package/dist/src/alu/src/operation.d.ts +168 -0
  24. package/dist/src/alu/src/operation.js +189 -0
  25. package/dist/src/alu/src/parser.d.ts +221 -0
  26. package/dist/src/alu/src/parser.js +577 -0
  27. package/dist/src/alu/src/resonance.d.ts +55 -0
  28. package/dist/src/alu/src/resonance.js +126 -0
  29. package/dist/src/alu/src/text.d.ts +31 -0
  30. package/dist/src/alu/src/text.js +73 -0
  31. package/dist/src/alu/src/value.d.ts +109 -0
  32. package/dist/src/alu/src/value.js +300 -0
  33. package/dist/src/alu/test/alu.test.d.ts +1 -0
  34. package/dist/src/alu/test/alu.test.js +764 -0
  35. package/dist/src/bytes.d.ts +14 -0
  36. package/dist/src/bytes.js +59 -0
  37. package/dist/src/canon.d.ts +26 -0
  38. package/dist/src/canon.js +57 -0
  39. package/dist/src/config.d.ts +111 -0
  40. package/dist/src/config.js +91 -0
  41. package/dist/src/derive/src/deduction.d.ts +125 -0
  42. package/dist/src/derive/src/deduction.js +155 -0
  43. package/dist/src/derive/src/index.d.ts +7 -0
  44. package/dist/src/derive/src/index.js +11 -0
  45. package/dist/src/derive/src/priority-queue.d.ts +20 -0
  46. package/dist/src/derive/src/priority-queue.js +73 -0
  47. package/dist/src/derive/src/rewrite.d.ts +56 -0
  48. package/dist/src/derive/src/rewrite.js +100 -0
  49. package/dist/src/derive/src/trie.d.ts +90 -0
  50. package/dist/src/derive/src/trie.js +217 -0
  51. package/dist/src/derive/test/derive.test.d.ts +1 -0
  52. package/dist/src/derive/test/derive.test.js +122 -0
  53. package/dist/src/extension.d.ts +37 -0
  54. package/dist/src/extension.js +7 -0
  55. package/dist/src/geometry.d.ts +148 -0
  56. package/dist/src/geometry.js +511 -0
  57. package/dist/src/index.d.ts +16 -0
  58. package/dist/src/index.js +18 -0
  59. package/dist/src/ingest-cache.d.ts +41 -0
  60. package/dist/src/ingest-cache.js +161 -0
  61. package/dist/src/mind/articulation.d.ts +6 -0
  62. package/dist/src/mind/articulation.js +99 -0
  63. package/dist/src/mind/attention.d.ts +72 -0
  64. package/dist/src/mind/attention.js +898 -0
  65. package/dist/src/mind/canonical.d.ts +29 -0
  66. package/dist/src/mind/canonical.js +88 -0
  67. package/dist/src/mind/graph-search.d.ts +270 -0
  68. package/dist/src/mind/graph-search.js +927 -0
  69. package/dist/src/mind/index.d.ts +5 -0
  70. package/dist/src/mind/index.js +5 -0
  71. package/dist/src/mind/junction.d.ts +95 -0
  72. package/dist/src/mind/junction.js +262 -0
  73. package/dist/src/mind/learning.d.ts +47 -0
  74. package/dist/src/mind/learning.js +233 -0
  75. package/dist/src/mind/match.d.ts +113 -0
  76. package/dist/src/mind/match.js +446 -0
  77. package/dist/src/mind/mechanisms/alu.d.ts +4 -0
  78. package/dist/src/mind/mechanisms/alu.js +29 -0
  79. package/dist/src/mind/mechanisms/cast.d.ts +35 -0
  80. package/dist/src/mind/mechanisms/cast.js +461 -0
  81. package/dist/src/mind/mechanisms/confluence.d.ts +24 -0
  82. package/dist/src/mind/mechanisms/confluence.js +225 -0
  83. package/dist/src/mind/mechanisms/cover.d.ts +6 -0
  84. package/dist/src/mind/mechanisms/cover.js +179 -0
  85. package/dist/src/mind/mechanisms/extraction.d.ts +67 -0
  86. package/dist/src/mind/mechanisms/extraction.js +342 -0
  87. package/dist/src/mind/mechanisms/recall.d.ts +13 -0
  88. package/dist/src/mind/mechanisms/recall.js +235 -0
  89. package/dist/src/mind/mind.d.ts +273 -0
  90. package/dist/src/mind/mind.js +598 -0
  91. package/dist/src/mind/pipeline-mechanism.d.ts +142 -0
  92. package/dist/src/mind/pipeline-mechanism.js +213 -0
  93. package/dist/src/mind/pipeline.d.ts +20 -0
  94. package/dist/src/mind/pipeline.js +185 -0
  95. package/dist/src/mind/primitives.d.ts +63 -0
  96. package/dist/src/mind/primitives.js +251 -0
  97. package/dist/src/mind/rationale.d.ts +134 -0
  98. package/dist/src/mind/rationale.js +162 -0
  99. package/dist/src/mind/reasoning.d.ts +15 -0
  100. package/dist/src/mind/reasoning.js +162 -0
  101. package/dist/src/mind/recognition.d.ts +20 -0
  102. package/dist/src/mind/recognition.js +246 -0
  103. package/dist/src/mind/resonance.d.ts +23 -0
  104. package/dist/src/mind/resonance.js +0 -0
  105. package/dist/src/mind/trace.d.ts +15 -0
  106. package/dist/src/mind/trace.js +73 -0
  107. package/dist/src/mind/traverse.d.ts +113 -0
  108. package/dist/src/mind/traverse.js +488 -0
  109. package/dist/src/mind/types.d.ts +186 -0
  110. package/dist/src/mind/types.js +84 -0
  111. package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
  112. package/dist/src/rabitq-ivf/src/database.js +201 -0
  113. package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
  114. package/dist/src/rabitq-ivf/src/index.js +4 -0
  115. package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
  116. package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
  117. package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
  118. package/dist/src/rabitq-ivf/src/prng.js +36 -0
  119. package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
  120. package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
  121. package/dist/src/sema.d.ts +31 -0
  122. package/dist/src/sema.js +63 -0
  123. package/dist/src/store-sqlite.d.ts +184 -0
  124. package/dist/src/store-sqlite.js +942 -0
  125. package/dist/src/store.d.ts +654 -0
  126. package/dist/src/store.js +1612 -0
  127. package/dist/src/vec.d.ts +31 -0
  128. package/dist/src/vec.js +109 -0
  129. package/package.json +1 -1
  130. package/src/mind/graph-search.ts +128 -46
  131. package/src/mind/mind.ts +37 -0
@@ -0,0 +1,264 @@
1
+ // kernel-arith.ts — the field-and-order layer.
2
+ //
3
+ // Identities 0 and 1, then the six primitives the field stands on — add,
4
+ // negate, multiply, reciprocal, sign (plus floor / mod for integer number
5
+ // theory). Everything else is a derivation:
6
+ //
7
+ // subtract = add ∘ negate
8
+ // divide = multiply ∘ reciprocal
9
+ // every comparison = sign ∘ subtract (−1 / 0 / +1 → a truth bit)
10
+ // abs(x) = multiply(sign x, x) (no branch needed)
11
+ // min / max = select on compare (control flow from layer 1)
12
+ // power = repeated multiply (integer) | exp(e·log b) (real, layer 3)
13
+ // gcd = Euclid via mod
14
+ //
15
+ // The arithmetic primitives are POLYMORPHIC over the numeric domains: when every
16
+ // operand is exact (bit/int) they run on bigint, so the result is exact past
17
+ // 2^53 and AGREES with the nand bootstrap (kernel-bits.ts); the moment a real
18
+ // operand appears the whole expression lifts to IEEE doubles, which is what the
19
+ // limit layer needs. This is the hybrid: the bit-vector derivation is the
20
+ // proof, native bigint is the exact hot path, native doubles back the reals.
21
+ //
22
+ // Vector / matrix / polynomial routines (dot, matmul, polyEval, linsolve) take
23
+ // JS arrays rather than the flat Value list an infix operator would, because a
24
+ // matrix has no sensible two-operand surface form; they are exported as pure
25
+ // functions, composed from the same scalar primitives, and tested directly.
26
+ // `linsolve` is Gaussian elimination — structured arithmetic, not a new
27
+ // primitive.
28
+ import { asInt, asReal, bit, int, joinDomain, real, } from "./value.js";
29
+ /** Reduce numeric operands in their join domain: exact bigint when all are
30
+ * bit/int, native double once any is real. `bigOp` and `realOp` are the same
31
+ * fold expressed in each carrier. */
32
+ function reduceNumeric(args, identityBig, bigOp, realOp) {
33
+ const d = joinDomain(args);
34
+ if (d === "real") {
35
+ let acc = Number(identityBig);
36
+ let first = true;
37
+ for (const a of args) {
38
+ const x = asReal(a);
39
+ acc = first ? x : realOp(acc, x);
40
+ first = false;
41
+ }
42
+ return real(acc);
43
+ }
44
+ let acc = identityBig;
45
+ let first = true;
46
+ for (const a of args) {
47
+ const n = asInt(a);
48
+ acc = first ? n : bigOp(acc, n);
49
+ first = false;
50
+ }
51
+ return int(acc);
52
+ }
53
+ // The infix binding tiers of arithmetic notation, loosest to tightest. These
54
+ // are declared ONCE, here, next to the ops they describe; the expression
55
+ // grammar (expr.ts) reads them off the registry, so no parser hardcodes an
56
+ // operator table. Comparisons deliberately declare NO infix binding: a
57
+ // statement like "2+2=4" is a learnt FACT (true/false lives in the corpus),
58
+ // not a computation the ALU should evaluate over the learner's head.
59
+ const ADDITIVE = { precedence: 1 };
60
+ const MULTIPLICATIVE = { precedence: 2 };
61
+ const EXPONENT = { precedence: 3, rightAssoc: true };
62
+ /** Register the arithmetic layer into `r`. */
63
+ export function registerArith(r) {
64
+ // ── identities ──────────────────────────────────────────────────────────
65
+ r.prim("zero", 0, ["0"], () => int(0n));
66
+ r.prim("one", 0, ["1"], () => int(1n));
67
+ // ── primitives ──────────────────────────────────────────────────────────
68
+ // add / multiply are variadic folds (so "sum"/"product" of many is one call);
69
+ // the infix path calls them with exactly two operands.
70
+ r.prim("add", "variadic", ["+", "plus", "sum", "add", "total"], (args) => reduceNumeric(args, 0n, (a, b) => a + b, (a, b) => a + b), { infix: ADDITIVE });
71
+ r.prim("multiply", "variadic", [
72
+ "*",
73
+ "×",
74
+ "·",
75
+ "times",
76
+ "multiply",
77
+ "product",
78
+ ], (args) => reduceNumeric(args, 1n, (a, b) => a * b, (a, b) => a * b), {
79
+ infix: MULTIPLICATIVE,
80
+ });
81
+ r.prim("negate", 1, ["-", "negate", "neg"], (args) => {
82
+ const v = args[0];
83
+ return v.domain === "real" ? real(-v.x) : int(-asInt(v));
84
+ });
85
+ // reciprocal lives in the reals: 1/2 = 0.5, so it lifts to a double (an int
86
+ // result like 1/1 still formats cleanly through the codec).
87
+ r.prim("reciprocal", 1, ["reciprocal", "recip"], (args) => real(1 / asReal(args[0])));
88
+ // sign ∈ {−1, 0, +1}, returned exact (int) so comparisons are exact.
89
+ r.prim("sign", 1, ["sign", "sgn"], (args) => {
90
+ const v = args[0];
91
+ if (v.domain === "real")
92
+ return int(v.x > 0 ? 1n : v.x < 0 ? -1n : 0n);
93
+ const n = asInt(v);
94
+ return int(n > 0n ? 1n : n < 0n ? -1n : 0n);
95
+ });
96
+ // floor / mod — the optional integer-number-theory primitives.
97
+ r.prim("floor", 1, ["floor"], (args) => {
98
+ const v = args[0];
99
+ return v.domain === "real" ? int(BigInt(Math.floor(v.x))) : int(asInt(v));
100
+ });
101
+ // ── derived: the field ─────────────────────────────────────────────────
102
+ r.derive("subtract", 2, ["-", "minus", "subtract", "difference", "less"], (args, ctx) => ctx.apply("add", [args[0], ctx.apply("negate", [args[1]])]), { infix: ADDITIVE });
103
+ r.derive("divide", 2, ["/", "÷", "divide", "over"], (args, ctx) => ctx.apply("multiply", [args[0], ctx.apply("reciprocal", [args[1]])]), { infix: MULTIPLICATIVE });
104
+ // Euclidean-style remainder. Exact for ints; native % for reals.
105
+ r.derive("mod", 2, ["mod", "%", "modulo"], (args, ctx) => {
106
+ void ctx;
107
+ const d = joinDomain(args);
108
+ if (d === "real")
109
+ return real(asReal(args[0]) % asReal(args[1]));
110
+ return int(asInt(args[0]) % asInt(args[1]));
111
+ }, { infix: MULTIPLICATIVE });
112
+ // ── derived: order (every comparison = sign ∘ subtract → a truth bit) ────
113
+ const cmpSign = (args, ctx) => asInt(ctx.apply("sign", [ctx.apply("subtract", [args[0], args[1]])]));
114
+ r.derive("eq", 2, ["=", "==", "equals", "eq"], (args, ctx) => bit(cmpSign(args, ctx) === 0n ? 1 : 0));
115
+ r.derive("ne", 2, ["!=", "≠", "ne"], (args, ctx) => bit(cmpSign(args, ctx) !== 0n ? 1 : 0));
116
+ r.derive("lt", 2, ["<", "lt"], (args, ctx) => bit(cmpSign(args, ctx) < 0n ? 1 : 0));
117
+ r.derive("le", 2, ["<=", "≤", "le"], (args, ctx) => bit(cmpSign(args, ctx) <= 0n ? 1 : 0));
118
+ r.derive("gt", 2, [">", "gt"], (args, ctx) => bit(cmpSign(args, ctx) > 0n ? 1 : 0));
119
+ r.derive("ge", 2, [">=", "≥", "ge"], (args, ctx) => bit(cmpSign(args, ctx) >= 0n ? 1 : 0));
120
+ // ── derived: magnitude / extremes ────────────────────────────────────────
121
+ // abs(x) = sign(x)·x — branch-free.
122
+ r.derive("abs", 1, ["abs", "|x|"], (args, ctx) => ctx.apply("multiply", [ctx.apply("sign", [args[0]]), args[0]]));
123
+ // min / max select on the comparison — the control flow layer 1 provides.
124
+ r.derive("min", 2, ["min"], (args, ctx) => cmpSign(args, ctx) <= 0n ? args[0] : args[1]);
125
+ r.derive("max", 2, ["max"], (args, ctx) => cmpSign(args, ctx) >= 0n ? args[0] : args[1]);
126
+ // ── derived: power ───────────────────────────────────────────────────────
127
+ // Integer exponent → repeated multiply (exact); non-integer or real → fall to
128
+ // the limit layer's exp(e·log b) when it is registered.
129
+ r.derive("power", 2, ["^", "**", "pow", "power"], (args, ctx) => {
130
+ const base = args[0];
131
+ const e = args[1];
132
+ // An INTEGER-VALUED exponent → repeated multiply (exact), even if it arrived
133
+ // as a real that happens to be whole (a derived call may hand a real 2.0).
134
+ // This keeps b^2 exact and avoids exp(e·ln b), which is approximate and
135
+ // undefined for a negative base (ln(−3) = NaN). Only a genuinely fractional
136
+ // exponent falls to the limit layer.
137
+ const eInt = e.domain !== "real"
138
+ ? asInt(e)
139
+ : Number.isInteger(e.x)
140
+ ? BigInt(e.x)
141
+ : null;
142
+ if (eInt !== null) {
143
+ let n = eInt;
144
+ const neg = n < 0n;
145
+ if (neg)
146
+ n = -n;
147
+ let acc = int(1n);
148
+ for (let i = 0n; i < n; i++)
149
+ acc = ctx.apply("multiply", [acc, base]);
150
+ return neg ? ctx.apply("reciprocal", [acc]) : acc;
151
+ }
152
+ // Fractional exponent: b^e = exp(e·ln b), needing the limit layer.
153
+ if (ctx.has("exp") && ctx.has("log")) {
154
+ return ctx.apply("exp", [
155
+ ctx.apply("multiply", [e, ctx.apply("log", [base])]),
156
+ ]);
157
+ }
158
+ return real(Math.pow(asReal(base), asReal(e)));
159
+ }, { infix: EXPONENT });
160
+ // gcd via Euclid (mod) — number theory standing on the integer primitives.
161
+ r.derive("gcd", 2, ["gcd"], (args, ctx) => {
162
+ let a = asInt(args[0]);
163
+ let b = asInt(args[1]);
164
+ a = a < 0n ? -a : a;
165
+ b = b < 0n ? -b : b;
166
+ while (b !== 0n) {
167
+ const t = asInt(ctx.apply("mod", [int(a), int(b)]));
168
+ a = b;
169
+ b = t < 0n ? -t : t;
170
+ }
171
+ return int(a);
172
+ });
173
+ // ── polymorphic inverse (the bridge to the symbol domain) ────────────────
174
+ // The additive inverse of a NUMBER is its negation; the inverse of a SYMBOL is
175
+ // its RESONANT OPPOSITE — found by the host's resonance and pre-resolved into
176
+ // ctx.resonance (see resonance.ts). One op, dispatched on the operand's
177
+ // domain: this is "inverse of 3 is −3, inverse of <a learned form> is its
178
+ // opposite", in any modality. A bit inverts as logical not.
179
+ r.derive("inverse", 1, ["inverse", "opposite", "invert"], (args, ctx) => {
180
+ const v = args[0];
181
+ if (v.domain === "symbol") {
182
+ const opp = ctx.resonance.opposite(v.bytes);
183
+ // No known opposite → leave the form unchanged rather than fabricate one
184
+ // (faithfulness: ALU never invents meaning resonance did not supply).
185
+ return opp ? { domain: "symbol", bytes: opp } : v;
186
+ }
187
+ if (v.domain === "bit")
188
+ return ctx.apply("not", [v]);
189
+ return ctx.apply("negate", [v]);
190
+ });
191
+ // reciprocal already registered as the multiplicative inverse primitive.
192
+ }
193
+ // ── exported array routines (derivations whose natural shape is arrays) ──────
194
+ /** Horner evaluation of a polynomial whose coefficients run constant-first
195
+ * (`coeffs[0]` is the constant term). Pure arithmetic over add/multiply. */
196
+ export function polyEval(coeffs, x) {
197
+ let acc = 0;
198
+ for (let i = coeffs.length - 1; i >= 0; i--)
199
+ acc = acc * x + coeffs[i];
200
+ return acc;
201
+ }
202
+ /** Dot product of two equal-length vectors — a fold of add over multiply. */
203
+ export function dot(a, b) {
204
+ if (a.length !== b.length)
205
+ throw new Error("dot: length mismatch");
206
+ let s = 0;
207
+ for (let i = 0; i < a.length; i++)
208
+ s += a[i] * b[i];
209
+ return s;
210
+ }
211
+ /** Matrix · vector. */
212
+ export function matVec(m, v) {
213
+ return m.map((row) => dot(row, v));
214
+ }
215
+ /** Matrix · matrix. */
216
+ export function matMul(a, b) {
217
+ const n = a.length;
218
+ const k = b.length;
219
+ const p = b[0].length;
220
+ const out = Array.from({ length: n }, () => new Array(p).fill(0));
221
+ for (let i = 0; i < n; i++) {
222
+ for (let j = 0; j < p; j++) {
223
+ let s = 0;
224
+ for (let t = 0; t < k; t++)
225
+ s += a[i][t] * b[t][j];
226
+ out[i][j] = s;
227
+ }
228
+ }
229
+ return out;
230
+ }
231
+ /** Solve A·x = b by Gaussian elimination with partial pivoting — structured
232
+ * arithmetic (add / multiply / divide / compare for the pivot), not a new
233
+ * primitive. Returns x, or null if A is singular to tolerance `tol`. */
234
+ export function linsolve(A, b, tol = 1e-12) {
235
+ const n = A.length;
236
+ // Work on an augmented copy so the inputs are untouched.
237
+ const M = A.map((row, i) => [...row, b[i]]);
238
+ for (let col = 0; col < n; col++) {
239
+ // Partial pivot: the row with the largest |value| in this column.
240
+ let piv = col;
241
+ for (let r = col + 1; r < n; r++) {
242
+ if (Math.abs(M[r][col]) > Math.abs(M[piv][col]))
243
+ piv = r;
244
+ }
245
+ if (Math.abs(M[piv][col]) < tol)
246
+ return null; // singular
247
+ [M[col], M[piv]] = [M[piv], M[col]];
248
+ // Eliminate below.
249
+ for (let r = col + 1; r < n; r++) {
250
+ const f = M[r][col] / M[col][col];
251
+ for (let c = col; c <= n; c++)
252
+ M[r][c] -= f * M[col][c];
253
+ }
254
+ }
255
+ // Back-substitute.
256
+ const x = new Array(n).fill(0);
257
+ for (let i = n - 1; i >= 0; i--) {
258
+ let s = M[i][n];
259
+ for (let j = i + 1; j < n; j++)
260
+ s -= M[i][j] * x[j];
261
+ x[i] = s / M[i][i];
262
+ }
263
+ return x;
264
+ }
@@ -0,0 +1,19 @@
1
+ import type { OpContext, OperationRegistry } from "./operation.js";
2
+ /** Exact addition through the ripple of full_adders. */
3
+ export declare function addBits(ctx: OpContext, a: bigint, b: bigint): bigint;
4
+ /** Exact two's-complement negation. */
5
+ export declare function negateBits(ctx: OpContext, a: bigint): bigint;
6
+ /** Exact shift-add multiplication: for each set bit i of b, add (a << i) to the
7
+ * accumulator. The per-bit gate is an AND mask of the shifted a with bᵢ; the
8
+ * accumulation is rippleAdd — so multiply traces entirely to nand. */
9
+ export declare function mulBits(ctx: OpContext, a: bigint, b: bigint): bigint;
10
+ /** Sign of an integer as {-1, 0, 1}: zero when every bit is zero, −1 when the
11
+ * two's-complement sign bit is set, +1 otherwise — read off the bit array. */
12
+ export declare function signBits(ctx: OpContext, a: bigint): bigint;
13
+ /** Compare via sign(subtract): −1 if a<b, 0 if a=b, +1 if a>b, where subtract is
14
+ * add ∘ negate — so comparison is structured arithmetic, not a new primitive. */
15
+ export declare function compareBits(ctx: OpContext, a: bigint, b: bigint): bigint;
16
+ /** Register the bit-bootstrap ops (int domain) into `r`. They have no surface
17
+ * forms — they are an internal exhibit, exercised by the tests and by anyone
18
+ * who wants to walk the nand→arithmetic chain, not matched from a query. */
19
+ export declare function registerBits(r: OperationRegistry): void;
@@ -0,0 +1,152 @@
1
+ // kernel-bits.ts — the "everything derives from nand" bootstrap, made exact.
2
+ //
3
+ // This is the EXHIBIT that proves the kernel's central claim: arithmetic is not
4
+ // a new primitive, it is a derivation over the logic layer. Here `full_adder`
5
+ // is built from the xor/and/or exposed in kernel-logic.ts (themselves derived
6
+ // from nand alone), and from one full_adder the whole integer field follows:
7
+ //
8
+ // full_adder → ripple add → two's-complement negate → shift-add multiply
9
+ // → sign → compare → (and, with control flow, everything else).
10
+ //
11
+ // It operates on EXACT integers (bigint) so the proof holds past 2^53 where a
12
+ // double would round. Every gate call goes through ctx.apply, so the dependency
13
+ // edges back to nand are literal, runnable source — the tests cross-check each
14
+ // op against native bigint, and the integration arithmetic (kernel-arith.ts)
15
+ // uses native bigint on the hot path, having been proven equal to this here.
16
+ //
17
+ // These ops are registered under a "bits." namespace, distinct from the
18
+ // polymorphic arithmetic of kernel-arith.ts, precisely so the bootstrap is an
19
+ // inspectable, separately-tested artifact and never silently the substrate of a
20
+ // real-number computation.
21
+ import { asInt, bit, int } from "./value.js";
22
+ /** Width-bounded two's-complement little-endian bit array (index 0 = LSB).
23
+ * Width is chosen by the caller wide enough that the signed result cannot
24
+ * overflow, so interpreting the top bit as the sign is always correct. */
25
+ function toBits(n, width) {
26
+ const mod = 1n << BigInt(width);
27
+ let u = ((n % mod) + mod) % mod; // two's-complement representation
28
+ const bits = new Array(width);
29
+ for (let i = 0; i < width; i++) {
30
+ bits[i] = Number(u & 1n);
31
+ u >>= 1n;
32
+ }
33
+ return bits;
34
+ }
35
+ /** Interpret a two's-complement little-endian bit array as a signed bigint. */
36
+ function fromBits(bits) {
37
+ const width = bits.length;
38
+ let u = 0n;
39
+ for (let i = 0; i < width; i++)
40
+ if (bits[i])
41
+ u |= 1n << BigInt(i);
42
+ const signBitSet = bits[width - 1] === 1;
43
+ return signBitSet ? u - (1n << BigInt(width)) : u;
44
+ }
45
+ /** Bits needed to hold |n| (at least 1). */
46
+ function magnitudeBits(n) {
47
+ const a = n < 0n ? -n : n;
48
+ return a === 0n ? 1 : a.toString(2).length;
49
+ }
50
+ /** A single full adder built from the logic gates: sum = a⊕b⊕cin, carry =
51
+ * (a∧b) ∨ (cin ∧ (a⊕b)). Every gate goes through ctx.apply → nand. */
52
+ function fullAdder(ctx, a, b, cin) {
53
+ const A = bit(a), B = bit(b), C = bit(cin);
54
+ const axb = ctx.apply("xor", [A, B]);
55
+ const sum = ctx.apply("xor", [axb, C]);
56
+ const cout = ctx.apply("or", [
57
+ ctx.apply("and", [A, B]),
58
+ ctx.apply("and", [C, axb]),
59
+ ]);
60
+ return {
61
+ sum: sum.domain === "bit" ? sum.b : 0,
62
+ cout: cout.domain === "bit" ? cout.b : 0,
63
+ };
64
+ }
65
+ /** Ripple-carry add of two two's-complement bit arrays (equal width). */
66
+ function rippleAdd(ctx, x, y) {
67
+ const width = x.length;
68
+ const out = new Array(width);
69
+ let carry = 0;
70
+ for (let i = 0; i < width; i++) {
71
+ const { sum, cout } = fullAdder(ctx, x[i], y[i], carry);
72
+ out[i] = sum;
73
+ carry = cout;
74
+ }
75
+ return out;
76
+ }
77
+ /** Bitwise NOT of a bit array, via the not gate. */
78
+ function notBits(ctx, x) {
79
+ return x.map((b) => {
80
+ const r = ctx.apply("not", [bit(b)]);
81
+ return (r.domain === "bit" ? r.b : 0);
82
+ });
83
+ }
84
+ /** Two's-complement negate: invert every bit, then add one. */
85
+ function negateBitsArr(ctx, x) {
86
+ const width = x.length;
87
+ const one = toBits(1n, width);
88
+ return rippleAdd(ctx, notBits(ctx, x), one);
89
+ }
90
+ // ── public pure functions (used by the tests and the explicit ops) ──────────
91
+ /** Exact addition through the ripple of full_adders. */
92
+ export function addBits(ctx, a, b) {
93
+ const width = Math.max(magnitudeBits(a), magnitudeBits(b)) + 2;
94
+ return fromBits(rippleAdd(ctx, toBits(a, width), toBits(b, width)));
95
+ }
96
+ /** Exact two's-complement negation. */
97
+ export function negateBits(ctx, a) {
98
+ const width = magnitudeBits(a) + 2;
99
+ return fromBits(negateBitsArr(ctx, toBits(a, width)));
100
+ }
101
+ /** Exact shift-add multiplication: for each set bit i of b, add (a << i) to the
102
+ * accumulator. The per-bit gate is an AND mask of the shifted a with bᵢ; the
103
+ * accumulation is rippleAdd — so multiply traces entirely to nand. */
104
+ export function mulBits(ctx, a, b) {
105
+ const width = magnitudeBits(a) + magnitudeBits(b) + 2;
106
+ const aBits = toBits(a, width);
107
+ const bBits = toBits(b, width);
108
+ let acc = toBits(0n, width);
109
+ for (let i = 0; i < width; i++) {
110
+ if (bBits[i] === 0)
111
+ continue;
112
+ // a shifted left by i (within width), masked by bᵢ (= 1 here).
113
+ const shifted = new Array(width);
114
+ for (let k = 0; k < width; k++) {
115
+ const src = k - i >= 0 ? aBits[k - i] : 0;
116
+ const m = ctx.apply("and", [bit(src), bit(bBits[i])]);
117
+ shifted[k] = (m.domain === "bit" ? m.b : 0);
118
+ }
119
+ acc = rippleAdd(ctx, acc, shifted);
120
+ }
121
+ return fromBits(acc);
122
+ }
123
+ /** Sign of an integer as {-1, 0, 1}: zero when every bit is zero, −1 when the
124
+ * two's-complement sign bit is set, +1 otherwise — read off the bit array. */
125
+ export function signBits(ctx, a) {
126
+ if (a === 0n)
127
+ return 0n;
128
+ const width = magnitudeBits(a) + 2;
129
+ const bits = toBits(a, width);
130
+ return bits[width - 1] === 1 ? -1n : 1n;
131
+ }
132
+ /** Compare via sign(subtract): −1 if a<b, 0 if a=b, +1 if a>b, where subtract is
133
+ * add ∘ negate — so comparison is structured arithmetic, not a new primitive. */
134
+ export function compareBits(ctx, a, b) {
135
+ return signBits(ctx, addBits(ctx, a, negateBits(ctx, b)));
136
+ }
137
+ /** Register the bit-bootstrap ops (int domain) into `r`. They have no surface
138
+ * forms — they are an internal exhibit, exercised by the tests and by anyone
139
+ * who wants to walk the nand→arithmetic chain, not matched from a query. */
140
+ export function registerBits(r) {
141
+ // full_adder exposed as a 3-bit op returning the 2-bit {sum, carry} as an int
142
+ // 0..3 (carry in bit 1, sum in bit 0) so it is callable/testable on its own.
143
+ r.derive("bits.fullAdder", 3, [], (args, ctx) => {
144
+ const s = fullAdder(ctx, asInt(args[0]) === 0n ? 0 : 1, asInt(args[1]) === 0n ? 0 : 1, asInt(args[2]) === 0n ? 0 : 1);
145
+ return int(BigInt(s.sum) | (BigInt(s.cout) << 1n));
146
+ });
147
+ r.derive("bits.add", 2, [], (args, ctx) => int(addBits(ctx, asInt(args[0]), asInt(args[1]))));
148
+ r.derive("bits.negate", 1, [], (args, ctx) => int(negateBits(ctx, asInt(args[0]))));
149
+ r.derive("bits.multiply", 2, [], (args, ctx) => int(mulBits(ctx, asInt(args[0]), asInt(args[1]))));
150
+ r.derive("bits.sign", 1, [], (args, ctx) => int(signBits(ctx, asInt(args[0]))));
151
+ r.derive("bits.compare", 2, [], (args, ctx) => int(compareBits(ctx, asInt(args[0]), asInt(args[1]))));
152
+ }
@@ -0,0 +1,4 @@
1
+ import type { OperationRegistry } from "./operation.js";
2
+ /** Register the logic layer into `r`. Idempotent in effect (re-registering
3
+ * overwrites with the same definitions). */
4
+ export declare function registerLogic(r: OperationRegistry): void;
@@ -0,0 +1,60 @@
1
+ // kernel-logic.ts — the completeness layer.
2
+ //
3
+ // One primitive: nand. It is functionally complete on its own, so EVERY other
4
+ // gate is a derivation over it, registered with `derive` and composing only
5
+ // through ctx.apply — the dependency edges are the literal source. This is the
6
+ // irreducible root of the whole library: arithmetic's bit bootstrap
7
+ // (kernel-bits.ts) builds full_adder from the xor/and/or exposed here, and from
8
+ // there add → multiply → everything.
9
+ //
10
+ // not(a) = nand(a, a)
11
+ // and(a, b) = not(nand(a, b))
12
+ // or(a, b) = nand(not a, not b) (De Morgan)
13
+ // nor(a, b) = not(or(a, b))
14
+ // xor(a, b) = or(and(a, not b), and(not a, b))
15
+ // xnor(a, b) = not(xor(a, b))
16
+ // implies(a, b) = or(not a, b)
17
+ // iff(a, b) = xnor(a, b)
18
+ // mux(s, a, b) = or(and(not s, a), and(s, b)) — select b when s, else a;
19
+ // the bridge to control flow (conditional selection).
20
+ //
21
+ // `not`, `and`, `or` are exposed for ergonomics but are themselves derived —
22
+ // only nand is primitive.
23
+ import { asBit, bit } from "./value.js";
24
+ /** Register the logic layer into `r`. Idempotent in effect (re-registering
25
+ * overwrites with the same definitions). */
26
+ export function registerLogic(r) {
27
+ // The one irreducible gate. ¬(a ∧ b).
28
+ r.prim("nand", 2, [], (args) => {
29
+ const a = asBit(args[0]);
30
+ const b = asBit(args[1]);
31
+ return bit(a & b ? 0 : 1);
32
+ });
33
+ // Exposed-but-derived basic gates.
34
+ r.derive("not", 1, ["not", "!", "~", "¬"], (args, ctx) => ctx.apply("nand", [args[0], args[0]]));
35
+ r.derive("and", 2, ["and", "&", "&&", "∧"], (args, ctx) => ctx.apply("not", [ctx.apply("nand", [args[0], args[1]])]));
36
+ r.derive("or", 2, ["or", "|", "||", "∨"], (args, ctx) => {
37
+ const na = ctx.apply("not", [args[0]]);
38
+ const nb = ctx.apply("not", [args[1]]);
39
+ return ctx.apply("nand", [na, nb]);
40
+ });
41
+ // Fully derived gates.
42
+ r.derive("nor", 2, ["nor", "⊽"], (args, ctx) => ctx.apply("not", [ctx.apply("or", [args[0], args[1]])]));
43
+ r.derive("xor", 2, ["xor", "^", "⊕"], (args, ctx) => {
44
+ const a = args[0], b = args[1];
45
+ const left = ctx.apply("and", [a, ctx.apply("not", [b])]);
46
+ const right = ctx.apply("and", [ctx.apply("not", [a]), b]);
47
+ return ctx.apply("or", [left, right]);
48
+ });
49
+ r.derive("xnor", 2, ["xnor", "⊙"], (args, ctx) => ctx.apply("not", [ctx.apply("xor", [args[0], args[1]])]));
50
+ r.derive("implies", 2, ["implies", "=>", "→", "⇒"], (args, ctx) => ctx.apply("or", [ctx.apply("not", [args[0]]), args[1]]));
51
+ r.derive("iff", 2, ["iff", "<=>", "↔", "⇔"], (args, ctx) => ctx.apply("xnor", [args[0], args[1]]));
52
+ // mux(s, a, b): select a when s = 0, b when s = 1. The bridge to control
53
+ // flow — conditional selection, and (with recursion in the caller) looping.
54
+ r.derive("mux", 3, ["mux", "select", "?:"], (args, ctx) => {
55
+ const s = args[0], a = args[1], b = args[2];
56
+ const lo = ctx.apply("and", [ctx.apply("not", [s]), a]);
57
+ const hi = ctx.apply("and", [s, b]);
58
+ return ctx.apply("or", [lo, hi]);
59
+ });
60
+ }
@@ -0,0 +1,3 @@
1
+ import type { OperationRegistry } from "./operation.js";
2
+ /** Register the n-dimensional layer into `r`. All ops are STRUCTURAL. */
3
+ export declare function registerNd(r: OperationRegistry): void;