toilscript 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.
@@ -0,0 +1,546 @@
1
+ import { u128, u256 } from "./integer";
2
+
3
+ @lazy export var __divmod_quot_hi: u64 = 0;
4
+ @lazy export var __divmod_rem_lo: u64 = 0;
5
+ @lazy export var __divmod_rem_hi: u64 = 0;
6
+
7
+ // used for returning low and high part of __mulq64, __multi3 etc
8
+ @lazy export var __res128_hi: u64 = 0;
9
+
10
+ // used for returning 0 or 1
11
+ @lazy export var __carry: u64 = 0;
12
+ @lazy export var __u256carry: u64 = 0;
13
+ @lazy export var __u256carrySub: u64 = 0;
14
+
15
+ /**
16
+ * Convert 128-bit unsigned integer to 64-bit float
17
+ * @param lo lower 64-bit part of unsigned 128-bit integer
18
+ * @param hi higher 64-bit part of unsigned 128-bit integer
19
+ * @return 64-bit float result
20
+ */
21
+ // @ts-ignore: decorator
22
+ @global
23
+ export function __floatuntidf(lo: u64, hi: u64): f64 {
24
+ // __floatuntidf ported from LLVM sources
25
+ if (!(lo | hi)) return 0.0;
26
+
27
+ var v = new u128(lo, hi);
28
+ var sd = 128 - __clz128(lo, hi);
29
+ var e = sd - 1;
30
+
31
+ if (sd > 53) {
32
+ if (sd != 55) {
33
+ if (sd == 54) {
34
+ v = u128.shl(v, 1);
35
+ } else {
36
+ v = u128.or(
37
+ u128.shr(v, sd - 55),
38
+ u128.fromBool(u128.and(v, u128.shr(u128.Max, 128 + 55 - sd)).toBool())
39
+ );
40
+ }
41
+ }
42
+
43
+ v.lo |= (v.lo & 4) >> 2;
44
+ v.preInc();
45
+
46
+ v = u128.shr(v, 2);
47
+
48
+ if (v.lo & (1 << 53)) {
49
+ v = u128.shr(v, 1);
50
+ ++e;
51
+ }
52
+
53
+ } else {
54
+ v = u128.shl(v, 53 - sd);
55
+ }
56
+
57
+ var w: u64 = u128.shr(v, 32).lo & 0x000FFFFF;
58
+ var u: u64 = <u64>(((e + 1023) << 20) | w) << 32;
59
+ return reinterpret<f64>(u | (v.lo & 0xFFFFFFFF));
60
+ }
61
+
62
+
63
+ /**
64
+ * Adds two 64-bit unsigned integers `a` and `b` along with a carry-in value.
65
+ * Sets the global `__carry2` variable to indicate whether an overflow occurred.
66
+ * @param {u64} a - The first 64-bit unsigned integer.
67
+ * @param {u64} b - The second 64-bit unsigned integer.
68
+ * @param {u64} carryIn - Carry-in value (0 or 1).
69
+ * @returns {u64} - The 64-bit result of the addition.
70
+ */
71
+ @inline
72
+ export function add64Local(a: u64, b: u64, carryIn: u64): u64 {
73
+ let tmp = a + carryIn;
74
+ let carry = tmp < a ? 1 : 0;
75
+ let sum = tmp + b;
76
+ carry += sum < tmp ? 1 : 0;
77
+ __u256carry = carry;
78
+ return sum;
79
+ }
80
+
81
+ /**
82
+ * Subtracts the 64-bit unsigned integer `b` from `a` along with a borrow-in value.
83
+ * Sets the global `__carry2` variable to indicate whether a borrow occurred.
84
+ * @param {u64} a - The minuend (64-bit unsigned integer).
85
+ * @param {u64} b - The subtrahend (64-bit unsigned integer).
86
+ * @param {u64} borrowIn - Borrow-in value (0 or 1).
87
+ * @returns {u64} - The 64-bit result of the subtraction.
88
+ */
89
+ @inline
90
+ export function sub64(a: u64, b: u64, borrowIn: u64): u64 {
91
+ let tmp = a - b;
92
+ let borrow = tmp > a ? 1 : 0;
93
+ let diff = tmp - borrowIn;
94
+ borrow += diff > tmp ? 1 : 0;
95
+ __u256carrySub = borrow;
96
+ return diff;
97
+ }
98
+
99
+ // @ts-ignore: decorator
100
+ @global
101
+ export function __umulh64(a: u64, b: u64): u64 {
102
+ var u = a & 0xFFFFFFFF;
103
+ a >>= 32;
104
+ var v = b & 0xFFFFFFFF;
105
+ b >>= 32;
106
+
107
+ var uv = u * v;
108
+ uv = a * v + (uv >> 32);
109
+ var w0 = (u * b) + (uv & 0xFFFFFFFF);
110
+ return a * b + (uv >> 32) + (w0 >> 32);
111
+ }
112
+
113
+ // @ts-ignore: decorator
114
+ @global
115
+ export function __umulq64(a: u64, b: u64): u64 {
116
+ var u = a & 0xFFFFFFFF;
117
+ a >>= 32;
118
+ var v = b & 0xFFFFFFFF;
119
+ b >>= 32;
120
+
121
+ var uv = u * v;
122
+ var w0 = uv & 0xFFFFFFFF;
123
+ uv = a * v + (uv >>> 32);
124
+ var w1 = uv >>> 32;
125
+ uv = u * b + (uv & 0xFFFFFFFF);
126
+
127
+ __res128_hi = a * b + w1 + (uv >>> 32);
128
+ return (uv << 32) | w0;
129
+ }
130
+
131
+ // __umul64Hop computes (hi * 2^64 + lo) = z + (x * y)
132
+ // @ts-ignore: decorator
133
+ @inline
134
+ export function __umul64Hop(z: u64, x: u64, y: u64): u64 {
135
+ var lo = __umulq64(x, y);
136
+ lo = __uadd64(lo, z);
137
+ var hi = __res128_hi + __carry;
138
+ __res128_hi = hi;
139
+ return lo
140
+ }
141
+
142
+ // __umul64Step computes (hi * 2^64 + lo) = z + (x * y) + carry.
143
+ // @ts-ignore: decorator
144
+ @inline
145
+ export function __umul64Step(z: u64, x: u64, y: u64, carry: u64): u64 {
146
+ var lo = __umulq64(x, y)
147
+ lo = __uadd64(lo, carry);
148
+ var hi = __uadd64(__res128_hi, 0, __carry);
149
+ lo = __uadd64(lo, z);
150
+ hi += __carry;
151
+ __res128_hi = hi;
152
+ return lo
153
+ }
154
+
155
+ // __uadd64 returns the sum with carry of x, y and carry: sum = x + y + carry.
156
+ // The carry input must be 0 or 1; otherwise the behavior is undefined.
157
+ // The carryOut output is guaranteed to be 0 or 1.
158
+ // @ts-ignore: decorator
159
+ @inline
160
+ export function __uadd64(x: u64, y: u64, carry: u64 = 0): u64 {
161
+ var sum = x + y + carry
162
+ // // The sum will overflow if both top bits are set (x & y) or if one of them
163
+ // // is (x | y), and a carry from the lower place happened. If such a carry
164
+ // // happens, the top bit will be 1 + 0 + 1 = 0 (& ~sum).
165
+ __carry = ((x & y) | ((x | y) & ~sum)) >>> 63
166
+ return sum;
167
+ }
168
+
169
+ // 64x64 => 128 bits
170
+ @inline
171
+ function mul64To128(x: u64, y: u64): u128 {
172
+ let lo = __umulq64(x, y); // sets __res128_hi
173
+ let hi = __res128_hi;
174
+ return new u128(lo, hi);
175
+ }
176
+
177
+ /**
178
+ * A correct 256×256 -> 256 multiply (mod 2^256).
179
+ * We do standard "schoolbook" multiplication for each 64-bit limb,
180
+ * skipping products that shift above 255 bits (they vanish mod 2^256).
181
+ */
182
+ @global
183
+ export function __mul256(
184
+ ax0: u64, ax1: u64, ax2: u64, ax3: u64,
185
+ bx0: u64, bx1: u64, bx2: u64, bx3: u64
186
+ ): u256 {
187
+ let result = new u256();
188
+ let a = [ax0, ax1, ax2, ax3];
189
+ let b = [bx0, bx1, bx2, bx3];
190
+
191
+ // For each (i,j), partial = a[i]*b[j], shift = 64*(i+j).
192
+ // If shift >= 256, that partial is 0 mod 2^256.
193
+ // Otherwise shift partial, add to result.
194
+ for (let i = 0; i < 4; i++) {
195
+ for (let j = 0; j < 4; j++) {
196
+ let shift = (i + j) << 6; // 64*(i+j)
197
+ if (shift >= 256) continue;
198
+ let p128 = mul64To128(a[i], b[j]); // 128-bit partial product
199
+ // convert to u256
200
+ let part = new u256(p128.lo, p128.hi, 0, 0);
201
+ // shift left by 'shift' bits
202
+ if (shift != 0) {
203
+ part = u256.shl(part, shift);
204
+ }
205
+ // add to accumulator
206
+ result = result + part;
207
+ }
208
+ }
209
+
210
+ return result;
211
+ }
212
+
213
+ // @ts-ignore: decorator
214
+ @global
215
+ export function __multi3(al: u64, ah: u64, bl: u64, bh: u64): u64 {
216
+ var u = al, v = bl;
217
+ var w: u64, k: u64;
218
+
219
+ var u1 = u & 0xFFFFFFFF;
220
+ u >>= 32;
221
+ var v1 = v & 0xFFFFFFFF;
222
+ v >>= 32;
223
+ var t = u1 * v1;
224
+ var w1 = t & 0xFFFFFFFF;
225
+
226
+ t = u * v1 + (t >> 32);
227
+ k = t & 0xFFFFFFFF;
228
+ w = t >> 32;
229
+ t = u1 * v + k;
230
+
231
+ var lo = (t << 32) | w1;
232
+ var hi = u * v + w;
233
+ hi += ah * bl;
234
+ hi += al * bh;
235
+ hi += t >> 32;
236
+
237
+ __res128_hi = hi;
238
+ return lo;
239
+ }
240
+
241
+ // @ts-ignore: decorator
242
+ @global
243
+ export function __floatuntfdi(value: f64): u64 {
244
+ var u = reinterpret<u64>(value);
245
+
246
+ // if (value < -1.7014118346046e38) { // -(2^127-1)
247
+ if (value < reinterpret<f64>(0xC7F0000000000000)) { // -(2^128-1)
248
+ // __float_u128_hi = <u64>-1; // for i128
249
+ __res128_hi = 0;
250
+ // overflow negative
251
+ return 0;
252
+ // } else if (value < -9.2233720368547e18) { // -2^63-1 // for i128
253
+ } else if (value < reinterpret<f64>(0xC3F0000000000000)) { // // -(2^64-1)
254
+ let lo: u64, hi: u64, m: u64;
255
+
256
+ m = (u & 0x000FFFFFFFFFFFFF) | (1 << 52);
257
+ u = (u & 0x7FFFFFFFFFFFFFFF) >> 52;
258
+
259
+ u -= 1075;
260
+ if (u > 64) {
261
+ lo = 0;
262
+ hi = m << (u - 64);
263
+ } else {
264
+ lo = m << u;
265
+ hi = m >> (64 - u);
266
+ }
267
+ // Convert to 2's complement for correct negative representation
268
+ lo = ~lo;
269
+ hi = ~hi;
270
+ lo += 1;
271
+ if (lo == 0) hi += 1; // carry to high part
272
+
273
+ __res128_hi = hi;
274
+ return lo;
275
+ // } else if (value < 9.2233720368547e18) { // 2^63-1 // for i128
276
+ } else if (value < reinterpret<f64>(0x43F0000000000000)) { // 2^64-1
277
+ // __float_u128_hi = (value < 0) ? -1 : 0; // for int
278
+ __res128_hi = 0;
279
+ // fit in a u64
280
+ return <u64>value;
281
+ // } else if (value < 1.7014118346046e38) {
282
+ } else if (value < reinterpret<f64>(0x47F0000000000000)) { // 2^128-1
283
+ let lo: u64, hi: u64, m: u64;
284
+
285
+ m = (u & 0x000FFFFFFFFFFFFF) | (1 << 52);
286
+ u = (u & 0x7FFFFFFFFFFFFFFF) >> 52;
287
+ u -= 1075;
288
+ if (u > 64) {
289
+ lo = 0;
290
+ hi = m << (u - 64);
291
+ } else {
292
+ lo = m << u;
293
+ hi = m >> (64 - u);
294
+ }
295
+ __res128_hi = hi;
296
+ return lo;
297
+ } else {
298
+ // overflow positive
299
+ __res128_hi = <u64>-1; // 0x7FFFFFFFFFFFFFFF for i128
300
+ return <u64>-1;
301
+ }
302
+ }
303
+
304
+ /**
305
+ * Count leading zeros in a 64-bit unsigned integer `x`, returning i32 in [0..64].
306
+ * If x == 0, returns 64.
307
+ */
308
+ function clz64(x: u64): i32 {
309
+ if (x == 0) return 64;
310
+
311
+ let n: i32 = 0;
312
+ // Check high half [ bits 63..32 ]
313
+ if ((x & 0xFFFFFFFF00000000) == 0) {
314
+ n += 32;
315
+ x <<= 32; // shift left so next checks are for the upper bits
316
+ }
317
+ // Check bits [63..48]
318
+ if ((x & 0xFFFF000000000000) == 0) {
319
+ n += 16;
320
+ x <<= 16;
321
+ }
322
+ // Check bits [63..56]
323
+ if ((x & 0xFF00000000000000) == 0) {
324
+ n += 8;
325
+ x <<= 8;
326
+ }
327
+ // Check bits [63..60]
328
+ if ((x & 0xF000000000000000) == 0) {
329
+ n += 4;
330
+ x <<= 4;
331
+ }
332
+ // Check bits [63..62]
333
+ if ((x & 0xC000000000000000) == 0) {
334
+ n += 2;
335
+ x <<= 2;
336
+ }
337
+ // Check bit [63]
338
+ if ((x & 0x8000000000000000) == 0) {
339
+ n += 1;
340
+ }
341
+ return n;
342
+ }
343
+
344
+ /**
345
+ * Count trailing zeros in a 64-bit unsigned integer `x`, returning i32 in [0..64].
346
+ * If x == 0, returns 64.
347
+ */
348
+ function ctz64(x: u64): i32 {
349
+ if (x == 0) return 64;
350
+
351
+ let n: i32 = 0;
352
+ // Check low half [bits 31..0]
353
+ if ((x & 0xFFFFFFFF) == 0) {
354
+ n += 32;
355
+ x >>= 32;
356
+ }
357
+ // Check bits [15..0]
358
+ if ((x & 0xFFFF) == 0) {
359
+ n += 16;
360
+ x >>= 16;
361
+ }
362
+ // Check bits [7..0]
363
+ if ((x & 0xFF) == 0) {
364
+ n += 8;
365
+ x >>= 8;
366
+ }
367
+ // Check bits [3..0]
368
+ if ((x & 0xF) == 0) {
369
+ n += 4;
370
+ x >>= 4;
371
+ }
372
+ // Check bits [1..0]
373
+ if ((x & 0x3) == 0) {
374
+ n += 2;
375
+ x >>= 2;
376
+ }
377
+ // Check bit [0]
378
+ if ((x & 0x1) == 0) {
379
+ n += 1;
380
+ }
381
+ return n;
382
+ }
383
+
384
+ /**
385
+ * Count leading zeros in a 128-bit integer [hi:lo], returning i32 in [0..128].
386
+ * If both hi and lo are 0, returns 128.
387
+ *
388
+ * hi is signed in i128, but we interpret it as unsigned here.
389
+ */
390
+ // @ts-ignore: decorator
391
+ @global @inline
392
+ export function __clz128(lo: u64, hi: i64): i32 {
393
+ let h: u64 = <u64>hi; // reinterpret hi as unsigned
394
+ if (h == 0) {
395
+ // If hi is 0, the leading zeros are "64 plus however many are in lo"
396
+ return 64 + <i32>i64.clz(lo);
397
+ } else {
398
+ // The top 64 bits are set => just measure their leading zeros
399
+ return <i32>i64.clz(h);
400
+ }
401
+ }
402
+
403
+ /**
404
+ * Count trailing zeros in a 128-bit integer [hi:lo], returning i32 in [0..128].
405
+ * If both hi and lo are 0, returns 128.
406
+ *
407
+ * For i128 we typically treat hi as signed, but ctz is purely bitwise, so we
408
+ * can pass it as u64 as well.
409
+ */
410
+ // @ts-ignore: decorator
411
+ @global @inline
412
+ export function __ctz128(lo: u64, hi: u64): i32 {
413
+ if (lo == 0) {
414
+ // Otherwise, ctz is 64 plus ctz(hi)
415
+ return 64 + <i32>i64.ctz(hi);
416
+ } else {
417
+ // If the lower 64 bits are non-zero, measure ctz(lo)
418
+ return <i32>i64.ctz(lo);
419
+ }
420
+ }
421
+
422
+ // @ts-ignore: decorator
423
+ @global
424
+ export function __udivmod128(alo: u64, ahi: u64, blo: u64, bhi: u64): u64 {
425
+ var bzn = __clz128(blo, bhi); // N
426
+
427
+ // b == 0
428
+ if (bzn == 128) {
429
+ throw new RangeError("Division by zero"); // division by zero
430
+ }
431
+
432
+ // var azn = __clz128(alo, ahi); // M
433
+ var btz = __ctz128(blo, bhi); // N
434
+
435
+ // a == 0
436
+ if (!(alo | ahi)) {
437
+ __divmod_quot_hi = 0;
438
+ __divmod_rem_lo = 0;
439
+ __divmod_rem_hi = 0;
440
+ return 0;
441
+ }
442
+
443
+ // a / 1
444
+ if (bzn == 127) {
445
+ __divmod_quot_hi = ahi;
446
+ __divmod_rem_lo = 0;
447
+ __divmod_rem_hi = 0;
448
+ return alo;
449
+ }
450
+
451
+ // a == b
452
+ if (alo == blo && ahi == bhi) {
453
+ __divmod_quot_hi = 0;
454
+ __divmod_rem_lo = 0;
455
+ __divmod_rem_hi = 0;
456
+ return 1;
457
+ }
458
+
459
+ if (!(ahi | bhi)) {
460
+ __divmod_quot_hi = 0;
461
+ __divmod_rem_hi = 0;
462
+ // if `b.lo` is power of two
463
+ if (!(blo & (blo - 1))) {
464
+ __divmod_rem_lo = alo & (blo - 1);
465
+ return alo >> btz;
466
+ } else {
467
+ let dlo = alo / blo;
468
+ __divmod_rem_lo = alo - dlo * blo;
469
+ return dlo;
470
+ }
471
+ }
472
+ return __udivmod128core(alo, ahi, blo, bhi);
473
+ }
474
+
475
+ function __udivmod128core(alo: u64, ahi: u64, blo: u64, bhi: u64): u64 {
476
+ var r = new u128(alo, ahi);
477
+ var d = new u128(blo, bhi);
478
+ var q = new u128(0, 0);
479
+
480
+ // Standard division by shifting
481
+ var leadingZeros = __clz128(blo, bhi) - __clz128(alo, ahi);
482
+
483
+ if (leadingZeros < 0) {
484
+ __divmod_quot_hi = 0;
485
+ __divmod_rem_lo = alo;
486
+ __divmod_rem_hi = ahi;
487
+ return 0;
488
+ }
489
+
490
+ var dShift = u128.shl(d, leadingZeros);
491
+
492
+ for (let i = 0; i <= leadingZeros; i++) {
493
+ q = u128.shl(q, 1);
494
+ if (r >= dShift) {
495
+ r -= dShift;
496
+ q = u128.add(q, u128.One);
497
+ }
498
+ dShift = u128.shr(dShift, 1);
499
+ }
500
+
501
+ __divmod_quot_hi = q.hi;
502
+ __divmod_rem_lo = r.lo;
503
+ __divmod_rem_hi = r.hi;
504
+ return q.lo;
505
+ }
506
+
507
+ // @ts-ignore: decorator
508
+ @global
509
+ export function __udivmod128_10(lo: u64, hi: u64): u64 {
510
+ if (hi == 0) {
511
+ __divmod_quot_hi = 0;
512
+ let q = lo / 10;
513
+ __divmod_rem_lo = lo - (q * 10);
514
+ __divmod_rem_hi = 0;
515
+ return q;
516
+ }
517
+
518
+ // High part division
519
+ let q_hi = hi / 10;
520
+ let r_hi = hi - (q_hi * 10);
521
+
522
+ // Low part chunking to avoid 128-bit math
523
+ // r_hi becomes the high bits for the next division
524
+ let lo_hi = lo >>> 32;
525
+ let lo_lo = lo & 0xFFFFFFFF;
526
+
527
+ // Divide upper half of lo (plus carry from hi)
528
+ let t1 = (r_hi << 32) | lo_hi;
529
+ let q1 = t1 / 10;
530
+ let r1 = t1 - (q1 * 10);
531
+
532
+ // Divide lower half of lo (plus carry from above)
533
+ let t2 = (r1 << 32) | lo_lo;
534
+ let q2 = t2 / 10;
535
+ let r2 = t2 - (q2 * 10);
536
+
537
+ // Reassemble quotient
538
+ // q1 is known to fit in 32 bits because max t1 < 10 * 2^32
539
+ let q_lo = (q1 << 32) | q2;
540
+
541
+ __divmod_quot_hi = q_hi;
542
+ __divmod_rem_lo = r2;
543
+ __divmod_rem_hi = 0;
544
+
545
+ return q_lo;
546
+ }
@@ -0,0 +1 @@
1
+ export * from "./integer";