toilscript 0.1.4 → 0.1.6
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/dist/cli.js +3480 -21
- 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 +7 -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 +1 -1
- package/std/assembly/toilscript.d.ts +273 -0
- package/std/assembly/toilscript.ts +0 -16
|
@@ -0,0 +1,963 @@
|
|
|
1
|
+
import { i128 } from './i128';
|
|
2
|
+
import { i256 } from './i256';
|
|
3
|
+
import { u256 } from './u256';
|
|
4
|
+
|
|
5
|
+
// TODO import this on top level 'index.ts'
|
|
6
|
+
import {
|
|
7
|
+
__clz128,
|
|
8
|
+
__ctz128,
|
|
9
|
+
__divmod_quot_hi,
|
|
10
|
+
__divmod_rem_hi,
|
|
11
|
+
__divmod_rem_lo,
|
|
12
|
+
__floatuntidf,
|
|
13
|
+
__multi3,
|
|
14
|
+
__res128_hi,
|
|
15
|
+
__udivmod128,
|
|
16
|
+
__udivmod128_10,
|
|
17
|
+
} from '../globals';
|
|
18
|
+
|
|
19
|
+
import { atou128, u128toDecimalString } from '../utils';
|
|
20
|
+
|
|
21
|
+
@lazy const HEX_CHARS = '0123456789abcdef';
|
|
22
|
+
|
|
23
|
+
export class u128 {
|
|
24
|
+
// CACHE: Static instances to avoid allocation
|
|
25
|
+
private static readonly _ZERO: u128 = new u128(0, 0);
|
|
26
|
+
private static readonly _ONE: u128 = new u128(1, 0);
|
|
27
|
+
private static readonly _MAX: u128 = new u128(-1, -1);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create 128-bit unsigned integer from 64-bit parts
|
|
31
|
+
* @param lo low 64-bit part of 128-bit unsigned integer
|
|
32
|
+
* @param hi high 64-bit part of 128-bit unsigned integer
|
|
33
|
+
*/
|
|
34
|
+
constructor(
|
|
35
|
+
public lo: u64 = 0,
|
|
36
|
+
public hi: u64 = 0,
|
|
37
|
+
) {
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@inline static get immutableZero(): u128 {
|
|
41
|
+
return u128._ZERO;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@inline static get immutableOne(): u128 {
|
|
45
|
+
return u128._ONE;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@inline static get immutableMin(): u128 {
|
|
49
|
+
return u128._ZERO;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@inline static get immutableMax(): u128 {
|
|
53
|
+
return u128._MAX;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@inline static get Zero(): u128 { return new u128(0, 0); }
|
|
57
|
+
@inline static get One(): u128 { return new u128(1, 0); }
|
|
58
|
+
@inline static get Min(): u128 { return new u128(0, 0); }
|
|
59
|
+
@inline static get Max(): u128 { return new u128(-1, -1); }
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Ensures the current instance is not a static constant.
|
|
63
|
+
* If it is, throws an error.
|
|
64
|
+
* Cost: 3 integer comparisons. Cheap insurance.
|
|
65
|
+
*/
|
|
66
|
+
@inline
|
|
67
|
+
private checkMutable(): void {
|
|
68
|
+
const ptr = changetype<usize>(this);
|
|
69
|
+
if (ptr == changetype<usize>(u128._ZERO) ||
|
|
70
|
+
ptr == changetype<usize>(u128._ONE) ||
|
|
71
|
+
ptr == changetype<usize>(u128._MAX)) {
|
|
72
|
+
throw new Error("u128: Immutable constant");
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@inline
|
|
77
|
+
static fromString(value: string, radix: i32 = 10): u128 {
|
|
78
|
+
return atou128(value, radix);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@inline
|
|
82
|
+
static fromI256(value: i256): u128 {
|
|
83
|
+
return new u128(value.lo1, value.lo2);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@inline
|
|
87
|
+
static fromU256(value: u256): u128 {
|
|
88
|
+
return new u128(value.lo1, value.lo2);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@inline
|
|
92
|
+
static fromI128(value: i128): u128 {
|
|
93
|
+
return new u128(value.lo, value.hi);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@inline
|
|
97
|
+
static fromU128(value: u128): u128 {
|
|
98
|
+
return new u128(value.lo, value.hi);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@inline
|
|
102
|
+
static fromI64(value: i64): u128 {
|
|
103
|
+
if (value == 0) return u128.Zero;
|
|
104
|
+
if (value == 1) return u128.One;
|
|
105
|
+
return new u128(value, value >> 63);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@inline
|
|
109
|
+
static fromU64(value: u64): u128 {
|
|
110
|
+
if (value == 0) return u128.Zero;
|
|
111
|
+
if (value == 1) return u128.One;
|
|
112
|
+
return new u128(value);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// max safe uint for f64 actually 53-bits
|
|
116
|
+
@inline
|
|
117
|
+
static fromF64(value: f64): u128 {
|
|
118
|
+
return new u128(<u64>value, reinterpret<i64>(value) >> 63);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// max safe int for f32 actually 23-bits
|
|
122
|
+
@inline
|
|
123
|
+
static fromF32(value: f32): u128 {
|
|
124
|
+
return new u128(<u64>value, <u64>(reinterpret<i32>(value) >> 31));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@inline
|
|
128
|
+
static fromI32(value: i32): u128 {
|
|
129
|
+
if (value == 0) return u128.Zero;
|
|
130
|
+
if (value == 1) return u128.One;
|
|
131
|
+
return new u128(value, value >> 31);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@inline
|
|
135
|
+
static fromU32(value: u32): u128 {
|
|
136
|
+
if (value == 0) return u128.Zero;
|
|
137
|
+
if (value == 1) return u128.One;
|
|
138
|
+
return new u128(value);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@inline
|
|
142
|
+
static fromBool(value: bool): u128 {
|
|
143
|
+
return value ? u128.One : u128.Zero;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@inline
|
|
147
|
+
static fromBits(lo1: u32, lo2: u32, hi1: u32, hi2: u32): u128 {
|
|
148
|
+
return new u128(
|
|
149
|
+
<u64>lo1 | ((<u64>lo2) << 32),
|
|
150
|
+
<u64>hi1 | ((<u64>hi2) << 32),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@inline
|
|
155
|
+
static fromBytes<T>(array: T, bigEndian: bool = false): u128 {
|
|
156
|
+
// @ts-ignore
|
|
157
|
+
if (array instanceof u8[]) {
|
|
158
|
+
return bigEndian
|
|
159
|
+
// @ts-ignore
|
|
160
|
+
? u128.fromBytesBE(<u8[]>array)
|
|
161
|
+
// @ts-ignore
|
|
162
|
+
: u128.fromBytesLE(<u8[]>array);
|
|
163
|
+
} else if (array instanceof Uint8Array) {
|
|
164
|
+
return bigEndian
|
|
165
|
+
? u128.fromUint8ArrayBE(<Uint8Array>array)
|
|
166
|
+
: u128.fromUint8ArrayLE(<Uint8Array>array);
|
|
167
|
+
} else {
|
|
168
|
+
throw new TypeError("Unsupported generic type");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@inline
|
|
173
|
+
static fromBytesLE(array: u8[]): u128 {
|
|
174
|
+
if (array.length !== 16) throw new Error("Invalid length");
|
|
175
|
+
let buffer = array.dataStart;
|
|
176
|
+
return new u128(
|
|
177
|
+
load<u64>(buffer, 0),
|
|
178
|
+
load<u64>(buffer, 8)
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@inline
|
|
183
|
+
static fromBytesBE(array: u8[]): u128 {
|
|
184
|
+
if (array.length !== 16) throw new Error("Invalid length");
|
|
185
|
+
let buffer = array.dataStart;
|
|
186
|
+
return new u128(
|
|
187
|
+
bswap<u64>(load<u64>(buffer, 8)),
|
|
188
|
+
bswap<u64>(load<u64>(buffer, 0))
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@inline
|
|
193
|
+
static fromUint8ArrayLE(array: Uint8Array): u128 {
|
|
194
|
+
if (array.length !== 16) throw new Error("Invalid length");
|
|
195
|
+
let buffer = array.dataStart;
|
|
196
|
+
return new u128(
|
|
197
|
+
load<u64>(buffer, 0),
|
|
198
|
+
load<u64>(buffer, 8)
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@inline
|
|
203
|
+
static fromUint8ArrayBE(array: Uint8Array): u128 {
|
|
204
|
+
if (array.length !== 16) throw new Error("Invalid length");
|
|
205
|
+
let buffer = array.dataStart;
|
|
206
|
+
return new u128(
|
|
207
|
+
bswap<u64>(load<u64>(buffer, 8)),
|
|
208
|
+
bswap<u64>(load<u64>(buffer, 0))
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Create 128-bit unsigned integer from generic type T
|
|
214
|
+
* @param value
|
|
215
|
+
* @returns 128-bit unsigned integer
|
|
216
|
+
*/
|
|
217
|
+
@inline
|
|
218
|
+
static from<T>(value: T): u128 {
|
|
219
|
+
if (value instanceof bool) return u128.fromU64(<u64>value);
|
|
220
|
+
else if (value instanceof i8) return u128.fromI64(<i64>value);
|
|
221
|
+
else if (value instanceof u8) return u128.fromU64(<u64>value);
|
|
222
|
+
else if (value instanceof i16) return u128.fromI64(<i64>value);
|
|
223
|
+
else if (value instanceof u16) return u128.fromU64(<u64>value);
|
|
224
|
+
else if (value instanceof i32) return u128.fromI64(<i64>value);
|
|
225
|
+
else if (value instanceof u32) return u128.fromU64(<u64>value);
|
|
226
|
+
else if (value instanceof i64) return u128.fromI64(<i64>value);
|
|
227
|
+
else if (value instanceof u64) return u128.fromU64(<u64>value);
|
|
228
|
+
else if (value instanceof f32) return u128.fromF64(<f64>value);
|
|
229
|
+
else if (value instanceof f64) return u128.fromF64(<f64>value);
|
|
230
|
+
else if (value instanceof i128) return u128.fromI128(<i128>value);
|
|
231
|
+
else if (value instanceof u128) return u128.fromU128(<u128>value);
|
|
232
|
+
else if (value instanceof i256) return u128.fromI256(<i256>value);
|
|
233
|
+
else if (value instanceof u256) return u128.fromU256(<u256>value);
|
|
234
|
+
else if (value instanceof u8[]) return u128.fromBytes(<u8[]>value);
|
|
235
|
+
else if (value instanceof Uint8Array) return u128.fromBytes(<Uint8Array>value);
|
|
236
|
+
else if (value instanceof String) return u128.fromString(<string>value);
|
|
237
|
+
else throw new TypeError("Unsupported generic type");
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
@inline @operator.prefix('!')
|
|
241
|
+
static isEmpty(value: u128): bool {
|
|
242
|
+
return !(value.lo | value.hi);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
@inline @operator('|')
|
|
246
|
+
static or(a: u128, b: u128): u128 {
|
|
247
|
+
return new u128(a.lo | b.lo, a.hi | b.hi);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
@inline @operator('^')
|
|
251
|
+
static xor(a: u128, b: u128): u128 {
|
|
252
|
+
return new u128(a.lo ^ b.lo, a.hi ^ b.hi);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
@inline @operator('&')
|
|
256
|
+
static and(a: u128, b: u128): u128 {
|
|
257
|
+
return new u128(a.lo & b.lo, a.hi & b.hi);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@inline @operator('<<')
|
|
261
|
+
static shl(value: u128, shift: i32): u128 {
|
|
262
|
+
// Cache check: if shift is 0 or invalid, return existing constants if possible
|
|
263
|
+
if (shift <= 0) {
|
|
264
|
+
return shift == 0 ? value.clone() : u128.Zero; // Use cached Zero
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (shift >= 128) {
|
|
268
|
+
return u128.Zero; // Use cached Zero
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Unrolled shift logic
|
|
272
|
+
if (shift < 64) {
|
|
273
|
+
const lo = value.lo << shift;
|
|
274
|
+
const hi = (value.hi << shift) | (value.lo >>> (64 - shift));
|
|
275
|
+
return new u128(lo, hi);
|
|
276
|
+
} else {
|
|
277
|
+
// shift >= 64
|
|
278
|
+
return new u128(0, value.lo << (shift - 64));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@inline @operator('>>')
|
|
283
|
+
static shr(value: u128, shift: i32): u128 {
|
|
284
|
+
shift &= 127;
|
|
285
|
+
if (shift == 0) return value.clone();
|
|
286
|
+
|
|
287
|
+
// Unrolled shift logic
|
|
288
|
+
if (shift < 64) {
|
|
289
|
+
let hi = value.hi >> shift;
|
|
290
|
+
let lo = (value.hi << (64 - shift)) | (value.lo >> shift);
|
|
291
|
+
return new u128(lo, hi);
|
|
292
|
+
} else {
|
|
293
|
+
let s = shift - 64;
|
|
294
|
+
return new u128(value.hi >> s, 0);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@inline @operator('>>>')
|
|
299
|
+
static shr_u(value: u128, shift: i32): u128 {
|
|
300
|
+
return u128.shr(value, shift);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
@inline
|
|
304
|
+
static rotl(value: u128, shift: i32): u128 {
|
|
305
|
+
let n = shift & 127;
|
|
306
|
+
if (n == 0) return value.clone();
|
|
307
|
+
|
|
308
|
+
let lo = value.lo;
|
|
309
|
+
let hi = value.hi;
|
|
310
|
+
if (n == 64) {
|
|
311
|
+
return new u128(hi, lo);
|
|
312
|
+
}
|
|
313
|
+
if (n & 64) {
|
|
314
|
+
let t = lo;
|
|
315
|
+
lo = hi;
|
|
316
|
+
hi = t;
|
|
317
|
+
}
|
|
318
|
+
let slo = lo << n;
|
|
319
|
+
let shi = hi << n;
|
|
320
|
+
let rlo = lo >> (64 - n);
|
|
321
|
+
let rhi = hi >> (64 - n);
|
|
322
|
+
return new u128(slo | rhi, shi | rlo);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
@inline
|
|
326
|
+
static rotr(value: u128, shift: i32): u128 {
|
|
327
|
+
let n = shift & 127;
|
|
328
|
+
if (n == 0) return value.clone();
|
|
329
|
+
|
|
330
|
+
let lo = value.lo;
|
|
331
|
+
let hi = value.hi;
|
|
332
|
+
if (n == 64) {
|
|
333
|
+
return new u128(hi, lo);
|
|
334
|
+
}
|
|
335
|
+
if (n & 64) {
|
|
336
|
+
let t = lo;
|
|
337
|
+
lo = hi;
|
|
338
|
+
hi = t;
|
|
339
|
+
}
|
|
340
|
+
let slo = lo >> n;
|
|
341
|
+
let shi = hi >> n;
|
|
342
|
+
let rlo = lo << (64 - n);
|
|
343
|
+
let rhi = hi << (64 - n);
|
|
344
|
+
return new u128(slo | rhi, shi | rlo);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
@inline @operator('+')
|
|
348
|
+
static add(a: u128, b: u128): u128 {
|
|
349
|
+
var alo = a.lo;
|
|
350
|
+
var lo = alo + b.lo;
|
|
351
|
+
var hi = a.hi + b.hi + u64(lo < alo);
|
|
352
|
+
return new u128(lo, hi);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
@inline @operator('-')
|
|
356
|
+
static sub(a: u128, b: u128): u128 {
|
|
357
|
+
var alo = a.lo;
|
|
358
|
+
var lo = alo - b.lo;
|
|
359
|
+
var hi = a.hi - b.hi - u64(lo > alo);
|
|
360
|
+
return new u128(lo, hi);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// mul: u128 x u128 = u128
|
|
364
|
+
@inline @operator('*')
|
|
365
|
+
static mul(a: u128, b: u128): u128 {
|
|
366
|
+
return new u128(
|
|
367
|
+
__multi3(a.lo, a.hi, b.lo, b.hi),
|
|
368
|
+
__res128_hi
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
@inline @operator('/')
|
|
373
|
+
static div(a: u128, b: u128): u128 {
|
|
374
|
+
return new u128(
|
|
375
|
+
__udivmod128(a.lo, a.hi, b.lo, b.hi),
|
|
376
|
+
__divmod_quot_hi
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
@inline @operator('%')
|
|
381
|
+
static rem(a: u128, b: u128): u128 {
|
|
382
|
+
__udivmod128(a.lo, a.hi, b.lo, b.hi);
|
|
383
|
+
return new u128(__divmod_rem_lo, __divmod_rem_hi);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
@inline
|
|
387
|
+
static div10(value: u128): u128 {
|
|
388
|
+
return new u128(
|
|
389
|
+
__udivmod128_10(value.lo, value.hi),
|
|
390
|
+
__divmod_quot_hi
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
@inline
|
|
395
|
+
static rem10(value: u128): u128 {
|
|
396
|
+
__udivmod128_10(value.lo, value.hi);
|
|
397
|
+
return new u128(__divmod_rem_lo, __divmod_rem_hi);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Calculate power of base with exponent
|
|
402
|
+
* @param base 128-bit unsigned integer
|
|
403
|
+
* @param exponent 32-bit signed integer
|
|
404
|
+
* @returns 128-bit unsigned integer
|
|
405
|
+
*/
|
|
406
|
+
@operator('**')
|
|
407
|
+
static pow(base: u128, exponent: i32): u128 {
|
|
408
|
+
// any negative exponent produce zero
|
|
409
|
+
|
|
410
|
+
var result = u128.One;
|
|
411
|
+
|
|
412
|
+
if (base == result) return result;
|
|
413
|
+
var tmp = base.clone();
|
|
414
|
+
if (exponent <= 1) {
|
|
415
|
+
if (exponent < 0) return u128.Zero;
|
|
416
|
+
return exponent == 0 ? result : tmp;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (ASC_SHRINK_LEVEL < 1) {
|
|
420
|
+
var lo = base.lo;
|
|
421
|
+
var hi = base.hi;
|
|
422
|
+
// if base > u64::max and exp > 1 always return "0"
|
|
423
|
+
if (!lo) return u128.Zero;
|
|
424
|
+
if (!hi) {
|
|
425
|
+
let lo1 = lo - 1;
|
|
426
|
+
// "1 ^ exponent" always return "1"
|
|
427
|
+
if (!lo1) return result;
|
|
428
|
+
|
|
429
|
+
// if base is power of two do "1 << log2(base) * exp"
|
|
430
|
+
if (!(lo & lo1)) {
|
|
431
|
+
let shift = <i32>(64 - clz(lo1)) * exponent;
|
|
432
|
+
// @ts-ignore
|
|
433
|
+
return shift < 128 ? result << shift : u128.Zero;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (exponent <= 4) {
|
|
438
|
+
let baseSq = tmp.sqr();
|
|
439
|
+
switch (exponent) {
|
|
440
|
+
case 2:
|
|
441
|
+
return baseSq; // base ^ 2
|
|
442
|
+
// @ts-ignore
|
|
443
|
+
case 3:
|
|
444
|
+
return baseSq * base; // base ^ 2 * base
|
|
445
|
+
case 4:
|
|
446
|
+
return baseSq.sqr(); // base ^ 2 * base ^ 2
|
|
447
|
+
default:
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
let log = 32 - clz(exponent);
|
|
453
|
+
if (log <= 7) {
|
|
454
|
+
// 128 = 2 ^ 7, so need usually only seven cases
|
|
455
|
+
switch (log) {
|
|
456
|
+
case 7:
|
|
457
|
+
// @ts-ignore
|
|
458
|
+
if (exponent & 1) result *= tmp;
|
|
459
|
+
exponent >>= 1;
|
|
460
|
+
tmp.sqr();
|
|
461
|
+
case 6:
|
|
462
|
+
// @ts-ignore
|
|
463
|
+
if (exponent & 1) result *= tmp;
|
|
464
|
+
exponent >>= 1;
|
|
465
|
+
tmp.sqr();
|
|
466
|
+
case 5:
|
|
467
|
+
// @ts-ignore
|
|
468
|
+
if (exponent & 1) result *= tmp;
|
|
469
|
+
exponent >>= 1;
|
|
470
|
+
tmp.sqr();
|
|
471
|
+
case 4:
|
|
472
|
+
// @ts-ignore
|
|
473
|
+
if (exponent & 1) result *= tmp;
|
|
474
|
+
exponent >>= 1;
|
|
475
|
+
tmp.sqr();
|
|
476
|
+
case 3:
|
|
477
|
+
// @ts-ignore
|
|
478
|
+
if (exponent & 1) result *= tmp;
|
|
479
|
+
exponent >>= 1;
|
|
480
|
+
tmp.sqr();
|
|
481
|
+
case 2:
|
|
482
|
+
// @ts-ignore
|
|
483
|
+
if (exponent & 1) result *= tmp;
|
|
484
|
+
exponent >>= 1;
|
|
485
|
+
tmp.sqr();
|
|
486
|
+
case 1:
|
|
487
|
+
// @ts-ignore
|
|
488
|
+
if (exponent & 1) result *= tmp;
|
|
489
|
+
}
|
|
490
|
+
return result;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
while (exponent > 0) {
|
|
495
|
+
// @ts-ignore
|
|
496
|
+
if (exponent & 1) result *= tmp;
|
|
497
|
+
exponent >>= 1;
|
|
498
|
+
tmp.sqr();
|
|
499
|
+
}
|
|
500
|
+
return result;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// compute floor(sqrt(x))
|
|
504
|
+
static sqrt(value: u128): u128 {
|
|
505
|
+
var rem = value.clone();
|
|
506
|
+
if (value < new u128(2)) {
|
|
507
|
+
return rem;
|
|
508
|
+
}
|
|
509
|
+
var res = u128.Zero;
|
|
510
|
+
// @ts-ignore
|
|
511
|
+
var pos = u128.One << (127 - (u128.clz(value) | 1));
|
|
512
|
+
// @ts-ignore
|
|
513
|
+
while (!pos.isZero()) {
|
|
514
|
+
// @ts-ignore
|
|
515
|
+
value = res + pos;
|
|
516
|
+
if (rem >= value) {
|
|
517
|
+
// @ts-ignore
|
|
518
|
+
rem = rem - value;
|
|
519
|
+
// @ts-ignore
|
|
520
|
+
res = pos + value;
|
|
521
|
+
}
|
|
522
|
+
// @ts-ignore
|
|
523
|
+
res >>= 1;
|
|
524
|
+
pos >>= 2;
|
|
525
|
+
}
|
|
526
|
+
return res;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
@inline @operator('==')
|
|
530
|
+
static eq(a: u128, b: u128): bool {
|
|
531
|
+
return a.hi == b.hi && a.lo == b.lo;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
@inline @operator('!=')
|
|
535
|
+
static ne(a: u128, b: u128): bool {
|
|
536
|
+
return !u128.eq(a, b);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
@inline @operator('<')
|
|
540
|
+
static lt(a: u128, b: u128): bool {
|
|
541
|
+
var ah = a.hi, bh = b.hi;
|
|
542
|
+
return ah == bh ? a.lo < b.lo : ah < bh;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
@inline @operator('>')
|
|
546
|
+
static gt(a: u128, b: u128): bool {
|
|
547
|
+
var ah = a.hi, bh = b.hi;
|
|
548
|
+
return ah == bh ? a.lo > b.lo : ah > bh;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
@inline @operator('<=')
|
|
552
|
+
static le(a: u128, b: u128): bool {
|
|
553
|
+
return !u128.gt(a, b);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
@inline @operator('>=')
|
|
557
|
+
static ge(a: u128, b: u128): bool {
|
|
558
|
+
return !u128.lt(a, b);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Get ordering
|
|
563
|
+
* if a > b then result is 1
|
|
564
|
+
* if a < b then result is -1
|
|
565
|
+
* if a = b then result is 0
|
|
566
|
+
* @param a 128-bit unsigned integer
|
|
567
|
+
* @param b 128-bit unsigned integer
|
|
568
|
+
* @returns 32-bit signed integer
|
|
569
|
+
*/
|
|
570
|
+
@inline
|
|
571
|
+
static ord(a: u128, b: u128): i32 {
|
|
572
|
+
// if a > b => +1
|
|
573
|
+
// if a < b => -1
|
|
574
|
+
// if equal => 0
|
|
575
|
+
if (a.hi > b.hi) return 1;
|
|
576
|
+
if (a.hi < b.hi) return -1;
|
|
577
|
+
if (a.lo > b.lo) return 1;
|
|
578
|
+
if (a.lo < b.lo) return -1;
|
|
579
|
+
return 0;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Compute count of set (populated) bits
|
|
584
|
+
* @param value 128-bit unsigned integer
|
|
585
|
+
* @returns 32-bit signed integer
|
|
586
|
+
*/
|
|
587
|
+
@inline
|
|
588
|
+
static popcnt(value: u128): i32 {
|
|
589
|
+
return <i32>(popcnt(value.lo) + popcnt(value.hi));
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Compute bit count of leading zeros
|
|
594
|
+
* @param value 128-bit unsigned integer
|
|
595
|
+
* @returns 32-bit signed integer
|
|
596
|
+
*/
|
|
597
|
+
@inline
|
|
598
|
+
static clz(value: u128): i32 {
|
|
599
|
+
return __clz128(value.lo, value.hi);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Compute bit count of trailing zeros
|
|
604
|
+
* @param value 128-bit unsigned integer
|
|
605
|
+
* @returns 32-bit signed integer
|
|
606
|
+
*/
|
|
607
|
+
@inline
|
|
608
|
+
static ctz(value: u128): i32 {
|
|
609
|
+
return __ctz128(value.lo, value.hi);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Calculate squared value (value ** 2)
|
|
614
|
+
* @param value 128-bit unsigned integer
|
|
615
|
+
* @returns 128-bit unsigned integer
|
|
616
|
+
*/
|
|
617
|
+
@inline
|
|
618
|
+
static sqr(value: u128): u128 {
|
|
619
|
+
return value.clone().sqr();
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Calculate multiply and division as `number * numerator / denominator`
|
|
624
|
+
* without overflow in multiplication part.
|
|
625
|
+
*
|
|
626
|
+
* @returns 128-bit unsigned integer
|
|
627
|
+
*/
|
|
628
|
+
static muldiv(a: u128, b: u128, c: u128): u128 {
|
|
629
|
+
let A = u256.fromU128(a);
|
|
630
|
+
let B = u256.fromU128(b);
|
|
631
|
+
let C = u256.fromU128(c);
|
|
632
|
+
|
|
633
|
+
let product = u256.mul(A, B);
|
|
634
|
+
let quotient = u256.div(product, C);
|
|
635
|
+
|
|
636
|
+
return quotient.toU128();
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
@inline
|
|
640
|
+
set(value: u128): this {
|
|
641
|
+
this.checkMutable();
|
|
642
|
+
this.lo = value.lo;
|
|
643
|
+
this.hi = value.hi;
|
|
644
|
+
return this;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
@inline
|
|
648
|
+
setI64(value: i64): this {
|
|
649
|
+
this.checkMutable();
|
|
650
|
+
this.lo = value;
|
|
651
|
+
this.hi = value >> 63;
|
|
652
|
+
return this;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
@inline
|
|
656
|
+
setU64(value: u64): this {
|
|
657
|
+
this.checkMutable();
|
|
658
|
+
this.lo = value;
|
|
659
|
+
this.hi = 0;
|
|
660
|
+
return this;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
@inline
|
|
664
|
+
setI32(value: i32): this {
|
|
665
|
+
this.checkMutable();
|
|
666
|
+
this.lo = value;
|
|
667
|
+
this.hi = value >> 63;
|
|
668
|
+
return this;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
@inline
|
|
672
|
+
setU32(value: u32): this {
|
|
673
|
+
this.checkMutable();
|
|
674
|
+
this.lo = value;
|
|
675
|
+
this.hi = 0;
|
|
676
|
+
return this;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
@inline
|
|
680
|
+
isZero(): bool {
|
|
681
|
+
return !(this.lo | this.hi);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
@inline @operator.prefix('~')
|
|
685
|
+
not(): u128 {
|
|
686
|
+
return new u128(~this.lo, ~this.hi);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
@inline @operator.prefix('+')
|
|
690
|
+
pos(): u128 {
|
|
691
|
+
return this;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
@inline @operator.prefix('-')
|
|
695
|
+
neg(): u128 {
|
|
696
|
+
var lo = ~this.lo;
|
|
697
|
+
var hi = ~this.hi;
|
|
698
|
+
var lo1 = lo + 1;
|
|
699
|
+
return new u128(lo1, hi + u64(lo1 < lo));
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
@operator.prefix('++')
|
|
703
|
+
preInc(): this {
|
|
704
|
+
this.checkMutable();
|
|
705
|
+
var lo = this.lo;
|
|
706
|
+
var lo1 = lo + 1;
|
|
707
|
+
this.hi += u64(lo1 < lo);
|
|
708
|
+
this.lo = lo1;
|
|
709
|
+
return this;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
@operator.prefix('--')
|
|
713
|
+
preDec(): this {
|
|
714
|
+
this.checkMutable();
|
|
715
|
+
var lo = this.lo;
|
|
716
|
+
var lo1 = lo - 1;
|
|
717
|
+
this.hi -= u64(lo1 > lo);
|
|
718
|
+
this.lo = lo1;
|
|
719
|
+
return this;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
@operator.postfix('++')
|
|
723
|
+
postInc(): u128 {
|
|
724
|
+
return this.clone().preInc();
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
@operator.postfix('--')
|
|
728
|
+
postDec(): u128 {
|
|
729
|
+
return this.clone().preDec();
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Calculate inplace squared 128-bit unsigned integer (this ** 2)
|
|
734
|
+
* @returns 128-bit unsigned integer
|
|
735
|
+
*/
|
|
736
|
+
sqr(): this {
|
|
737
|
+
this.checkMutable();
|
|
738
|
+
// Use built-in 128×128 => 128 multiplication
|
|
739
|
+
// i.e. "x * x"
|
|
740
|
+
let tmp = u128.mul(this, this);
|
|
741
|
+
this.lo = tmp.lo;
|
|
742
|
+
this.hi = tmp.hi;
|
|
743
|
+
return this;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Convert to 256-bit signed integer
|
|
748
|
+
* @returns 256-bit signed integer
|
|
749
|
+
*/
|
|
750
|
+
@inline
|
|
751
|
+
toI256(): i256 {
|
|
752
|
+
return new i256(this.lo, this.hi);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Convert to 256-bit unsigned integer
|
|
757
|
+
* @returns 256-bit unsigned integer
|
|
758
|
+
*/
|
|
759
|
+
@inline
|
|
760
|
+
toU256(): u256 {
|
|
761
|
+
return new u256(this.lo, this.hi);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Convert to 128-bit signed integer
|
|
766
|
+
* @returns 128-bit signed integer
|
|
767
|
+
*/
|
|
768
|
+
@inline
|
|
769
|
+
toI128(): i128 {
|
|
770
|
+
return new i128(this.lo, this.hi);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* Convert to 128-bit unsigned integer
|
|
775
|
+
* @returns 128-bit unsigned integer
|
|
776
|
+
*/
|
|
777
|
+
@inline
|
|
778
|
+
toU128(): this {
|
|
779
|
+
return this;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Convert to 64-bit signed integer
|
|
784
|
+
* @returns 64-bit signed integer
|
|
785
|
+
*/
|
|
786
|
+
@inline
|
|
787
|
+
toI64(): i64 {
|
|
788
|
+
return <i64>(
|
|
789
|
+
(this.lo & 0x7FFFFFFFFFFFFFFF) |
|
|
790
|
+
(this.hi & 0x8000000000000000)
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Convert to 64-bit unsigned integer
|
|
796
|
+
* @returns 64-bit unsigned integer
|
|
797
|
+
*/
|
|
798
|
+
@inline
|
|
799
|
+
toU64(): u64 {
|
|
800
|
+
return this.lo;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* Convert to 32-bit signed integer
|
|
805
|
+
* @returns 32-bit signed integer
|
|
806
|
+
*/
|
|
807
|
+
@inline
|
|
808
|
+
toI32(): i32 {
|
|
809
|
+
return <i32>this.toI64();
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Convert to 32-bit unsigned integer
|
|
814
|
+
* @returns 32-bit unsigned integer
|
|
815
|
+
*/
|
|
816
|
+
@inline
|
|
817
|
+
toU32(): u32 {
|
|
818
|
+
return <u32>this.lo;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Convert to 1-bit boolean
|
|
823
|
+
* @returns 1-bit boolean
|
|
824
|
+
*/
|
|
825
|
+
@inline
|
|
826
|
+
toBool(): bool {
|
|
827
|
+
return (this.lo | this.hi) != 0;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
* Convert to 64-bit float number in deteministic way
|
|
832
|
+
* @returns 64-bit float
|
|
833
|
+
*/
|
|
834
|
+
@inline
|
|
835
|
+
toF64(): f64 {
|
|
836
|
+
return __floatuntidf(this.lo, this.hi);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* Convert to 32-bit float number
|
|
841
|
+
* @returns 32-bit float
|
|
842
|
+
*/
|
|
843
|
+
@inline
|
|
844
|
+
toF32(): f32 {
|
|
845
|
+
return <f32>this.toF64();
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Convert to generic type `T`. Useful inside other generics methods
|
|
850
|
+
* @param T is <bool | i8 | u8 | i16 | u16 | i32 | u32 | i64 | u64 | f32 | f64 | i128 | u128 | u256 | u8[] | Uint8Array | `StaticArray<u8>` | string>
|
|
851
|
+
* @returns type of `T`
|
|
852
|
+
*/
|
|
853
|
+
@inline
|
|
854
|
+
as<T>(): T {
|
|
855
|
+
if (isBoolean<T>()) {
|
|
856
|
+
return <T>this.toBool();
|
|
857
|
+
} else if (isInteger<T>()) {
|
|
858
|
+
if (isSigned<T>()) {
|
|
859
|
+
// i8, i16, i32, i64
|
|
860
|
+
return <T>this.toI64();
|
|
861
|
+
} else {
|
|
862
|
+
// u8, u16, u32, u64
|
|
863
|
+
return <T>this.toU64();
|
|
864
|
+
}
|
|
865
|
+
} else if (isFloat<T>()) {
|
|
866
|
+
// f32, f64
|
|
867
|
+
return <T>this.toF64();
|
|
868
|
+
} else if (isString<T>()) {
|
|
869
|
+
return <T>this.toString();
|
|
870
|
+
} else if (isReference<T>()) {
|
|
871
|
+
let dummy = changetype<T>(0);
|
|
872
|
+
if (dummy instanceof u8[]) return <T>this.toBytes();
|
|
873
|
+
else if (dummy instanceof StaticArray<u8>) return <T>this.toStaticBytes();
|
|
874
|
+
else if (dummy instanceof Uint8Array) return <T>this.toUint8Array();
|
|
875
|
+
else if (dummy instanceof i128) return <T>this.toI128();
|
|
876
|
+
else if (dummy instanceof u128) return <T>this;
|
|
877
|
+
else if (dummy instanceof u256) return <T>this.toU256();
|
|
878
|
+
else throw new TypeError('Unsupported generic type');
|
|
879
|
+
} else throw new TypeError('Unsupported generic type');
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Convert to byte array
|
|
884
|
+
* @param bigEndian Little or Big Endian? Default: false
|
|
885
|
+
* @returns Array of bytes
|
|
886
|
+
*/
|
|
887
|
+
@inline
|
|
888
|
+
toBytes(bigEndian: bool = false): u8[] {
|
|
889
|
+
var result = new Array<u8>(16);
|
|
890
|
+
this.toArrayBuffer(result.dataStart, bigEndian);
|
|
891
|
+
return result;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* Convert to byte static array
|
|
896
|
+
* @param bigEndian Little or Big Endian? Default: false
|
|
897
|
+
* @returns StaticArray of bytes
|
|
898
|
+
*/
|
|
899
|
+
@inline
|
|
900
|
+
toStaticBytes(bigEndian: bool = false): StaticArray<u8> {
|
|
901
|
+
var result = new StaticArray<u8>(16);
|
|
902
|
+
this.toArrayBuffer(changetype<usize>(result), bigEndian);
|
|
903
|
+
return result;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Convert to Uint8Array
|
|
908
|
+
* @param bigEndian Little or Big Endian? Default: false
|
|
909
|
+
* @returns Uint8Array
|
|
910
|
+
*/
|
|
911
|
+
@inline
|
|
912
|
+
toUint8Array(bigEndian: bool = false): Uint8Array {
|
|
913
|
+
var result = new Uint8Array(16);
|
|
914
|
+
this.toArrayBuffer(result.dataStart, bigEndian);
|
|
915
|
+
return result;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Return copy of current 128-bit value
|
|
920
|
+
* @returns 128-bit unsigned integer
|
|
921
|
+
*/
|
|
922
|
+
clone(): u128 {
|
|
923
|
+
return new u128(this.lo, this.hi);
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
toString(radix: i32 = 10): string {
|
|
927
|
+
assert(radix == 10 || radix == 16, 'radix argument must be between 10 or 16');
|
|
928
|
+
if (this.isZero()) return '0';
|
|
929
|
+
|
|
930
|
+
var result = '';
|
|
931
|
+
if (radix == 16) {
|
|
932
|
+
let shift: i32 = 124 - (u128.clz(this) & ~3);
|
|
933
|
+
while (shift >= 0) {
|
|
934
|
+
// @ts-ignore
|
|
935
|
+
result += HEX_CHARS.charAt(<i32>((this >> shift).lo & 15));
|
|
936
|
+
shift -= 4;
|
|
937
|
+
}
|
|
938
|
+
return result;
|
|
939
|
+
}
|
|
940
|
+
return u128toDecimalString(this);
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
@inline
|
|
944
|
+
private toArrayBufferLE(buffer: usize): void {
|
|
945
|
+
store<u64>(buffer, this.lo, 0 * sizeof<u64>());
|
|
946
|
+
store<u64>(buffer, this.hi, 1 * sizeof<u64>());
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
@inline
|
|
950
|
+
private toArrayBufferBE(buffer: usize): void {
|
|
951
|
+
store<u64>(buffer, bswap(this.hi), 0 * sizeof<u64>());
|
|
952
|
+
store<u64>(buffer, bswap(this.lo), 1 * sizeof<u64>());
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
@inline
|
|
956
|
+
private toArrayBuffer(buffer: usize, bigEndian: bool = false): void {
|
|
957
|
+
if (bigEndian) {
|
|
958
|
+
this.toArrayBufferBE(buffer);
|
|
959
|
+
} else {
|
|
960
|
+
this.toArrayBufferLE(buffer);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|