@hviana/sema 0.1.4 → 0.1.5

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 (122) hide show
  1. package/dist/example/demo.js +25 -25
  2. package/dist/example/train_base.d.ts +21 -19
  3. package/dist/example/train_base.js +1952 -1684
  4. package/dist/src/alphabet.d.ts +3 -3
  5. package/dist/src/alphabet.js +27 -24
  6. package/dist/src/alu/src/alu.d.ts +194 -169
  7. package/dist/src/alu/src/alu.js +414 -374
  8. package/dist/src/alu/src/expr.d.ts +43 -36
  9. package/dist/src/alu/src/expr.js +278 -252
  10. package/dist/src/alu/src/index.d.ts +98 -9
  11. package/dist/src/alu/src/index.js +63 -9
  12. package/dist/src/alu/src/kernel-arith.d.ts +5 -1
  13. package/dist/src/alu/src/kernel-arith.js +285 -195
  14. package/dist/src/alu/src/kernel-bits.d.ts +5 -1
  15. package/dist/src/alu/src/kernel-bits.js +115 -81
  16. package/dist/src/alu/src/kernel-logic.js +63 -33
  17. package/dist/src/alu/src/kernel-nd.js +195 -155
  18. package/dist/src/alu/src/kernel-numeric.d.ts +80 -16
  19. package/dist/src/alu/src/kernel-numeric.js +331 -259
  20. package/dist/src/alu/src/operation.d.ts +132 -112
  21. package/dist/src/alu/src/operation.js +163 -149
  22. package/dist/src/alu/src/parser.d.ts +175 -168
  23. package/dist/src/alu/src/parser.js +421 -382
  24. package/dist/src/alu/src/resonance.d.ts +25 -16
  25. package/dist/src/alu/src/resonance.js +56 -49
  26. package/dist/src/alu/src/text.d.ts +7 -3
  27. package/dist/src/alu/src/text.js +37 -31
  28. package/dist/src/alu/src/value.d.ts +14 -14
  29. package/dist/src/alu/src/value.js +160 -150
  30. package/dist/src/alu/test/alu.test.js +656 -543
  31. package/dist/src/bytes.d.ts +5 -1
  32. package/dist/src/bytes.js +40 -33
  33. package/dist/src/config.d.ts +102 -102
  34. package/dist/src/config.js +83 -83
  35. package/dist/src/derive/src/deduction.d.ts +62 -60
  36. package/dist/src/derive/src/deduction.js +109 -103
  37. package/dist/src/derive/src/index.d.ts +7 -1
  38. package/dist/src/derive/src/priority-queue.d.ts +8 -8
  39. package/dist/src/derive/src/priority-queue.js +61 -57
  40. package/dist/src/derive/src/rewrite.d.ts +18 -15
  41. package/dist/src/derive/src/rewrite.js +67 -59
  42. package/dist/src/derive/src/trie.d.ts +56 -56
  43. package/dist/src/derive/src/trie.js +179 -175
  44. package/dist/src/derive/test/derive.test.js +100 -96
  45. package/dist/src/extension.d.ts +16 -13
  46. package/dist/src/geometry.d.ts +42 -17
  47. package/dist/src/geometry.js +266 -235
  48. package/dist/src/index.d.ts +17 -2
  49. package/dist/src/index.js +7 -1
  50. package/dist/src/ingest-cache.d.ts +30 -25
  51. package/dist/src/ingest-cache.js +127 -108
  52. package/dist/src/mind/articulation.d.ts +5 -1
  53. package/dist/src/mind/articulation.js +112 -77
  54. package/dist/src/mind/attention.d.ts +108 -40
  55. package/dist/src/mind/attention.js +871 -749
  56. package/dist/src/mind/canonical.d.ts +19 -4
  57. package/dist/src/mind/canonical.js +31 -27
  58. package/dist/src/mind/graph-search.d.ts +225 -201
  59. package/dist/src/mind/graph-search.js +821 -742
  60. package/dist/src/mind/index.d.ts +10 -2
  61. package/dist/src/mind/junction.d.ts +58 -31
  62. package/dist/src/mind/junction.js +237 -172
  63. package/dist/src/mind/learning.d.ts +52 -16
  64. package/dist/src/mind/learning.js +165 -143
  65. package/dist/src/mind/match.d.ts +69 -20
  66. package/dist/src/mind/match.js +318 -259
  67. package/dist/src/mind/mechanisms/alu.js +16 -16
  68. package/dist/src/mind/mechanisms/cast.d.ts +13 -9
  69. package/dist/src/mind/mechanisms/cast.js +456 -363
  70. package/dist/src/mind/mechanisms/confluence.d.ts +12 -8
  71. package/dist/src/mind/mechanisms/confluence.js +183 -152
  72. package/dist/src/mind/mechanisms/cover.d.ts +8 -2
  73. package/dist/src/mind/mechanisms/cover.js +210 -148
  74. package/dist/src/mind/mechanisms/extraction.d.ts +34 -8
  75. package/dist/src/mind/mechanisms/extraction.js +288 -234
  76. package/dist/src/mind/mechanisms/recall.d.ts +10 -6
  77. package/dist/src/mind/mechanisms/recall.js +185 -126
  78. package/dist/src/mind/mind.d.ts +154 -129
  79. package/dist/src/mind/mind.js +288 -258
  80. package/dist/src/mind/pipeline-mechanism.d.ts +124 -112
  81. package/dist/src/mind/pipeline-mechanism.js +172 -161
  82. package/dist/src/mind/pipeline.d.ts +14 -4
  83. package/dist/src/mind/pipeline.js +189 -125
  84. package/dist/src/mind/primitives.d.ts +32 -8
  85. package/dist/src/mind/primitives.js +117 -99
  86. package/dist/src/mind/rationale.d.ts +98 -86
  87. package/dist/src/mind/rationale.js +121 -113
  88. package/dist/src/mind/reasoning.d.ts +13 -2
  89. package/dist/src/mind/reasoning.js +166 -129
  90. package/dist/src/mind/recognition.d.ts +4 -1
  91. package/dist/src/mind/recognition.js +208 -183
  92. package/dist/src/mind/resonance.d.ts +22 -5
  93. package/dist/src/mind/resonance.js +0 -0
  94. package/dist/src/mind/trace.d.ts +25 -6
  95. package/dist/src/mind/trace.js +58 -50
  96. package/dist/src/mind/traverse.d.ts +58 -16
  97. package/dist/src/mind/traverse.js +357 -304
  98. package/dist/src/mind/types.d.ts +127 -120
  99. package/dist/src/mind/types.js +69 -60
  100. package/dist/src/rabitq-hnsw/src/database.d.ts +179 -177
  101. package/dist/src/rabitq-hnsw/src/database.js +359 -342
  102. package/dist/src/rabitq-hnsw/src/heap.d.ts +12 -12
  103. package/dist/src/rabitq-hnsw/src/heap.js +80 -75
  104. package/dist/src/rabitq-hnsw/src/hnsw.d.ts +103 -103
  105. package/dist/src/rabitq-hnsw/src/hnsw.js +454 -428
  106. package/dist/src/rabitq-hnsw/src/index.d.ts +6 -1
  107. package/dist/src/rabitq-hnsw/src/prng.d.ts +10 -10
  108. package/dist/src/rabitq-hnsw/src/prng.js +27 -25
  109. package/dist/src/rabitq-hnsw/src/rabitq.d.ts +69 -69
  110. package/dist/src/rabitq-hnsw/src/rabitq.js +262 -246
  111. package/dist/src/rabitq-hnsw/src/store.d.ts +132 -132
  112. package/dist/src/rabitq-hnsw/src/store.js +843 -752
  113. package/dist/src/rabitq-hnsw/test/hnsw.test.js +1054 -805
  114. package/dist/src/sema.d.ts +13 -9
  115. package/dist/src/sema.js +40 -26
  116. package/dist/src/store-sqlite.d.ts +166 -144
  117. package/dist/src/store-sqlite.js +660 -578
  118. package/dist/src/store.d.ts +630 -593
  119. package/dist/src/store.js +1581 -1440
  120. package/dist/src/vec.d.ts +9 -5
  121. package/dist/src/vec.js +73 -61
  122. package/package.json +2 -2
@@ -25,30 +25,30 @@
25
25
  // functions, composed from the same scalar primitives, and tested directly.
26
26
  // `linsolve` is Gaussian elimination — structured arithmetic, not a new
27
27
  // primitive.
28
- import { asInt, asReal, bit, int, joinDomain, real, } from "./value.js";
28
+ import { asInt, asReal, bit, int, joinDomain, real } from "./value.js";
29
29
  /** Reduce numeric operands in their join domain: exact bigint when all are
30
30
  * bit/int, native double once any is real. `bigOp` and `realOp` are the same
31
31
  * fold expressed in each carrier. */
32
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;
33
+ const d = joinDomain(args);
34
+ if (d === "real") {
35
+ let acc = Number(identityBig);
45
36
  let first = true;
46
37
  for (const a of args) {
47
- const n = asInt(a);
48
- acc = first ? n : bigOp(acc, n);
49
- first = false;
38
+ const x = asReal(a);
39
+ acc = first ? x : realOp(acc, x);
40
+ first = false;
50
41
  }
51
- return int(acc);
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
52
  }
53
53
  // The infix binding tiers of arithmetic notation, loosest to tightest. These
54
54
  // are declared ONCE, here, next to the ops they describe; the expression
@@ -61,204 +61,294 @@ const MULTIPLICATIVE = { precedence: 2 };
61
61
  const EXPONENT = { precedence: 3, rightAssoc: true };
62
62
  /** Register the arithmetic layer into `r`. */
63
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.
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(
71
+ "add",
72
+ "variadic",
73
+ ["+", "plus", "sum", "add", "total"],
74
+ (args) => reduceNumeric(args, 0n, (a, b) => a + b, (a, b) => a + b),
75
+ { infix: ADDITIVE },
76
+ );
77
+ r.prim(
78
+ "multiply",
79
+ "variadic",
80
+ [
81
+ "*",
82
+ "×",
83
+ "·",
84
+ "times",
85
+ "multiply",
86
+ "product",
87
+ ],
88
+ (args) => reduceNumeric(args, 1n, (a, b) => a * b, (a, b) => a * b),
89
+ {
90
+ infix: MULTIPLICATIVE,
91
+ },
92
+ );
93
+ r.prim("negate", 1, ["-", "negate", "neg"], (args) => {
94
+ const v = args[0];
95
+ return v.domain === "real" ? real(-v.x) : int(-asInt(v));
96
+ });
97
+ // reciprocal lives in the reals: 1/2 = 0.5, so it lifts to a double (an int
98
+ // result like 1/1 still formats cleanly through the codec).
99
+ r.prim(
100
+ "reciprocal",
101
+ 1,
102
+ ["reciprocal", "recip"],
103
+ (args) => real(1 / asReal(args[0])),
104
+ );
105
+ // sign ∈ {−1, 0, +1}, returned exact (int) so comparisons are exact.
106
+ r.prim("sign", 1, ["sign", "sgn"], (args) => {
107
+ const v = args[0];
108
+ if (v.domain === "real") {
109
+ return int(v.x > 0 ? 1n : v.x < 0 ? -1n : 0n);
110
+ }
111
+ const n = asInt(v);
112
+ return int(n > 0n ? 1n : n < 0n ? -1n : 0n);
113
+ });
114
+ // floor / mod the optional integer-number-theory primitives.
115
+ r.prim("floor", 1, ["floor"], (args) => {
116
+ const v = args[0];
117
+ return v.domain === "real" ? int(BigInt(Math.floor(v.x))) : int(asInt(v));
118
+ });
119
+ // ── derived: the field ─────────────────────────────────────────────────
120
+ r.derive(
121
+ "subtract",
122
+ 2,
123
+ ["-", "minus", "subtract", "difference", "less"],
124
+ (args, ctx) => ctx.apply("add", [args[0], ctx.apply("negate", [args[1]])]),
125
+ { infix: ADDITIVE },
126
+ );
127
+ r.derive(
128
+ "divide",
129
+ 2,
130
+ ["/", "÷", "divide", "over"],
131
+ (args, ctx) =>
132
+ ctx.apply("multiply", [args[0], ctx.apply("reciprocal", [args[1]])]),
133
+ { infix: MULTIPLICATIVE },
134
+ );
135
+ // Euclidean-style remainder. Exact for ints; native % for reals.
136
+ r.derive("mod", 2, ["mod", "%", "modulo"], (args, ctx) => {
137
+ void ctx;
138
+ const d = joinDomain(args);
139
+ if (d === "real") {
140
+ return real(asReal(args[0]) % asReal(args[1]));
141
+ }
142
+ return int(asInt(args[0]) % asInt(args[1]));
143
+ }, { infix: MULTIPLICATIVE });
144
+ // ── derived: order (every comparison = sign subtract → a truth bit) ────
145
+ const cmpSign = (args, ctx) =>
146
+ asInt(ctx.apply("sign", [ctx.apply("subtract", [args[0], args[1]])]));
147
+ r.derive(
148
+ "eq",
149
+ 2,
150
+ ["=", "==", "equals", "eq"],
151
+ (args, ctx) => bit(cmpSign(args, ctx) === 0n ? 1 : 0),
152
+ );
153
+ r.derive(
154
+ "ne",
155
+ 2,
156
+ ["!=", "≠", "ne"],
157
+ (args, ctx) => bit(cmpSign(args, ctx) !== 0n ? 1 : 0),
158
+ );
159
+ r.derive(
160
+ "lt",
161
+ 2,
162
+ ["<", "lt"],
163
+ (args, ctx) => bit(cmpSign(args, ctx) < 0n ? 1 : 0),
164
+ );
165
+ r.derive(
166
+ "le",
167
+ 2,
168
+ ["<=", "≤", "le"],
169
+ (args, ctx) => bit(cmpSign(args, ctx) <= 0n ? 1 : 0),
170
+ );
171
+ r.derive(
172
+ "gt",
173
+ 2,
174
+ [">", "gt"],
175
+ (args, ctx) => bit(cmpSign(args, ctx) > 0n ? 1 : 0),
176
+ );
177
+ r.derive(
178
+ "ge",
179
+ 2,
180
+ [">=", "≥", "ge"],
181
+ (args, ctx) => bit(cmpSign(args, ctx) >= 0n ? 1 : 0),
182
+ );
183
+ // ── derived: magnitude / extremes ────────────────────────────────────────
184
+ // abs(x) = sign(x)·x branch-free.
185
+ r.derive(
186
+ "abs",
187
+ 1,
188
+ ["abs", "|x|"],
189
+ (args, ctx) =>
190
+ ctx.apply("multiply", [ctx.apply("sign", [args[0]]), args[0]]),
191
+ );
192
+ // min / max select on the comparison — the control flow layer 1 provides.
193
+ r.derive(
194
+ "min",
195
+ 2,
196
+ ["min"],
197
+ (args, ctx) => cmpSign(args, ctx) <= 0n ? args[0] : args[1],
198
+ );
199
+ r.derive(
200
+ "max",
201
+ 2,
202
+ ["max"],
203
+ (args, ctx) => cmpSign(args, ctx) >= 0n ? args[0] : args[1],
204
+ );
205
+ // ── derived: power ───────────────────────────────────────────────────────
206
+ // Integer exponent → repeated multiply (exact); non-integer or real → fall to
207
+ // the limit layer's exp(e·log b) when it is registered.
208
+ r.derive("power", 2, ["^", "**", "pow", "power"], (args, ctx) => {
209
+ const base = args[0];
210
+ const e = args[1];
211
+ // An INTEGER-VALUED exponent → repeated multiply (exact), even if it arrived
212
+ // as a real that happens to be whole (a derived call may hand a real 2.0).
213
+ // This keeps b^2 exact and avoids exp(e·ln b), which is approximate and
214
+ // undefined for a negative base (ln(−3) = NaN). Only a genuinely fractional
215
+ // exponent falls to the limit layer.
216
+ const eInt = e.domain !== "real"
217
+ ? asInt(e)
218
+ : Number.isInteger(e.x)
219
+ ? BigInt(e.x)
220
+ : null;
221
+ if (eInt !== null) {
222
+ let n = eInt;
223
+ const neg = n < 0n;
224
+ if (neg) {
225
+ n = -n;
226
+ }
227
+ let acc = int(1n);
228
+ for (let i = 0n; i < n; i++) {
229
+ acc = ctx.apply("multiply", [acc, base]);
230
+ }
231
+ return neg ? ctx.apply("reciprocal", [acc]) : acc;
232
+ }
233
+ // Fractional exponent: b^e = exp(e·ln b), needing the limit layer.
234
+ if (ctx.has("exp") && ctx.has("log")) {
235
+ return ctx.apply("exp", [
236
+ ctx.apply("multiply", [e, ctx.apply("log", [base])]),
237
+ ]);
238
+ }
239
+ return real(Math.pow(asReal(base), asReal(e)));
240
+ }, { infix: EXPONENT });
241
+ // gcd via Euclid (mod) — number theory standing on the integer primitives.
242
+ r.derive("gcd", 2, ["gcd"], (args, ctx) => {
243
+ let a = asInt(args[0]);
244
+ let b = asInt(args[1]);
245
+ a = a < 0n ? -a : a;
246
+ b = b < 0n ? -b : b;
247
+ while (b !== 0n) {
248
+ const t = asInt(ctx.apply("mod", [int(a), int(b)]));
249
+ a = b;
250
+ b = t < 0n ? -t : t;
251
+ }
252
+ return int(a);
253
+ });
254
+ // ── polymorphic inverse (the bridge to the symbol domain) ────────────────
255
+ // The additive inverse of a NUMBER is its negation; the inverse of a SYMBOL is
256
+ // its RESONANT OPPOSITE — found by the host's resonance and pre-resolved into
257
+ // ctx.resonance (see resonance.ts). One op, dispatched on the operand's
258
+ // domain: this is "inverse of 3 is −3, inverse of <a learned form> is its
259
+ // opposite", in any modality. A bit inverts as logical not.
260
+ r.derive("inverse", 1, ["inverse", "opposite", "invert"], (args, ctx) => {
261
+ const v = args[0];
262
+ if (v.domain === "symbol") {
263
+ const opp = ctx.resonance.opposite(v.bytes);
264
+ // No known opposite → leave the form unchanged rather than fabricate one
265
+ // (faithfulness: ALU never invents meaning resonance did not supply).
266
+ return opp ? { domain: "symbol", bytes: opp } : v;
267
+ }
268
+ if (v.domain === "bit") {
269
+ return ctx.apply("not", [v]);
270
+ }
271
+ return ctx.apply("negate", [v]);
272
+ });
273
+ // reciprocal already registered as the multiplicative inverse primitive.
192
274
  }
193
275
  // ── exported array routines (derivations whose natural shape is arrays) ──────
194
276
  /** Horner evaluation of a polynomial whose coefficients run constant-first
195
277
  * (`coeffs[0]` is the constant term). Pure arithmetic over add/multiply. */
196
278
  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;
279
+ let acc = 0;
280
+ for (let i = coeffs.length - 1; i >= 0; i--) {
281
+ acc = acc * x + coeffs[i];
282
+ }
283
+ return acc;
201
284
  }
202
285
  /** Dot product of two equal-length vectors — a fold of add over multiply. */
203
286
  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;
287
+ if (a.length !== b.length) {
288
+ throw new Error("dot: length mismatch");
289
+ }
290
+ let s = 0;
291
+ for (let i = 0; i < a.length; i++) {
292
+ s += a[i] * b[i];
293
+ }
294
+ return s;
210
295
  }
211
296
  /** Matrix · vector. */
212
297
  export function matVec(m, v) {
213
- return m.map((row) => dot(row, v));
298
+ return m.map((row) => dot(row, v));
214
299
  }
215
300
  /** Matrix · matrix. */
216
301
  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
- }
302
+ const n = a.length;
303
+ const k = b.length;
304
+ const p = b[0].length;
305
+ const out = Array.from({ length: n }, () => new Array(p).fill(0));
306
+ for (let i = 0; i < n; i++) {
307
+ for (let j = 0; j < p; j++) {
308
+ let s = 0;
309
+ for (let t = 0; t < k; t++) {
310
+ s += a[i][t] * b[t][j];
311
+ }
312
+ out[i][j] = s;
228
313
  }
229
- return out;
314
+ }
315
+ return out;
230
316
  }
231
317
  /** Solve A·x = b by Gaussian elimination with partial pivoting — structured
232
318
  * arithmetic (add / multiply / divide / compare for the pivot), not a new
233
319
  * primitive. Returns x, or null if A is singular to tolerance `tol`. */
234
320
  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
- }
321
+ const n = A.length;
322
+ // Work on an augmented copy so the inputs are untouched.
323
+ const M = A.map((row, i) => [...row, b[i]]);
324
+ for (let col = 0; col < n; col++) {
325
+ // Partial pivot: the row with the largest |value| in this column.
326
+ let piv = col;
327
+ for (let r = col + 1; r < n; r++) {
328
+ if (Math.abs(M[r][col]) > Math.abs(M[piv][col])) {
329
+ piv = r;
330
+ }
331
+ }
332
+ if (Math.abs(M[piv][col]) < tol) {
333
+ return null; // singular
334
+ }
335
+ [M[col], M[piv]] = [M[piv], M[col]];
336
+ // Eliminate below.
337
+ for (let r = col + 1; r < n; r++) {
338
+ const f = M[r][col] / M[col][col];
339
+ for (let c = col; c <= n; c++) {
340
+ M[r][c] -= f * M[col][c];
341
+ }
254
342
  }
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];
343
+ }
344
+ // Back-substitute.
345
+ const x = new Array(n).fill(0);
346
+ for (let i = n - 1; i >= 0; i--) {
347
+ let s = M[i][n];
348
+ for (let j = i + 1; j < n; j++) {
349
+ s -= M[i][j] * x[j];
262
350
  }
263
- return x;
351
+ x[i] = s / M[i][i];
352
+ }
353
+ return x;
264
354
  }
@@ -12,7 +12,11 @@ export declare function mulBits(ctx: OpContext, a: bigint, b: bigint): bigint;
12
12
  export declare function signBits(ctx: OpContext, a: bigint): bigint;
13
13
  /** Compare via sign(subtract): −1 if a<b, 0 if a=b, +1 if a>b, where subtract is
14
14
  * add ∘ negate — so comparison is structured arithmetic, not a new primitive. */
15
- export declare function compareBits(ctx: OpContext, a: bigint, b: bigint): bigint;
15
+ export declare function compareBits(
16
+ ctx: OpContext,
17
+ a: bigint,
18
+ b: bigint,
19
+ ): bigint;
16
20
  /** Register the bit-bootstrap ops (int domain) into `r`. They have no surface
17
21
  * forms — they are an internal exhibit, exercised by the tests and by anyone
18
22
  * who wants to walk the nand→arithmetic chain, not matched from a query. */