toilscript 0.1.2 → 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.
- package/README.md +1 -1
- package/dist/cli.js +3737 -5
- package/dist/cli.js.map +2 -2
- package/dist/importmap.json +2 -2
- package/dist/web.js +3 -3
- package/package.json +1 -1
- package/std/assembly/bignum/LICENSE +201 -0
- package/std/assembly/bignum/NOTICE +13 -0
- package/std/assembly/bignum/fixed/fp128.ts +58 -0
- package/std/assembly/bignum/fixed/fp256.ts +9 -0
- package/std/assembly/bignum/fixed/index.ts +38 -0
- package/std/assembly/bignum/fixed/safe/fp128.ts +3 -0
- package/std/assembly/bignum/fixed/safe/fp256.ts +3 -0
- package/std/assembly/bignum/fixed/types.ts +103 -0
- package/std/assembly/bignum/globals.ts +546 -0
- package/std/assembly/bignum/index.ts +1 -0
- package/std/assembly/bignum/integer/i128.ts +413 -0
- package/std/assembly/bignum/integer/i256.ts +50 -0
- package/std/assembly/bignum/integer/index.ts +3 -0
- package/std/assembly/bignum/integer/u128.ts +963 -0
- package/std/assembly/bignum/integer/u256.ts +1007 -0
- package/std/assembly/bignum/utils.ts +260 -0
- package/std/assembly/bignum.ts +18 -0
- package/std/assembly/index.d.ts +257 -0
- package/std/assembly/toilscript.ts +1 -1
- package/std/assembly.json +1 -0
- package/std/ts-plugin.cjs +44 -0
|
@@ -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";
|