@fraczak/k 6.10.5 → 7.0.0
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/CHANGELOG.md +70 -0
- package/CLAUDE.md +1 -1
- package/DOCS/BIG_PICTURE.md +156 -172
- package/DOCS/BINARY_CODEC_STATUS_AND_TODO.md +3 -3
- package/DOCS/CODEC_ARCHITECTURE.md +2 -2
- package/DOCS/DICTIONARY.md +243 -250
- package/DOCS/DIVERGENCE_DETECTION.md +0 -1
- package/DOCS/FILE_FORMATS.md +5 -5
- package/DOCS/KIR_SPECIALIZATION_DESIGN.md +1 -1
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +12 -12
- package/DOCS/PATTERNS.md +17 -17
- package/DOCS/PATTERNS_AND_TYPED_VALUES.md +1 -1
- package/DOCS/REPL.md +9 -19
- package/DOCS/TYPE_DERIVATION.md +2 -8
- package/DOCS/WEB_REPL_REQUIREMENTS.md +8 -8
- package/DOCS/book/01-introduction.md +8 -11
- package/DOCS/book/02-syntax-and-values.md +19 -20
- package/DOCS/book/03-types-as-finite-automata.md +42 -43
- package/DOCS/book/04-partial-functions-and-composition.md +2 -3
- package/DOCS/book/05-typing-filters-and-normalization.md +44 -46
- package/DOCS/book/06-values-in-memory.md +10 -10
- package/DOCS/book/08-operational-semantics-and-execution.md +21 -26
- package/DOCS/book/09-compiler-architecture.md +11 -11
- package/DOCS/book/10-from-ast-to-intermediate-representation.md +6 -7
- package/DOCS/book/14-canonical-serialization.md +2 -2
- package/DOCS/book/appendix-b-incorporating-external-predefined-types-and-functions.md +17 -17
- package/DOCS/book.md +5 -5
- package/Examples/arithmetics.k +49 -153
- package/Examples/bnat.k +13 -13
- package/Examples/byte.k +2 -50
- package/Examples/ieee.k +408 -423
- package/Examples/karatsuba-mult.k +30 -34
- package/Examples/nat.k +5 -6
- package/README.md +54 -49
- package/TODO.md +13 -18
- package/browser/repl-browser.mjs +40 -22
- package/browser/shims/fs.mjs +7 -10
- package/browser/vfs-data.mjs +12 -12
- package/codecs/BINARY_FORMAT.md +4 -4
- package/codecs/POLYMORPHIC_BINARY_FORMAT.md +4 -4
- package/codecs/README.md +6 -6
- package/codecs/ieee.mjs +15 -11
- package/codecs/int.mjs +9 -5
- package/codecs/string-codec.mjs +46 -47
- package/core.k +124 -175
- package/object.mjs +0 -7
- package/package.json +5 -2
- package/parser.jison +2 -41
- package/parser.mjs +55 -95
- package/pretty.mjs +11 -4
- package/repl.mjs +8 -63
- package/scripts/build-repl-html.mjs +18 -49
- package/tests/code-derivation/blowup.mjs +2 -4
- package/tests/code-derivation/bnat.mjs +2 -3
- package/tests/code-derivation/dot.mjs +5 -11
- package/tests/code-derivation/nat.mjs +2 -2
- package/tests/code-derivation/not-not.mjs +6 -6
- package/tests/code-derivation/pattern-envelope.mjs +4 -6
- package/tests/code-derivation/product.mjs +3 -6
- package/tests/code-derivation/rlz.mjs +4 -5
- package/tests/test-codecs.mjs +1 -1
- package/tests/test-fingerprint.mjs +36 -41
- package/tests/test-hash-normalization.mjs +4 -6
- package/tests/test-ieee-arithmetic.mjs +6 -7
- package/tests/test-k-object.mjs +11 -15
- package/tests/test-kir.mjs +0 -1
- package/tests/test-kvm-polymorphic.mjs +1 -2
- package/tests/test-kvm.mjs +8 -11
- package/tests/test-repl-html.mjs +86 -9
- package/tests/test-repl.mjs +38 -53
- package/tests/test.mjs +2 -3
|
@@ -16,7 +16,7 @@ Each external type has:
|
|
|
16
16
|
|
|
17
17
|
| Field | Description |
|
|
18
18
|
| --------------------- | ---------------------------------------------------------------------------- |
|
|
19
|
-
| **Name** | symbolic name (e.g.,
|
|
19
|
+
| **Name** | symbolic name (e.g., `int`, `string`) |
|
|
20
20
|
| **Hash** | unique stable identifier, just like canonical types |
|
|
21
21
|
| **Runtime kind** | how the value is stored in memory (pointer, immediate integer, etc.) |
|
|
22
22
|
| **Adapter functions** | conversion between the external representation and the standard `KNode` tree |
|
|
@@ -28,7 +28,7 @@ Example registry entry:
|
|
|
28
28
|
"hash": "E001",
|
|
29
29
|
"kind": "type",
|
|
30
30
|
"external": true,
|
|
31
|
-
"name": "
|
|
31
|
+
"name": "int",
|
|
32
32
|
"runtime_kind": "primitive_i64"
|
|
33
33
|
}
|
|
34
34
|
```
|
|
@@ -40,11 +40,11 @@ The compiler treats such a type as an atomic node, represented internally as a s
|
|
|
40
40
|
## **B.3 External constructors**
|
|
41
41
|
|
|
42
42
|
External types may provide special constructors or constants.
|
|
43
|
-
For example,
|
|
43
|
+
For example, `int` might include predefined constant functions:
|
|
44
44
|
|
|
45
45
|
```
|
|
46
|
-
zero = {}
|
|
47
|
-
one = {}
|
|
46
|
+
zero = {} int;
|
|
47
|
+
one = {} int;
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
At compile time these appear as constant functions returning fixed external nodes provided by the runtime.
|
|
@@ -59,8 +59,8 @@ They have known input and output types, possibly external.
|
|
|
59
59
|
Declaration syntax:
|
|
60
60
|
|
|
61
61
|
```
|
|
62
|
-
extern add :
|
|
63
|
-
extern less :
|
|
62
|
+
extern add : int int → int;
|
|
63
|
+
extern less : int int → bool;
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
At compile time the compiler records the signature and associates it with a runtime symbol name such as `k_ext_add`.
|
|
@@ -82,15 +82,15 @@ They can appear as components in products or unions just like built-in ones.
|
|
|
82
82
|
|
|
83
83
|
Example:
|
|
84
84
|
|
|
85
|
-
```
|
|
86
|
-
|
|
85
|
+
```k-lang
|
|
86
|
+
point = ?{ int x, int y };
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
Canonical form:
|
|
90
90
|
|
|
91
91
|
```
|
|
92
92
|
$C0 = { C1 "x", C1 "y" };
|
|
93
|
-
$C1 = external
|
|
93
|
+
$C1 = external int;
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
This allows normal serialization and type comparison; the external leaf is treated as opaque but identified by its hash.
|
|
@@ -111,10 +111,10 @@ All external codecs must be deterministic and version-stable to preserve canonic
|
|
|
111
111
|
|
|
112
112
|
## **B.7 Example**
|
|
113
113
|
|
|
114
|
-
Suppose we introduce
|
|
114
|
+
Suppose we introduce `int` and external function `add`:
|
|
115
115
|
|
|
116
|
-
```
|
|
117
|
-
|
|
116
|
+
```k-lang
|
|
117
|
+
pair_int = ?{ int a, int b };
|
|
118
118
|
sum = { .a x, .b y } (add x y);
|
|
119
119
|
```
|
|
120
120
|
|
|
@@ -122,7 +122,7 @@ The compiler generates code that:
|
|
|
122
122
|
|
|
123
123
|
* projects fields `.a` and `.b`,
|
|
124
124
|
* passes them as `KVal` pointers to `@k_ext_add`,
|
|
125
|
-
* and returns the result as a new
|
|
125
|
+
* and returns the result as a new `int` node.
|
|
126
126
|
|
|
127
127
|
All logic outside arithmetic remains standard k code.
|
|
128
128
|
|
|
@@ -134,12 +134,12 @@ In a Python prototype:
|
|
|
134
134
|
|
|
135
135
|
```python
|
|
136
136
|
EXTERNAL_TYPES = {
|
|
137
|
-
"
|
|
137
|
+
"int": {"hash": "E001", "kind": "external", "runtime_kind": "primitive_i64"}
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
EXTERNAL_FUNCS = {
|
|
141
|
-
"add": {"inputs": ["
|
|
142
|
-
"less": {"inputs": ["
|
|
141
|
+
"add": {"inputs": ["int", "int"], "output": "int", "symbol": "k_ext_add"},
|
|
142
|
+
"less": {"inputs": ["int", "int"], "output": "bool", "symbol": "k_ext_less"}
|
|
143
143
|
}
|
|
144
144
|
```
|
|
145
145
|
|
package/DOCS/book.md
CHANGED
|
@@ -17,17 +17,17 @@ author: "W. Fraczak"
|
|
|
17
17
|
|
|
18
18
|
# The k Book
|
|
19
19
|
|
|
20
|
-
This book describes the k programming language: a minimal
|
|
21
|
-
for
|
|
22
|
-
|
|
20
|
+
This book describes the k programming language: a minimal language
|
|
21
|
+
for content-addressable schemas and data transformations over labeled trees
|
|
22
|
+
using partial relations and algebraic finite automata.
|
|
23
23
|
|
|
24
24
|
## Available Chapters
|
|
25
25
|
|
|
26
26
|
- [Introduction](book/01-introduction.md)
|
|
27
27
|
- [Syntax and Values](book/02-syntax-and-values.md)
|
|
28
|
-
- [
|
|
28
|
+
- [Schemas as Finite Automata](book/03-types-as-finite-automata.md)
|
|
29
29
|
- [Partial Functions and Composition](book/04-partial-functions-and-composition.md)
|
|
30
|
-
- [
|
|
30
|
+
- [Schemas, Filters, and Contracts](book/05-typing-filters-and-normalization.md)
|
|
31
31
|
- [Values in Memory](book/06-values-in-memory.md)
|
|
32
32
|
- [The Partial Function ABI](book/07-the-partial-function-abi.md)
|
|
33
33
|
- [Operational Semantics and Execution](book/08-operational-semantics-and-execution.md)
|
package/Examples/arithmetics.k
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
-- Examples for defining arithmetic functions natively
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
yes = {}|yes $yes_no;
|
|
2
|
+
swap_yes_no = < /yes |no, /no |yes >;
|
|
3
|
+
yes = {}|yes;
|
|
5
4
|
no = yes swap_yes_no;
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
bits = ?< {} _, bits 0, bits 1 > = bits;
|
|
8
7
|
|
|
9
8
|
0b = {} | _;
|
|
10
9
|
-- |1 = | 1;
|
|
@@ -25,11 +24,11 @@ succ = {inv x, 0b y} _inc;
|
|
|
25
24
|
11 = 10 succ;
|
|
26
25
|
12 = 11 succ;
|
|
27
26
|
|
|
28
|
-
empty =
|
|
27
|
+
empty = < /_ yes, no >;
|
|
29
28
|
empty? = {empty /yes if, () then} .then;
|
|
30
29
|
|
|
31
|
-
concat =
|
|
32
|
-
concat_ =
|
|
30
|
+
concat = {.x inv x, .y y} concat_;
|
|
31
|
+
concat_ = ?{ <X 0, X 1, {} _>=X x, ... }
|
|
33
32
|
<
|
|
34
33
|
{.x empty? if, .y then} .then,
|
|
35
34
|
<
|
|
@@ -38,7 +37,7 @@ concat_ = ${bits x, bits y}
|
|
|
38
37
|
> concat_
|
|
39
38
|
>;
|
|
40
39
|
inv = {()x, 0b r} _inv;
|
|
41
|
-
_inv =
|
|
40
|
+
_inv = ?{ <X 0, X 1, {} _>=X x, ... }
|
|
42
41
|
<
|
|
43
42
|
{.x empty? if, .r then} .then,
|
|
44
43
|
<
|
|
@@ -47,8 +46,8 @@ _inv = ${bits x, bits r}
|
|
|
47
46
|
> _inv
|
|
48
47
|
>;
|
|
49
48
|
|
|
50
|
-
inOrder =
|
|
51
|
-
inOrder_ =
|
|
49
|
+
inOrder = {.x inv x, .y inv y, yes inOrder} inOrder_;
|
|
50
|
+
inOrder_ = ?{ <X 0, X 1, {} _>=X x, ... }
|
|
52
51
|
<
|
|
53
52
|
{.x </0,/1> if1, .y /_ if2, .inOrder swap_yes_no then} .then,
|
|
54
53
|
{.x /_ if, .inOrder then} .then,
|
|
@@ -65,49 +64,48 @@ GT = {inOrder /no if, () then} . then;
|
|
|
65
64
|
EQ = {inOrder /yes if, {.x y, .y x} inOrder /yes and, () then} .then;
|
|
66
65
|
|
|
67
66
|
--------------------------------------
|
|
68
|
-
|
|
67
|
+
int = ?< <bits 0, bits 1, {} _>=bits "+", bits "-" >;
|
|
69
68
|
|
|
70
69
|
remove_leading_zeros = <
|
|
71
70
|
/0 remove_leading_zeros,
|
|
72
71
|
()
|
|
73
72
|
>;
|
|
74
73
|
nat = remove_leading_zeros <empty? 0, ()>;
|
|
75
|
-
int = nat | '+'
|
|
76
|
-
abs =
|
|
74
|
+
int = nat | '+';
|
|
75
|
+
abs = </'+',/'-'>;
|
|
77
76
|
|
|
78
|
-
pos? =
|
|
79
|
-
neg? =
|
|
80
|
-
zero_int? =
|
|
81
|
-
minus_one? =
|
|
77
|
+
pos? = {/'+' remove_leading_zeros /1 if, () then} .then;
|
|
78
|
+
neg? = {/'-' if, () then} .then;
|
|
79
|
+
zero_int? = {/'+' /0 empty? if, () then} .then;
|
|
80
|
+
minus_one? = {/'-' /1 empty? if, () then} .then;
|
|
82
81
|
|
|
83
|
-
inc =
|
|
82
|
+
inc = <
|
|
84
83
|
/'+' {inv x, 0b y} _inc nat |'+',
|
|
85
84
|
minus_one? 0 int,
|
|
86
85
|
/'-' {inv x, 0b y} _dec nat |'-'
|
|
87
|
-
|
|
86
|
+
>;
|
|
88
87
|
|
|
89
|
-
_inc =
|
|
88
|
+
_inc = ?{ <X 0, X 1, {} _>=X x, ... } <
|
|
90
89
|
{.x empty? if, .y |1 then} .then,
|
|
91
90
|
{.x /0 x, .y |1 y} concat_,
|
|
92
91
|
{.x /1 x, .y |0 y} _inc
|
|
93
92
|
>;
|
|
94
93
|
|
|
95
|
-
dec =
|
|
94
|
+
dec = <
|
|
96
95
|
zero_int? 1 |'-',
|
|
97
96
|
/'+' {inv x, 0b y} _dec nat |'+',
|
|
98
97
|
/'-' {inv x, 0b y} _inc nat |'-'
|
|
99
|
-
|
|
98
|
+
>;
|
|
100
99
|
|
|
101
|
-
_dec =
|
|
100
|
+
_dec = ?{ <X 0, X 1, {} _>=X x, ... } <
|
|
102
101
|
{.x /1 x, .y |0 y} concat_,
|
|
103
102
|
{.x /0 x, .y |1 y} _dec
|
|
104
103
|
>;
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
c1 = {}|1 $carry;
|
|
105
|
+
c0 = {}|0;
|
|
106
|
+
c1 = {}|1;
|
|
109
107
|
|
|
110
|
-
plus =
|
|
108
|
+
plus =
|
|
111
109
|
<
|
|
112
110
|
{.x/'+' inv x, .y/'+' inv y, c0 c } _plus inv nat | '+',
|
|
113
111
|
{.x/'-' inv x, .y/'-' inv y, c0 c } _plus inv nat | '-',
|
|
@@ -115,8 +113,7 @@ plus = ${int x, int y}
|
|
|
115
113
|
{.x/'+' inv x, .y/'-' inv y, c0 c} _minus inv nat |'+',
|
|
116
114
|
{.x/'-' x, .y/'+' y} GT {.x inv x, .y inv y, c0 c} _minus inv nat | '-',
|
|
117
115
|
{.y/'+' inv x, .x/'-' inv y, c0 c} _minus inv nat | '+'
|
|
118
|
-
|
|
119
|
-
$int;
|
|
116
|
+
>;
|
|
120
117
|
|
|
121
118
|
swap_sign = <
|
|
122
119
|
zero_int?,
|
|
@@ -124,14 +121,14 @@ swap_sign = <
|
|
|
124
121
|
/'-' | '+'
|
|
125
122
|
>;
|
|
126
123
|
|
|
127
|
-
minus =
|
|
124
|
+
minus =
|
|
128
125
|
{.x x, .y swap_sign y} plus;
|
|
129
126
|
|
|
130
127
|
_plus = {.x x, .y y, .c c, 0b r} _plus_;
|
|
131
128
|
|
|
132
129
|
_plus_ =
|
|
133
130
|
-- least significant bit first addition with carry
|
|
134
|
-
|
|
131
|
+
?{ <X 0, X 1, {} _>=X x, ... }
|
|
135
132
|
<
|
|
136
133
|
{.x empty? if, .y empty? and, .c/0 c, .r inv then} .then,
|
|
137
134
|
{.x empty? if, .y empty? and, {.r x, 1 r} _inv then} .then,
|
|
@@ -159,7 +156,7 @@ _minus = {.x x, .y y, .c c, 0b r} _minus_;
|
|
|
159
156
|
|
|
160
157
|
_minus_ =
|
|
161
158
|
-- least significant bit first substraction with carry
|
|
162
|
-
|
|
159
|
+
?{ <X 0, X 1, {} _>=X x, ... }
|
|
163
160
|
<
|
|
164
161
|
{.y empty? if, .c/0 and, {.r x, .x r} _inv then} .then,
|
|
165
162
|
<
|
|
@@ -178,12 +175,11 @@ _minus_ =
|
|
|
178
175
|
>
|
|
179
176
|
;
|
|
180
177
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
get_sign = $int </'+' sign_plus, /'-' sign_minus>;
|
|
178
|
+
sign_plus = {}|'+';
|
|
179
|
+
sign_minus = {}|'-';
|
|
180
|
+
get_sign = </'+' sign_plus, /'-' sign_minus>;
|
|
185
181
|
|
|
186
|
-
times =
|
|
182
|
+
times =
|
|
187
183
|
{
|
|
188
184
|
<
|
|
189
185
|
{.x/'+' if, .y /'+' and} sign_plus,
|
|
@@ -203,7 +199,7 @@ times = ${int x, int y}
|
|
|
203
199
|
;
|
|
204
200
|
|
|
205
201
|
_times =
|
|
206
|
-
|
|
202
|
+
?{ <Y 0, Y 1, {} _>=Y y, ... }
|
|
207
203
|
<
|
|
208
204
|
{ .y empty? if, .result then } .then,
|
|
209
205
|
<
|
|
@@ -221,40 +217,16 @@ _times =
|
|
|
221
217
|
>
|
|
222
218
|
;
|
|
223
219
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
220
|
// ----------------------------------------------------------------------
|
|
229
221
|
// Integer Division: Adaptive Hybrid Algorithm
|
|
230
|
-
//
|
|
231
|
-
// Combines two complementary strategies based on the bit-length
|
|
232
|
-
// comparison between dividend x and divisor y (|x| vs |y|):
|
|
233
|
-
//
|
|
234
|
-
// 1. Down-Shift Division (|x| < 2|y|, y is large relative to x):
|
|
235
|
-
// - Scales y up to y_max = y * 2^k to match length(x) via 'y inv'
|
|
236
|
-
// and prepending k zeros (|0).
|
|
237
|
-
// - In each step: trial subtraction x = x - y_scaled, then down-shifts
|
|
238
|
-
// y_scaled by 1 bit in O(1) by popping the outer zero (/_0).
|
|
239
|
-
// - Runs in exactly (|x| - |y| + 1) iterations. When y ~= x, this
|
|
240
|
-
// terminates in 1-2 steps rather than looping through all bits of x.
|
|
241
|
-
//
|
|
242
|
-
// 2. Restoring Division (|x| >= 2|y|, y is small relative to x):
|
|
243
|
-
// - Consumes bits of x from MSB to LSB into remainder accumulator r.
|
|
244
|
-
// - Remainder r stays small (r <= 2y), so trial subtractions operate
|
|
245
|
-
// on tiny numbers of length |y| rather than full-length |x|.
|
|
246
|
-
//
|
|
247
|
-
// The crossover condition |x| < 2|y| is evaluated structurally in
|
|
248
|
-
// O(min(|y|, |x|/2)) by consuming 2 bits of x for every 1 bit of y.
|
|
249
222
|
// ----------------------------------------------------------------------
|
|
250
223
|
|
|
251
|
-
// Helpers for Restoring Division (shift-and-subtract)
|
|
252
224
|
shift_in_0 = inv |0 inv nat;
|
|
253
225
|
shift_in_1 = inv |1 inv nat;
|
|
254
|
-
sub_bits =
|
|
226
|
+
sub_bits = {.x inv x, .y inv y, c0 c} _minus inv nat;
|
|
255
227
|
|
|
256
228
|
_div_restoring =
|
|
257
|
-
|
|
229
|
+
?{ <X 0, X 1, {} _>=X x, ... }
|
|
258
230
|
<
|
|
259
231
|
{.x empty? if, {.q inv int div, .r rem} then} .then,
|
|
260
232
|
<
|
|
@@ -275,9 +247,7 @@ _div_restoring =
|
|
|
275
247
|
_div_restoring
|
|
276
248
|
>;
|
|
277
249
|
|
|
278
|
-
|
|
279
|
-
// Phase 1: pad _y with |0 to match length of x, counting shift steps
|
|
280
|
-
_pad_down = ${bits x, bits _y, bits steps}
|
|
250
|
+
_pad_down = ?{ <X 0, X 1, {} _>=X x, <S 0, S 1, {} _>=S steps, ... }
|
|
281
251
|
<
|
|
282
252
|
{.x empty? if, {._y _y, .steps steps} then} .then,
|
|
283
253
|
{
|
|
@@ -287,22 +257,19 @@ _pad_down = ${bits x, bits _y, bits steps}
|
|
|
287
257
|
} _pad_down
|
|
288
258
|
>;
|
|
289
259
|
|
|
290
|
-
_align_down =
|
|
260
|
+
_align_down = ?{ <X 0, X 1, {} _>=X x, <Y 0, Y 1, {} _>=Y y, ... }
|
|
291
261
|
<
|
|
292
|
-
// Both x and y have bits remaining: advance both
|
|
293
262
|
{
|
|
294
263
|
.x </0, /1> x,
|
|
295
264
|
.y </0, /1> y,
|
|
296
265
|
._y _y
|
|
297
266
|
} _align_down,
|
|
298
267
|
|
|
299
|
-
// y is empty while x remains: pad _y with shift zeros
|
|
300
268
|
{
|
|
301
269
|
.y empty? if,
|
|
302
270
|
{.x x, ._y _y, 0b steps} _pad_down then
|
|
303
271
|
} .then,
|
|
304
272
|
|
|
305
|
-
// Both x and y are empty: lengths equal (0 shift steps)
|
|
306
273
|
{
|
|
307
274
|
.x empty? if,
|
|
308
275
|
.y empty? and,
|
|
@@ -310,8 +277,7 @@ _align_down = ${bits x, bits y, bits _y}
|
|
|
310
277
|
} .then
|
|
311
278
|
>;
|
|
312
279
|
|
|
313
|
-
|
|
314
|
-
_div_down = ${bits x, bits _y, bits steps, bits q}
|
|
280
|
+
_div_down = ?{ <X 0, X 1, {} _>=X steps, ... }
|
|
315
281
|
{
|
|
316
282
|
.x x,
|
|
317
283
|
._y _y,
|
|
@@ -328,7 +294,6 @@ _div_down = ${bits x, bits _y, bits steps, bits q}
|
|
|
328
294
|
{.y_scaled x, .x y} inOrder test
|
|
329
295
|
}
|
|
330
296
|
<
|
|
331
|
-
// If x >= y_scaled, subtract and emit quotient bit 1
|
|
332
297
|
{
|
|
333
298
|
.test /yes if,
|
|
334
299
|
{
|
|
@@ -338,19 +303,16 @@ _div_down = ${bits x, bits _y, bits steps, bits q}
|
|
|
338
303
|
.steps steps
|
|
339
304
|
} then
|
|
340
305
|
} .then,
|
|
341
|
-
// If x < y_scaled, keep x and emit quotient bit 0
|
|
342
306
|
{
|
|
343
307
|
.test /no if,
|
|
344
308
|
{.x x, .q |0 q, ._y _y, .steps steps} then
|
|
345
309
|
} .then
|
|
346
310
|
>
|
|
347
311
|
<
|
|
348
|
-
// If no more shift steps remaining, division is complete
|
|
349
312
|
{
|
|
350
313
|
.steps empty? if,
|
|
351
314
|
{.q inv int div, .x rem} then
|
|
352
315
|
} .then,
|
|
353
|
-
// Otherwise down-shift: remove the last 0 from _y and steps
|
|
354
316
|
{
|
|
355
317
|
.x x,
|
|
356
318
|
._y /0 _y,
|
|
@@ -359,26 +321,18 @@ _div_down = ${bits x, bits _y, bits steps, bits q}
|
|
|
359
321
|
} _div_down
|
|
360
322
|
>;
|
|
361
323
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
// Evaluates whether |x| < 2|y| by advancing 2 bits of x per 1 bit of y
|
|
365
|
-
_check_2y = ${bits x, bits y}
|
|
324
|
+
_check_2y = ?{ <X 0, X 1, {} _>=X x, <Y 0, Y 1, {} _>=Y y, ... }
|
|
366
325
|
<
|
|
367
|
-
|
|
368
|
-
{.
|
|
369
|
-
|
|
370
|
-
{.y empty? if, {} | restore $choose_div then} .then,
|
|
371
|
-
// x has only 1 bit left while y remains -> |x| < 2|y|
|
|
372
|
-
{.x </0, /1> empty? if, {} | down_shift $choose_div then} .then,
|
|
373
|
-
// Advance 2 bits from x and 1 bit from y
|
|
326
|
+
{.x empty? if, {} | down_shift then} .then,
|
|
327
|
+
{.y empty? if, {} | restore then} .then,
|
|
328
|
+
{.x </0, /1> empty? if, {} | down_shift then} .then,
|
|
374
329
|
{
|
|
375
330
|
.x </0, /1> </0, /1> x,
|
|
376
331
|
.y </0, /1> y
|
|
377
332
|
} _check_2y
|
|
378
333
|
>;
|
|
379
334
|
|
|
380
|
-
|
|
381
|
-
div = ${int x, int y}
|
|
335
|
+
div =
|
|
382
336
|
{
|
|
383
337
|
<
|
|
384
338
|
{ .x/'+' if, .y get_sign then } .then,
|
|
@@ -388,17 +342,14 @@ div = ${int x, int y}
|
|
|
388
342
|
.y abs remove_leading_zeros y_norm
|
|
389
343
|
}
|
|
390
344
|
<
|
|
391
|
-
// Case 1: x == 0 -> quotient 0, remainder 0
|
|
392
345
|
{
|
|
393
346
|
.x_norm empty? if,
|
|
394
347
|
{ 0 int div, 0 rem } then
|
|
395
348
|
} .then,
|
|
396
|
-
// Case 2: |x| < |y| -> x < y, quotient 0, remainder x
|
|
397
349
|
{
|
|
398
350
|
{.y_norm x, .x_norm y} GT if,
|
|
399
351
|
{ 0 int div, .x_norm rem } then
|
|
400
352
|
} .then,
|
|
401
|
-
// Case 3: general division via adaptive hybrid choice
|
|
402
353
|
{
|
|
403
354
|
.sign sign,
|
|
404
355
|
{
|
|
@@ -407,7 +358,6 @@ div = ${int x, int y}
|
|
|
407
358
|
{.x_norm x, .y_norm y} _check_2y choice
|
|
408
359
|
}
|
|
409
360
|
<
|
|
410
|
-
// If |x| < 2|y|, use down-shift division
|
|
411
361
|
{
|
|
412
362
|
.choice /down_shift if,
|
|
413
363
|
{
|
|
@@ -421,7 +371,6 @@ div = ${int x, int y}
|
|
|
421
371
|
0b q
|
|
422
372
|
} _div_down then
|
|
423
373
|
} .then,
|
|
424
|
-
// If |x| >= 2|y|, use restoring long division
|
|
425
374
|
{
|
|
426
375
|
.choice /restore if,
|
|
427
376
|
{.x x, .y y, 0 r, 0b q} _div_restoring then
|
|
@@ -434,31 +383,22 @@ div = ${int x, int y}
|
|
|
434
383
|
>
|
|
435
384
|
>;
|
|
436
385
|
|
|
437
|
-
|
|
438
|
-
// ----------------------------------------------------------------------
|
|
439
|
-
// Number Theory: Modulo, Greatest Common Divisor, Least Common Multiple
|
|
440
|
-
// ----------------------------------------------------------------------
|
|
441
|
-
|
|
442
|
-
// Modulo: remainder of x divided by y in $bits, delegated to div
|
|
443
|
-
mod = ${bits x, bits y}
|
|
386
|
+
mod =
|
|
444
387
|
{{.x int x, .y int y} div .rem rem} .rem;
|
|
445
388
|
|
|
446
|
-
|
|
447
|
-
gcd = ${bits x, bits y}
|
|
389
|
+
gcd =
|
|
448
390
|
<
|
|
449
391
|
{.y x, .x y} GT,
|
|
450
392
|
()
|
|
451
393
|
> _gcd
|
|
452
394
|
;
|
|
453
395
|
|
|
454
|
-
_gcd = <
|
|
396
|
+
_gcd = ?{ <X 0, X 1, {} _>=X x, ... } <
|
|
455
397
|
{ .y remove_leading_zeros empty? if, .x nat then } .then,
|
|
456
398
|
{ .y x, mod y } _gcd
|
|
457
399
|
>;
|
|
458
400
|
|
|
459
|
-
// Least common multiple: (x / gcd(x, y)) * y
|
|
460
401
|
lcm =
|
|
461
|
-
${bits x, bits y}
|
|
462
402
|
{{.x int x, gcd int y} div .div x, .y int y} times abs
|
|
463
403
|
;
|
|
464
404
|
|
|
@@ -477,16 +417,13 @@ fib_ =
|
|
|
477
417
|
>
|
|
478
418
|
;
|
|
479
419
|
|
|
480
|
-
fib = {
|
|
481
|
-
|
|
420
|
+
fib = {() n, {1 int x, 0 int y} "fib(n),fib(n.1)"} fib_ .x;
|
|
482
421
|
|
|
483
422
|
--------------------
|
|
484
|
-
$ rat = { int n, int d };
|
|
485
423
|
|
|
486
|
-
rat =
|
|
424
|
+
rat = {.n int n, .d int d } normalize_rat;
|
|
487
425
|
|
|
488
426
|
normalize_rat =
|
|
489
|
-
$rat
|
|
490
427
|
<
|
|
491
428
|
{ .d/"-" if,
|
|
492
429
|
{
|
|
@@ -501,12 +438,9 @@ normalize_rat =
|
|
|
501
438
|
{.x.n x,.y y} div .div n,
|
|
502
439
|
{.x.d x,.y y} div .div d
|
|
503
440
|
}
|
|
504
|
-
$rat
|
|
505
441
|
;
|
|
506
442
|
|
|
507
|
-
|
|
508
443
|
plus_rat =
|
|
509
|
-
${rat x, rat y}
|
|
510
444
|
{
|
|
511
445
|
.x x,
|
|
512
446
|
.y y,
|
|
@@ -522,18 +456,14 @@ plus_rat =
|
|
|
522
456
|
normalize_rat
|
|
523
457
|
;
|
|
524
458
|
|
|
525
|
-
|
|
526
459
|
times_rat =
|
|
527
|
-
${rat x, rat y}
|
|
528
460
|
{
|
|
529
461
|
{.x.n x,.y.n y} times n,
|
|
530
462
|
{.x.d x,.y.d y} times d
|
|
531
463
|
}
|
|
532
464
|
normalize_rat;
|
|
533
|
-
|
|
534
465
|
|
|
535
466
|
minus_rat =
|
|
536
|
-
${rat x, rat y}
|
|
537
467
|
{
|
|
538
468
|
.x x,
|
|
539
469
|
.y {.n swap_sign n, .d d} y
|
|
@@ -541,51 +471,17 @@ minus_rat =
|
|
|
541
471
|
plus_rat;
|
|
542
472
|
|
|
543
473
|
inverse_rat =
|
|
544
|
-
$rat
|
|
545
474
|
{ .d n, .n d }
|
|
546
475
|
normalize_rat
|
|
547
476
|
;
|
|
548
477
|
|
|
549
478
|
div_rat =
|
|
550
|
-
${rat x, rat y}
|
|
551
479
|
{ .x x, .y inverse_rat y} times_rat
|
|
552
480
|
;
|
|
553
481
|
|
|
554
|
-
|
|
555
|
-
--------------------
|
|
556
|
-
|
|
557
482
|
int_rat =
|
|
558
|
-
$rat
|
|
559
483
|
{ .n n, .d d, {.n x,.d y} div div }
|
|
560
484
|
{ .div.div int, {.div.rem int n, .d d} rat}
|
|
561
|
-
${int int, rat rat}
|
|
562
485
|
;
|
|
563
486
|
|
|
564
|
-
/*
|
|
565
|
-
ratToString =
|
|
566
|
-
-- $rat
|
|
567
|
-
[
|
|
568
|
-
.n toJSON,
|
|
569
|
-
"/",
|
|
570
|
-
.d toJSON,
|
|
571
|
-
" = ",
|
|
572
|
-
normalize_rat
|
|
573
|
-
<
|
|
574
|
-
[.d,.n] GT [.1 toJSON ,"/", .0 toJSON] CONCAT,
|
|
575
|
-
{.n 0,[.d,1] EQ 1} [.0 toJSON] CONCAT,
|
|
576
|
-
int_rat [.int toJSON,"+",.rat.n toJSON,"/",.rat.d toJSON] CONCAT
|
|
577
|
-
>
|
|
578
|
-
] CONCAT
|
|
579
|
-
-- $@string
|
|
580
|
-
;
|
|
581
|
-
|
|
582
|
-
_rat! = $rat {
|
|
583
|
-
() carryOn,
|
|
584
|
-
ratToString drop
|
|
585
|
-
} .carryOn;
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
*/
|
|
590
|
-
|
|
591
487
|
()
|