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.
@@ -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
+ }