@hviana/sema 0.1.5 → 0.1.7
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.
- package/AGENTS.md +6 -5
- package/CITATION.cff +49 -0
- package/HOW_IT_WORKS.md +11 -12
- package/README.md +7 -5
- package/dist/example/demo.js +25 -25
- package/dist/example/train_base.d.ts +19 -21
- package/dist/example/train_base.js +1700 -1952
- package/dist/src/alphabet.d.ts +3 -3
- package/dist/src/alphabet.js +24 -27
- package/dist/src/alu/src/alu.d.ts +169 -194
- package/dist/src/alu/src/alu.js +374 -414
- package/dist/src/alu/src/expr.d.ts +36 -43
- package/dist/src/alu/src/expr.js +252 -278
- package/dist/src/alu/src/index.d.ts +9 -98
- package/dist/src/alu/src/index.js +10 -64
- package/dist/src/alu/src/kernel-arith.d.ts +1 -5
- package/dist/src/alu/src/kernel-arith.js +195 -285
- package/dist/src/alu/src/kernel-bits.d.ts +1 -5
- package/dist/src/alu/src/kernel-bits.js +81 -115
- package/dist/src/alu/src/kernel-logic.js +33 -63
- package/dist/src/alu/src/kernel-nd.js +155 -195
- package/dist/src/alu/src/kernel-numeric.d.ts +16 -80
- package/dist/src/alu/src/kernel-numeric.js +259 -331
- package/dist/src/alu/src/operation.d.ts +112 -132
- package/dist/src/alu/src/operation.js +149 -163
- package/dist/src/alu/src/parser.d.ts +168 -175
- package/dist/src/alu/src/parser.js +382 -421
- package/dist/src/alu/src/resonance.d.ts +16 -25
- package/dist/src/alu/src/resonance.js +49 -56
- package/dist/src/alu/src/text.d.ts +3 -7
- package/dist/src/alu/src/text.js +31 -37
- package/dist/src/alu/src/value.d.ts +14 -14
- package/dist/src/alu/src/value.js +150 -160
- package/dist/src/alu/test/alu.test.js +543 -656
- package/dist/src/bytes.d.ts +1 -5
- package/dist/src/bytes.js +33 -40
- package/dist/src/config.d.ts +99 -102
- package/dist/src/config.js +78 -83
- package/dist/src/derive/src/deduction.d.ts +60 -62
- package/dist/src/derive/src/deduction.js +103 -109
- package/dist/src/derive/src/index.d.ts +1 -7
- package/dist/src/derive/src/priority-queue.d.ts +8 -8
- package/dist/src/derive/src/priority-queue.js +57 -61
- package/dist/src/derive/src/rewrite.d.ts +15 -18
- package/dist/src/derive/src/rewrite.js +59 -67
- package/dist/src/derive/src/trie.d.ts +56 -56
- package/dist/src/derive/src/trie.js +175 -179
- package/dist/src/derive/test/derive.test.js +96 -100
- package/dist/src/extension.d.ts +13 -16
- package/dist/src/geometry.d.ts +29 -43
- package/dist/src/geometry.js +324 -268
- package/dist/src/index.d.ts +2 -17
- package/dist/src/index.js +2 -12
- package/dist/src/ingest-cache.d.ts +25 -30
- package/dist/src/ingest-cache.js +108 -127
- package/dist/src/mind/articulation.d.ts +1 -5
- package/dist/src/mind/articulation.js +77 -112
- package/dist/src/mind/attention.d.ts +40 -108
- package/dist/src/mind/attention.js +754 -872
- package/dist/src/mind/canonical.d.ts +4 -19
- package/dist/src/mind/canonical.js +27 -31
- package/dist/src/mind/graph-search.d.ts +201 -225
- package/dist/src/mind/graph-search.js +742 -821
- package/dist/src/mind/index.d.ts +2 -10
- package/dist/src/mind/junction.d.ts +31 -58
- package/dist/src/mind/junction.js +172 -237
- package/dist/src/mind/learning.d.ts +16 -52
- package/dist/src/mind/learning.js +143 -165
- package/dist/src/mind/match.d.ts +20 -69
- package/dist/src/mind/match.js +259 -318
- package/dist/src/mind/mechanisms/alu.js +16 -16
- package/dist/src/mind/mechanisms/cast.d.ts +9 -13
- package/dist/src/mind/mechanisms/cast.js +363 -456
- package/dist/src/mind/mechanisms/confluence.d.ts +8 -12
- package/dist/src/mind/mechanisms/confluence.js +152 -183
- package/dist/src/mind/mechanisms/cover.d.ts +2 -8
- package/dist/src/mind/mechanisms/cover.js +148 -210
- package/dist/src/mind/mechanisms/extraction.d.ts +8 -34
- package/dist/src/mind/mechanisms/extraction.js +234 -288
- package/dist/src/mind/mechanisms/recall.d.ts +6 -10
- package/dist/src/mind/mechanisms/recall.js +141 -185
- package/dist/src/mind/mind.d.ts +194 -155
- package/dist/src/mind/mind.js +392 -289
- package/dist/src/mind/pipeline-mechanism.d.ts +112 -124
- package/dist/src/mind/pipeline-mechanism.js +161 -172
- package/dist/src/mind/pipeline.d.ts +4 -14
- package/dist/src/mind/pipeline.js +125 -189
- package/dist/src/mind/primitives.d.ts +20 -33
- package/dist/src/mind/primitives.js +124 -120
- package/dist/src/mind/rationale.d.ts +86 -98
- package/dist/src/mind/rationale.js +113 -121
- package/dist/src/mind/reasoning.d.ts +2 -13
- package/dist/src/mind/reasoning.js +129 -166
- package/dist/src/mind/recognition.d.ts +1 -4
- package/dist/src/mind/recognition.js +198 -210
- package/dist/src/mind/resonance.d.ts +5 -22
- package/dist/src/mind/resonance.js +0 -0
- package/dist/src/mind/trace.d.ts +6 -25
- package/dist/src/mind/trace.js +50 -58
- package/dist/src/mind/traverse.d.ts +29 -58
- package/dist/src/mind/traverse.js +344 -356
- package/dist/src/mind/types.d.ts +122 -127
- package/dist/src/mind/types.js +60 -69
- package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
- package/dist/src/rabitq-ivf/src/database.js +201 -0
- package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
- package/dist/src/{rabitq-hnsw → rabitq-ivf}/src/index.js +1 -3
- package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
- package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
- package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
- package/dist/src/rabitq-ivf/src/prng.js +36 -0
- package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
- package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
- package/dist/src/sema.d.ts +9 -13
- package/dist/src/sema.js +26 -40
- package/dist/src/store-sqlite.d.ts +171 -166
- package/dist/src/store-sqlite.js +768 -662
- package/dist/src/store.d.ts +597 -630
- package/dist/src/store.js +1434 -1581
- package/dist/src/vec.d.ts +5 -9
- package/dist/src/vec.js +61 -73
- package/example/train_base.ts +33 -15
- package/index.html +65 -0
- package/package.json +1 -1
- package/src/alu/README.md +1 -1
- package/src/alu/src/index.ts +1 -1
- package/src/config.ts +19 -27
- package/src/geometry.ts +93 -1
- package/src/index.ts +6 -11
- package/src/mind/attention.ts +11 -6
- package/src/mind/mechanisms/recall.ts +29 -13
- package/src/mind/mind.ts +250 -19
- package/src/mind/primitives.ts +43 -6
- package/src/mind/recognition.ts +26 -8
- package/src/mind/traverse.ts +47 -0
- package/src/mind/types.ts +20 -21
- package/src/rabitq-ivf/README.md +56 -0
- package/src/rabitq-ivf/src/database.ts +276 -0
- package/src/{rabitq-hnsw → rabitq-ivf}/src/index.ts +2 -5
- package/src/rabitq-ivf/src/ivf.ts +1330 -0
- package/src/{rabitq-hnsw → rabitq-ivf}/src/prng.ts +1 -1
- package/src/store-sqlite.ts +204 -9
- package/src/store.ts +27 -34
- package/test/08-storage.test.mjs +3 -3
- package/test/13-conversation.test.mjs +190 -20
- package/test/14-scaling.test.mjs +2 -2
- package/test/35-ivf.test.mjs +263 -0
- package/test/36-bloom.test.mjs +123 -0
- package/dist/src/rabitq-hnsw/src/database.d.ts +0 -202
- package/dist/src/rabitq-hnsw/src/database.js +0 -405
- package/dist/src/rabitq-hnsw/src/heap.d.ts +0 -22
- package/dist/src/rabitq-hnsw/src/heap.js +0 -94
- package/dist/src/rabitq-hnsw/src/hnsw.d.ts +0 -125
- package/dist/src/rabitq-hnsw/src/hnsw.js +0 -500
- package/dist/src/rabitq-hnsw/src/index.d.ts +0 -15
- package/dist/src/rabitq-hnsw/src/prng.d.ts +0 -19
- package/dist/src/rabitq-hnsw/src/prng.js +0 -38
- package/dist/src/rabitq-hnsw/src/rabitq.d.ts +0 -95
- package/dist/src/rabitq-hnsw/src/rabitq.js +0 -299
- package/dist/src/rabitq-hnsw/src/store.d.ts +0 -162
- package/dist/src/rabitq-hnsw/src/store.js +0 -916
- package/dist/src/rabitq-hnsw/test/hnsw.test.d.ts +0 -1
- package/dist/src/rabitq-hnsw/test/hnsw.test.js +0 -1197
- package/src/rabitq-hnsw/README.md +0 -303
- package/src/rabitq-hnsw/src/database.ts +0 -492
- package/src/rabitq-hnsw/src/heap.ts +0 -90
- package/src/rabitq-hnsw/src/hnsw.ts +0 -514
- package/src/rabitq-hnsw/src/store.ts +0 -994
- package/src/rabitq-hnsw/test/hnsw.test.ts +0 -1213
- /package/src/{rabitq-hnsw → rabitq-ivf}/src/rabitq.ts +0 -0
|
@@ -23,164 +23,130 @@ import { asInt, bit, int } from "./value.js";
|
|
|
23
23
|
* Width is chosen by the caller wide enough that the signed result cannot
|
|
24
24
|
* overflow, so interpreting the top bit as the sign is always correct. */
|
|
25
25
|
function toBits(n, width) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
34
|
}
|
|
35
35
|
/** Interpret a two's-complement little-endian bit array as a signed bigint. */
|
|
36
36
|
function fromBits(bits) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const signBitSet = bits[width - 1] === 1;
|
|
45
|
-
return signBitSet ? u - (1n << BigInt(width)) : u;
|
|
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;
|
|
46
44
|
}
|
|
47
45
|
/** Bits needed to hold |n| (at least 1). */
|
|
48
46
|
function magnitudeBits(n) {
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
const a = n < 0n ? -n : n;
|
|
48
|
+
return a === 0n ? 1 : a.toString(2).length;
|
|
51
49
|
}
|
|
52
50
|
/** A single full adder built from the logic gates: sum = a⊕b⊕cin, carry =
|
|
53
51
|
* (a∧b) ∨ (cin ∧ (a⊕b)). Every gate goes through ctx.apply → nand. */
|
|
54
52
|
function fullAdder(ctx, a, b, cin) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
+
};
|
|
66
64
|
}
|
|
67
65
|
/** Ripple-carry add of two two's-complement bit arrays (equal width). */
|
|
68
66
|
function rippleAdd(ctx, x, y) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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;
|
|
78
76
|
}
|
|
79
77
|
/** Bitwise NOT of a bit array, via the not gate. */
|
|
80
78
|
function notBits(ctx, x) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
return x.map((b) => {
|
|
80
|
+
const r = ctx.apply("not", [bit(b)]);
|
|
81
|
+
return (r.domain === "bit" ? r.b : 0);
|
|
82
|
+
});
|
|
85
83
|
}
|
|
86
84
|
/** Two's-complement negate: invert every bit, then add one. */
|
|
87
85
|
function negateBitsArr(ctx, x) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
const width = x.length;
|
|
87
|
+
const one = toBits(1n, width);
|
|
88
|
+
return rippleAdd(ctx, notBits(ctx, x), one);
|
|
91
89
|
}
|
|
92
90
|
// ── public pure functions (used by the tests and the explicit ops) ──────────
|
|
93
91
|
/** Exact addition through the ripple of full_adders. */
|
|
94
92
|
export function addBits(ctx, a, b) {
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
const width = Math.max(magnitudeBits(a), magnitudeBits(b)) + 2;
|
|
94
|
+
return fromBits(rippleAdd(ctx, toBits(a, width), toBits(b, width)));
|
|
97
95
|
}
|
|
98
96
|
/** Exact two's-complement negation. */
|
|
99
97
|
export function negateBits(ctx, a) {
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
const width = magnitudeBits(a) + 2;
|
|
99
|
+
return fromBits(negateBitsArr(ctx, toBits(a, width)));
|
|
102
100
|
}
|
|
103
101
|
/** Exact shift-add multiplication: for each set bit i of b, add (a << i) to the
|
|
104
102
|
* accumulator. The per-bit gate is an AND mask of the shifted a with bᵢ; the
|
|
105
103
|
* accumulation is rippleAdd — so multiply traces entirely to nand. */
|
|
106
104
|
export function mulBits(ctx, a, b) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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);
|
|
121
120
|
}
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
return fromBits(acc);
|
|
121
|
+
return fromBits(acc);
|
|
125
122
|
}
|
|
126
123
|
/** Sign of an integer as {-1, 0, 1}: zero when every bit is zero, −1 when the
|
|
127
124
|
* two's-complement sign bit is set, +1 otherwise — read off the bit array. */
|
|
128
125
|
export function signBits(ctx, a) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return bits[width - 1] === 1 ? -1n : 1n;
|
|
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;
|
|
135
131
|
}
|
|
136
132
|
/** Compare via sign(subtract): −1 if a<b, 0 if a=b, +1 if a>b, where subtract is
|
|
137
133
|
* add ∘ negate — so comparison is structured arithmetic, not a new primitive. */
|
|
138
134
|
export function compareBits(ctx, a, b) {
|
|
139
|
-
|
|
135
|
+
return signBits(ctx, addBits(ctx, a, negateBits(ctx, b)));
|
|
140
136
|
}
|
|
141
137
|
/** Register the bit-bootstrap ops (int domain) into `r`. They have no surface
|
|
142
138
|
* forms — they are an internal exhibit, exercised by the tests and by anyone
|
|
143
139
|
* who wants to walk the nand→arithmetic chain, not matched from a query. */
|
|
144
140
|
export function registerBits(r) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
r.derive(
|
|
157
|
-
"bits.add",
|
|
158
|
-
2,
|
|
159
|
-
[],
|
|
160
|
-
(args, ctx) => int(addBits(ctx, asInt(args[0]), asInt(args[1]))),
|
|
161
|
-
);
|
|
162
|
-
r.derive(
|
|
163
|
-
"bits.negate",
|
|
164
|
-
1,
|
|
165
|
-
[],
|
|
166
|
-
(args, ctx) => int(negateBits(ctx, asInt(args[0]))),
|
|
167
|
-
);
|
|
168
|
-
r.derive(
|
|
169
|
-
"bits.multiply",
|
|
170
|
-
2,
|
|
171
|
-
[],
|
|
172
|
-
(args, ctx) => int(mulBits(ctx, asInt(args[0]), asInt(args[1]))),
|
|
173
|
-
);
|
|
174
|
-
r.derive(
|
|
175
|
-
"bits.sign",
|
|
176
|
-
1,
|
|
177
|
-
[],
|
|
178
|
-
(args, ctx) => int(signBits(ctx, asInt(args[0]))),
|
|
179
|
-
);
|
|
180
|
-
r.derive(
|
|
181
|
-
"bits.compare",
|
|
182
|
-
2,
|
|
183
|
-
[],
|
|
184
|
-
(args, ctx) => int(compareBits(ctx, asInt(args[0]), asInt(args[1]))),
|
|
185
|
-
);
|
|
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]))));
|
|
186
152
|
}
|
|
@@ -24,67 +24,37 @@ import { asBit, bit } from "./value.js";
|
|
|
24
24
|
/** Register the logic layer into `r`. Idempotent in effect (re-registering
|
|
25
25
|
* overwrites with the same definitions). */
|
|
26
26
|
export function registerLogic(r) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"not",
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
2,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const left = ctx.apply("and", [a, ctx.apply("not", [b])]);
|
|
61
|
-
const right = ctx.apply("and", [ctx.apply("not", [a]), b]);
|
|
62
|
-
return ctx.apply("or", [left, right]);
|
|
63
|
-
});
|
|
64
|
-
r.derive(
|
|
65
|
-
"xnor",
|
|
66
|
-
2,
|
|
67
|
-
["xnor", "⊙"],
|
|
68
|
-
(args, ctx) => ctx.apply("not", [ctx.apply("xor", [args[0], args[1]])]),
|
|
69
|
-
);
|
|
70
|
-
r.derive(
|
|
71
|
-
"implies",
|
|
72
|
-
2,
|
|
73
|
-
["implies", "=>", "→", "⇒"],
|
|
74
|
-
(args, ctx) => ctx.apply("or", [ctx.apply("not", [args[0]]), args[1]]),
|
|
75
|
-
);
|
|
76
|
-
r.derive(
|
|
77
|
-
"iff",
|
|
78
|
-
2,
|
|
79
|
-
["iff", "<=>", "↔", "⇔"],
|
|
80
|
-
(args, ctx) => ctx.apply("xnor", [args[0], args[1]]),
|
|
81
|
-
);
|
|
82
|
-
// mux(s, a, b): select a when s = 0, b when s = 1. The bridge to control
|
|
83
|
-
// flow — conditional selection, and (with recursion in the caller) looping.
|
|
84
|
-
r.derive("mux", 3, ["mux", "select", "?:"], (args, ctx) => {
|
|
85
|
-
const s = args[0], a = args[1], b = args[2];
|
|
86
|
-
const lo = ctx.apply("and", [ctx.apply("not", [s]), a]);
|
|
87
|
-
const hi = ctx.apply("and", [s, b]);
|
|
88
|
-
return ctx.apply("or", [lo, hi]);
|
|
89
|
-
});
|
|
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
|
+
});
|
|
90
60
|
}
|