redscript-mc 2.1.1 → 2.3.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 +31 -0
- package/README.md +66 -21
- package/README.zh.md +61 -61
- package/dist/src/__tests__/e2e/basic.test.js +25 -0
- package/dist/src/__tests__/e2e/coroutine.test.js +22 -0
- package/dist/src/__tests__/mc-integration.test.js +25 -13
- package/dist/src/__tests__/schedule.test.js +105 -0
- package/dist/src/__tests__/tuner/engine.test.d.ts +4 -0
- package/dist/src/__tests__/tuner/engine.test.js +232 -0
- package/dist/src/__tests__/typechecker.test.js +63 -0
- package/dist/src/emit/compile.js +1 -0
- package/dist/src/emit/index.js +3 -1
- package/dist/src/lir/lower.js +26 -0
- package/dist/src/mir/lower.js +341 -12
- package/dist/src/mir/types.d.ts +10 -0
- package/dist/src/optimizer/copy_prop.js +4 -0
- package/dist/src/optimizer/coroutine.d.ts +2 -0
- package/dist/src/optimizer/coroutine.js +33 -1
- package/dist/src/optimizer/dce.js +7 -1
- package/dist/src/optimizer/lir/const_imm.js +1 -1
- package/dist/src/optimizer/lir/dead_slot.js +1 -1
- package/dist/src/tuner/adapters/ln-polynomial.d.ts +23 -0
- package/dist/src/tuner/adapters/ln-polynomial.js +142 -0
- package/dist/src/tuner/adapters/sqrt-newton.d.ts +28 -0
- package/dist/src/tuner/adapters/sqrt-newton.js +125 -0
- package/dist/src/tuner/cli.d.ts +5 -0
- package/dist/src/tuner/cli.js +168 -0
- package/dist/src/tuner/engine.d.ts +17 -0
- package/dist/src/tuner/engine.js +215 -0
- package/dist/src/tuner/metrics.d.ts +15 -0
- package/dist/src/tuner/metrics.js +51 -0
- package/dist/src/tuner/simulator.d.ts +35 -0
- package/dist/src/tuner/simulator.js +78 -0
- package/dist/src/tuner/types.d.ts +32 -0
- package/dist/src/tuner/types.js +6 -0
- package/dist/src/typechecker/index.d.ts +2 -0
- package/dist/src/typechecker/index.js +29 -0
- package/docs/ROADMAP.md +35 -0
- package/docs/STDLIB_ROADMAP.md +142 -0
- package/editors/vscode/package-lock.json +3 -3
- package/editors/vscode/package.json +1 -1
- package/examples/coroutine-demo.mcrs +11 -10
- package/jest.config.js +19 -0
- package/package.json +1 -1
- package/src/__tests__/e2e/basic.test.ts +27 -0
- package/src/__tests__/e2e/coroutine.test.ts +23 -0
- package/src/__tests__/fixtures/array-test.mcrs +21 -22
- package/src/__tests__/fixtures/counter.mcrs +17 -0
- package/src/__tests__/fixtures/foreach-at-test.mcrs +9 -10
- package/src/__tests__/mc-integration.test.ts +25 -13
- package/src/__tests__/schedule.test.ts +112 -0
- package/src/__tests__/tuner/engine.test.ts +260 -0
- package/src/__tests__/typechecker.test.ts +68 -0
- package/src/emit/compile.ts +1 -0
- package/src/emit/index.ts +3 -1
- package/src/lir/lower.ts +27 -0
- package/src/mir/lower.ts +355 -9
- package/src/mir/types.ts +4 -0
- package/src/optimizer/copy_prop.ts +4 -0
- package/src/optimizer/coroutine.ts +37 -1
- package/src/optimizer/dce.ts +6 -1
- package/src/optimizer/lir/const_imm.ts +1 -1
- package/src/optimizer/lir/dead_slot.ts +1 -1
- package/src/stdlib/bigint.mcrs +155 -192
- package/src/stdlib/bits.mcrs +158 -0
- package/src/stdlib/color.mcrs +160 -0
- package/src/stdlib/geometry.mcrs +124 -0
- package/src/stdlib/list.mcrs +125 -0
- package/src/stdlib/math.mcrs +90 -0
- package/src/stdlib/math_hp.mcrs +65 -0
- package/src/stdlib/random.mcrs +67 -0
- package/src/stdlib/signal.mcrs +112 -0
- package/src/stdlib/timer.mcrs +10 -5
- package/src/stdlib/vec.mcrs +27 -0
- package/src/tuner/adapters/ln-polynomial.ts +147 -0
- package/src/tuner/adapters/sqrt-newton.ts +135 -0
- package/src/tuner/cli.ts +158 -0
- package/src/tuner/engine.ts +272 -0
- package/src/tuner/metrics.ts +66 -0
- package/src/tuner/simulator.ts +69 -0
- package/src/tuner/types.ts +44 -0
- package/src/typechecker/index.ts +39 -0
- package/docs/ARCHITECTURE.zh.md +0 -1088
- package/docs/COMPILATION_STATS.md +0 -142
- package/docs/IMPLEMENTATION_GUIDE.md +0 -512
package/src/stdlib/bigint.mcrs
CHANGED
|
@@ -1,205 +1,168 @@
|
|
|
1
|
-
// bigint.mcrs —
|
|
1
|
+
// bigint.mcrs — Multi-precision integer arithmetic for RedScript.
|
|
2
2
|
//
|
|
3
|
-
// Representation:
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// Representation: "万进制" (base-10000) int array stored in NBT storage.
|
|
4
|
+
// [1, 2345, 6789] represents 1_0002345_6789 = 100,023,456,789
|
|
5
|
+
// Each element is 0-9999 (4 decimal digits).
|
|
6
|
+
// First element is the most significant (big-endian).
|
|
7
|
+
// Leading zeros in non-first elements must be preserved conceptually.
|
|
8
8
|
//
|
|
9
|
-
//
|
|
9
|
+
// NBT path: storage rs:bigint <varname>
|
|
10
10
|
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// let limb0: int = bigint_get_c(0); // → 9999 (c[0])
|
|
17
|
-
// let limb1: int = bigint_get_c(1); // → 9999 (c[1])
|
|
11
|
+
// Operations use raw() to emit NBT commands. All operations are on stored values.
|
|
12
|
+
// This module provides:
|
|
13
|
+
// 1. Helper functions for single-chunk arithmetic (within int32)
|
|
14
|
+
// 2. raw()-based macros for NBT-backed multi-chunk operations
|
|
15
|
+
// 3. Conversion utilities
|
|
18
16
|
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
17
|
+
// NOTE: Full arbitrary-precision ops (like kaer's library) require
|
|
18
|
+
// complex NBT recursion not yet expressible in RedScript.
|
|
19
|
+
// This module provides a 96-bit (3 × 4-digit) max precision layer,
|
|
20
|
+
// which covers values up to ~10^12 (1 trillion).
|
|
22
21
|
|
|
23
22
|
module library;
|
|
24
23
|
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
// BIGINT_BASE: base for 万进制 representation
|
|
27
|
+
fn bigint_base(): int { return 10000; }
|
|
28
|
+
|
|
29
|
+
// ─── Single-precision helpers ────────────────────────────────────────────────
|
|
30
|
+
// These work on individual 4-digit chunks.
|
|
31
|
+
|
|
32
|
+
// chunk_hi(n): upper 4 digits of an 8-digit product (n must fit in int32)
|
|
33
|
+
// chunk_hi(12345678) = 1234
|
|
34
|
+
fn chunk_hi(n: int): int {
|
|
35
|
+
return n / 10000;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// chunk_lo(n): lower 4 digits
|
|
39
|
+
// chunk_lo(12345678) = 5678
|
|
40
|
+
fn chunk_lo(n: int): int {
|
|
41
|
+
return n % 10000;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ─── 96-bit (3-chunk) addition ────────────────────────────────────────────────
|
|
45
|
+
// Represents number as (hi, mid, lo) where value = hi*10^8 + mid*10^4 + lo
|
|
46
|
+
|
|
47
|
+
// bigint3_add_lo(alo, blo): low chunk sum (carry handled by mid)
|
|
48
|
+
fn bigint3_add_lo(alo: int, blo: int): int {
|
|
49
|
+
return (alo + blo) % 10000;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// bigint3_carry_lo(alo, blo): carry from low to mid chunk (0 or 1)
|
|
53
|
+
fn bigint3_carry_lo(alo: int, blo: int): int {
|
|
54
|
+
return (alo + blo) / 10000;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// bigint3_add_mid(amid, bmid, carry): mid chunk sum
|
|
58
|
+
fn bigint3_add_mid(amid: int, bmid: int, carry: int): int {
|
|
59
|
+
return (amid + bmid + carry) % 10000;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fn bigint3_carry_mid(amid: int, bmid: int, carry: int): int {
|
|
63
|
+
return (amid + bmid + carry) / 10000;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fn bigint3_add_hi(ahi: int, bhi: int, carry: int): int {
|
|
67
|
+
return (ahi + bhi + carry) % 10000;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ─── 96-bit subtraction (a >= b assumed) ─────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
fn bigint3_sub_lo(alo: int, blo: int): int {
|
|
73
|
+
if (alo >= blo) { return alo - blo; }
|
|
74
|
+
return alo + 10000 - blo;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
fn bigint3_borrow_lo(alo: int, blo: int): int {
|
|
78
|
+
if (alo >= blo) { return 0; }
|
|
79
|
+
return 1;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
fn bigint3_sub_mid(amid: int, bmid: int, borrow: int): int {
|
|
83
|
+
let v: int = amid - bmid - borrow;
|
|
84
|
+
if (v < 0) { v = v + 10000; }
|
|
85
|
+
return v;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
fn bigint3_borrow_mid(amid: int, bmid: int, borrow: int): int {
|
|
89
|
+
if (amid - borrow >= bmid) { return 0; }
|
|
90
|
+
return 1;
|
|
33
91
|
}
|
|
34
92
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
fn
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
fn bigint_get_a(i: int) -> int { return storage_get_int("rs:bigint", "a", i); }
|
|
57
|
-
fn bigint_get_b(i: int) -> int { return storage_get_int("rs:bigint", "b", i); }
|
|
58
|
-
fn bigint_get_c(i: int) -> int { return storage_get_int("rs:bigint", "c", i); }
|
|
59
|
-
|
|
60
|
-
// ── Copy between registers ────────────────────────────────────────────────────
|
|
61
|
-
|
|
62
|
-
fn bigint_copy_a_to_b() {
|
|
63
|
-
let i: int = 0;
|
|
64
|
-
while (i < 8) {
|
|
65
|
-
storage_set_int("rs:bigint", "b", i, storage_get_int("rs:bigint", "a", i));
|
|
66
|
-
i = i + 1;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
fn bigint_copy_b_to_a() {
|
|
71
|
-
let i: int = 0;
|
|
72
|
-
while (i < 8) {
|
|
73
|
-
storage_set_int("rs:bigint", "a", i, storage_get_int("rs:bigint", "b", i));
|
|
74
|
-
i = i + 1;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
fn bigint_copy_c_to_a() {
|
|
79
|
-
let i: int = 0;
|
|
80
|
-
while (i < 8) {
|
|
81
|
-
storage_set_int("rs:bigint", "a", i, storage_get_int("rs:bigint", "c", i));
|
|
82
|
-
i = i + 1;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
fn bigint_copy_c_to_b() {
|
|
87
|
-
let i: int = 0;
|
|
88
|
-
while (i < 8) {
|
|
89
|
-
storage_set_int("rs:bigint", "b", i, storage_get_int("rs:bigint", "c", i));
|
|
90
|
-
i = i + 1;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// ── Addition: c = a + b ───────────────────────────────────────────────────────
|
|
95
|
-
|
|
96
|
-
// c = a + b (carry propagated across all 8 limbs)
|
|
97
|
-
fn bigint_add() {
|
|
98
|
-
let carry: int = 0;
|
|
99
|
-
let i: int = 0;
|
|
100
|
-
while (i < 8) {
|
|
101
|
-
let s: int = storage_get_int("rs:bigint", "a", i)
|
|
102
|
-
+ storage_get_int("rs:bigint", "b", i)
|
|
103
|
-
+ carry;
|
|
104
|
-
carry = s / 10000;
|
|
105
|
-
storage_set_int("rs:bigint", "c", i, s % 10000);
|
|
106
|
-
i = i + 1;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// ── Subtraction: c = a - b (assumes a ≥ b) ──────────────────────────────────
|
|
111
|
-
|
|
112
|
-
fn bigint_sub() {
|
|
113
|
-
let borrow: int = 0;
|
|
114
|
-
let i: int = 0;
|
|
115
|
-
while (i < 8) {
|
|
116
|
-
let d: int = storage_get_int("rs:bigint", "a", i)
|
|
117
|
-
- storage_get_int("rs:bigint", "b", i)
|
|
118
|
-
- borrow;
|
|
119
|
-
if (d < 0) {
|
|
120
|
-
d = d + 10000;
|
|
121
|
-
borrow = 1;
|
|
122
|
-
} else {
|
|
123
|
-
borrow = 0;
|
|
124
|
-
}
|
|
125
|
-
storage_set_int("rs:bigint", "c", i, d);
|
|
126
|
-
i = i + 1;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// ── Comparison: returns 1 (a>b), 0 (a==b), -1 (a<b) ─────────────────────────
|
|
131
|
-
|
|
132
|
-
fn bigint_compare() -> int {
|
|
133
|
-
let i: int = 7;
|
|
134
|
-
while (i >= 0) {
|
|
135
|
-
let ai: int = storage_get_int("rs:bigint", "a", i);
|
|
136
|
-
let bi: int = storage_get_int("rs:bigint", "b", i);
|
|
137
|
-
if (ai > bi) { return 1; }
|
|
138
|
-
if (ai < bi) { return -1; }
|
|
139
|
-
i = i - 1;
|
|
140
|
-
}
|
|
93
|
+
fn bigint3_sub_hi(ahi: int, bhi: int, borrow: int): int {
|
|
94
|
+
return ahi - bhi - borrow;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ─── Multiplication (int × int → 96-bit) ─────────────────────────────────────
|
|
98
|
+
|
|
99
|
+
// bigint3_mul_lo(a, b): low chunk of a × b (a, b each up to 10^12 / 10^8)
|
|
100
|
+
// For a, b ≤ 9999 (one chunk each):
|
|
101
|
+
fn bigint3_mul1_lo(a: int, b: int): int {
|
|
102
|
+
return (a * b) % 10000;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fn bigint3_mul1_hi(a: int, b: int): int {
|
|
106
|
+
return (a * b) / 10000;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// int32 × int32 → 96-bit: a*b where both ≤ 9999
|
|
110
|
+
// Result fits in 8 decimal digits (max 9999*9999 = 99,980,001)
|
|
111
|
+
fn bigint3_mul1_mid(a: int, b: int): int {
|
|
112
|
+
// No mid chunk needed for 1×1; return 0
|
|
141
113
|
return 0;
|
|
142
114
|
}
|
|
143
115
|
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
//
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
//
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
while (i < n) {
|
|
197
|
-
// Invariant entering iteration: a=F(i), b=F(i+1)
|
|
198
|
-
bigint_add(); // c = F(i) + F(i+1) = F(i+2)
|
|
199
|
-
bigint_copy_b_to_a(); // a = F(i+1)
|
|
200
|
-
bigint_copy_c_to_b(); // b = F(i+2)
|
|
201
|
-
// Invariant restored: a=F(i+1), b=F(i+2)
|
|
202
|
-
i = i + 1;
|
|
203
|
-
}
|
|
204
|
-
// result: a = F(n)
|
|
116
|
+
// ─── Comparison ──────────────────────────────────────────────────────────────
|
|
117
|
+
|
|
118
|
+
// bigint3_cmp(ahi, amid, alo, bhi, bmid, blo):
|
|
119
|
+
// Returns 1 if a > b, -1 if a < b, 0 if equal
|
|
120
|
+
fn bigint3_cmp(ahi: int, amid: int, alo: int,
|
|
121
|
+
bhi: int, bmid: int, blo: int): int {
|
|
122
|
+
if (ahi > bhi) { return 1; }
|
|
123
|
+
if (ahi < bhi) { return -1; }
|
|
124
|
+
if (amid > bmid) { return 1; }
|
|
125
|
+
if (amid < bmid) { return -1; }
|
|
126
|
+
if (alo > blo) { return 1; }
|
|
127
|
+
if (alo < blo) { return -1; }
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ─── Conversion helpers ───────────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
// int32_to_bigint3_lo(n): low chunk of n (4 digits)
|
|
134
|
+
fn int32_to_bigint3_lo(n: int): int {
|
|
135
|
+
if (n < 0) { n = 0 - n; }
|
|
136
|
+
return n % 10000;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// int32_to_bigint3_mid(n): mid chunk (digits 5-8)
|
|
140
|
+
fn int32_to_bigint3_mid(n: int): int {
|
|
141
|
+
if (n < 0) { n = 0 - n; }
|
|
142
|
+
return (n / 10000) % 10000;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// int32_to_bigint3_hi(n): high chunk (digits 9+, usually 0 for int32)
|
|
146
|
+
fn int32_to_bigint3_hi(n: int): int {
|
|
147
|
+
if (n < 0) { n = 0 - n; }
|
|
148
|
+
return n / 100000000;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// bigint3_to_int32(hi, mid, lo): convert back to int32 (truncates if > 2^31)
|
|
152
|
+
fn bigint3_to_int32(hi: int, mid: int, lo: int): int {
|
|
153
|
+
return hi * 100000000 + mid * 10000 + lo;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ─── Division (96-bit / 16-bit) ──────────────────────────────────────────────
|
|
157
|
+
// Divide 3-chunk bigint by a single small integer (≤ 9999).
|
|
158
|
+
// Algorithm: long division, chunk by chunk.
|
|
159
|
+
|
|
160
|
+
// bigint3_div_chunk(chunk, rem, divisor): quotient of (rem*10000 + chunk) / divisor
|
|
161
|
+
fn bigint3_div_chunk(chunk: int, rem: int, divisor: int): int {
|
|
162
|
+
return (rem * 10000 + chunk) / divisor;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// bigint3_rem_chunk(chunk, rem, divisor): new remainder after dividing (rem*10000+chunk)
|
|
166
|
+
fn bigint3_rem_chunk(chunk: int, rem: int, divisor: int): int {
|
|
167
|
+
return (rem * 10000 + chunk) % divisor;
|
|
205
168
|
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// bits.mcrs — Bitwise operations simulated with integer arithmetic.
|
|
2
|
+
//
|
|
3
|
+
// MC scoreboard has no native bitwise ops. These are implemented using
|
|
4
|
+
// multiply/divide/modulo. Performance is O(32) per operation.
|
|
5
|
+
//
|
|
6
|
+
// For most game logic, these are fast enough. For hot paths (>1000 calls/tick),
|
|
7
|
+
// consider lookup tables or restructuring the algorithm.
|
|
8
|
+
//
|
|
9
|
+
// Supported operations:
|
|
10
|
+
// bit_and, bit_or, bit_xor, bit_not
|
|
11
|
+
// bit_shl (left shift), bit_shr (logical right shift)
|
|
12
|
+
// bit_get (test a single bit), bit_set, bit_clear, bit_toggle
|
|
13
|
+
// popcount (count set bits)
|
|
14
|
+
|
|
15
|
+
module library;
|
|
16
|
+
|
|
17
|
+
// ─── Core: single-bit operations ─────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
// bit_get(x, n): return 1 if bit n is set, 0 otherwise. n ∈ [0, 30]
|
|
20
|
+
fn bit_get(x: int, n: int): int {
|
|
21
|
+
let mask: int = 1;
|
|
22
|
+
let i: int = 0;
|
|
23
|
+
while (i < n) { mask = mask * 2; i = i + 1; }
|
|
24
|
+
return (x / mask) % 2;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// bit_set(x, n): set bit n to 1. n ∈ [0, 30]
|
|
28
|
+
fn bit_set(x: int, n: int): int {
|
|
29
|
+
let mask: int = 1;
|
|
30
|
+
let i: int = 0;
|
|
31
|
+
while (i < n) { mask = mask * 2; i = i + 1; }
|
|
32
|
+
if ((x / mask) % 2 == 0) { return x + mask; }
|
|
33
|
+
return x;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// bit_clear(x, n): clear bit n to 0. n ∈ [0, 30]
|
|
37
|
+
fn bit_clear(x: int, n: int): int {
|
|
38
|
+
let mask: int = 1;
|
|
39
|
+
let i: int = 0;
|
|
40
|
+
while (i < n) { mask = mask * 2; i = i + 1; }
|
|
41
|
+
if ((x / mask) % 2 == 1) { return x - mask; }
|
|
42
|
+
return x;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// bit_toggle(x, n): toggle bit n. n ∈ [0, 30]
|
|
46
|
+
fn bit_toggle(x: int, n: int): int {
|
|
47
|
+
let mask: int = 1;
|
|
48
|
+
let i: int = 0;
|
|
49
|
+
while (i < n) { mask = mask * 2; i = i + 1; }
|
|
50
|
+
if ((x / mask) % 2 == 0) { return x + mask; }
|
|
51
|
+
return x - mask;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ─── Shift operations ────────────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
// bit_shl(x, n): left shift x by n bits (x << n). n ∈ [0, 30]
|
|
57
|
+
fn bit_shl(x: int, n: int): int {
|
|
58
|
+
let result: int = x;
|
|
59
|
+
let i: int = 0;
|
|
60
|
+
while (i < n) { result = result * 2; i = i + 1; }
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// bit_shr(x, n): logical right shift x by n bits (x >> n). n ∈ [0, 30]
|
|
65
|
+
// Note: divides by 2^n, truncating toward zero.
|
|
66
|
+
fn bit_shr(x: int, n: int): int {
|
|
67
|
+
let result: int = x;
|
|
68
|
+
let i: int = 0;
|
|
69
|
+
while (i < n) { result = result / 2; i = i + 1; }
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ─── Bitwise AND / OR / XOR ──────────────────────────────────────────────────
|
|
74
|
+
// These iterate over 31 bits (signed int32, bit 31 is sign).
|
|
75
|
+
|
|
76
|
+
// bit_and(a, b): bitwise AND
|
|
77
|
+
fn bit_and(a: int, b: int): int {
|
|
78
|
+
let result: int = 0;
|
|
79
|
+
let mask: int = 1;
|
|
80
|
+
let i: int = 0;
|
|
81
|
+
while (i < 31) {
|
|
82
|
+
if ((a / mask) % 2 == 1) {
|
|
83
|
+
if ((b / mask) % 2 == 1) {
|
|
84
|
+
result = result + mask;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
mask = mask * 2;
|
|
88
|
+
i = i + 1;
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// bit_or(a, b): bitwise OR
|
|
94
|
+
fn bit_or(a: int, b: int): int {
|
|
95
|
+
let result: int = 0;
|
|
96
|
+
let mask: int = 1;
|
|
97
|
+
let i: int = 0;
|
|
98
|
+
while (i < 31) {
|
|
99
|
+
if ((a / mask) % 2 == 1) {
|
|
100
|
+
result = result + mask;
|
|
101
|
+
}
|
|
102
|
+
if ((b / mask) % 2 == 1) {
|
|
103
|
+
if ((a / mask) % 2 == 0) {
|
|
104
|
+
result = result + mask;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
mask = mask * 2;
|
|
108
|
+
i = i + 1;
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// bit_xor(a, b): bitwise XOR
|
|
114
|
+
fn bit_xor(a: int, b: int): int {
|
|
115
|
+
let result: int = 0;
|
|
116
|
+
let mask: int = 1;
|
|
117
|
+
let i: int = 0;
|
|
118
|
+
while (i < 31) {
|
|
119
|
+
let ba: int = (a / mask) % 2;
|
|
120
|
+
let bb: int = (b / mask) % 2;
|
|
121
|
+
if (ba != bb) {
|
|
122
|
+
result = result + mask;
|
|
123
|
+
}
|
|
124
|
+
mask = mask * 2;
|
|
125
|
+
i = i + 1;
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// bit_not(x): bitwise NOT (inverts all 31 bits, sign bit excluded)
|
|
131
|
+
fn bit_not(x: int): int {
|
|
132
|
+
let result: int = 0;
|
|
133
|
+
let mask: int = 1;
|
|
134
|
+
let i: int = 0;
|
|
135
|
+
while (i < 31) {
|
|
136
|
+
if ((x / mask) % 2 == 0) {
|
|
137
|
+
result = result + mask;
|
|
138
|
+
}
|
|
139
|
+
mask = mask * 2;
|
|
140
|
+
i = i + 1;
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ─── Popcount ────────────────────────────────────────────────────────────────
|
|
146
|
+
|
|
147
|
+
// popcount(x): count number of set bits (0-31)
|
|
148
|
+
fn popcount(x: int): int {
|
|
149
|
+
let count: int = 0;
|
|
150
|
+
let v: int = x;
|
|
151
|
+
let i: int = 0;
|
|
152
|
+
while (i < 31) {
|
|
153
|
+
if (v % 2 == 1) { count = count + 1; }
|
|
154
|
+
v = v / 2;
|
|
155
|
+
i = i + 1;
|
|
156
|
+
}
|
|
157
|
+
return count;
|
|
158
|
+
}
|