@btc-vision/btc-runtime 1.3.7 → 1.3.9

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,779 @@
1
+ import { i128, u128 } from 'as-bignum/assembly';
2
+ import { __carry, __uadd64, __umulh64 } from 'as-bignum/assembly/globals';
3
+
4
+ @lazy const HEX_CHARS = '0123456789abcdef';
5
+
6
+
7
+ /**
8
+ * Multiplies two 160-bit unsigned integers and returns the lower 160 bits.
9
+ * @param a_lo1 Lower 64 bits of the first operand.
10
+ * @param a_lo2 Middle 64 bits of the first operand.
11
+ * @param a_hi Upper 32 bits of the first operand.
12
+ * @param b_lo1 Lower 64 bits of the second operand.
13
+ * @param b_lo2 Middle 64 bits of the second operand.
14
+ * @param b_hi Upper 32 bits of the second operand.
15
+ * @returns The lower 160 bits of the product as a u160 instance.
16
+ */
17
+ @global
18
+ export function __mul160(
19
+ a_lo1: u64,
20
+ a_lo2: u64,
21
+ a_hi: u32,
22
+ b_lo1: u64,
23
+ b_lo2: u64,
24
+ b_hi: u32
25
+ ): u160 {
26
+ // Step 1: Multiply lower parts
27
+ let c0 = a_lo1 * b_lo1;
28
+ let c0_hi = __umulh64(a_lo1, b_lo1);
29
+
30
+ // Step 2: Multiply cross terms
31
+ let c1 = a_lo1 * b_lo2;
32
+ let c2 = a_lo2 * b_lo1;
33
+
34
+ // Step 3: Add cross terms and carry
35
+ let lo2 = __uadd64(c1, c2);
36
+ let carry1 = __carry;
37
+
38
+ lo2 = __uadd64(lo2, c0_hi);
39
+ let carry2 = __carry;
40
+
41
+ // Step 4: Multiply high parts
42
+ let c3 = a_lo1 * <u64>b_hi;
43
+ let c4 = <u64>a_hi * b_lo1;
44
+
45
+ // Step 5: Add high parts and carry
46
+ let hi = <u32>(c3 + c4 + carry1 + carry2);
47
+
48
+ return new u160(c0, lo2, hi);
49
+ }
50
+
51
+ /**
52
+ * Performs division and modulus on two 160-bit unsigned integers.
53
+ * @param dividend The dividend as a u160 instance.
54
+ * @param divisor The divisor as a u160 instance.
55
+ * @returns An object containing the quotient and remainder as u160 instances.
56
+ */
57
+ @global
58
+ export function __udivmod160(dividend: u160, divisor: u160): { quotient: u160, remainder: u160 } {
59
+ if (divisor.isZero()) {
60
+ throw new RangeError("Division by zero");
61
+ }
62
+
63
+ if (dividend.lt(divisor)) {
64
+ return { quotient: u160.Zero, remainder: dividend };
65
+ }
66
+
67
+ if (divisor.isZero()) {
68
+ throw new RangeError("Division by zero");
69
+ }
70
+
71
+ let quotient = u160.Zero;
72
+ let remainder = u160.Zero;
73
+ let temp = dividend.clone();
74
+
75
+ // Determine the number of bits in dividend and divisor
76
+ let dividend_bits = 160 - __clz160(temp.lo1, temp.lo2, temp.hi);
77
+ let divisor_bits = 160 - __clz160(divisor.lo1, divisor.lo2, divisor.hi);
78
+
79
+ let shift = dividend_bits - divisor_bits;
80
+
81
+ // Align divisor with dividend
82
+ let shifted_divisor = divisor << shift;
83
+
84
+ for (let i = shift; i >= 0; i--) {
85
+ if (temp >= shifted_divisor) {
86
+ temp = temp - shifted_divisor;
87
+ quotient = quotient | (u160.One << i);
88
+ }
89
+ shifted_divisor = shifted_divisor >> 1;
90
+ }
91
+
92
+ remainder = temp;
93
+
94
+ return { quotient, remainder };
95
+ }
96
+
97
+ /**
98
+ * Counts the leading zeros in a 160-bit unsigned integer.
99
+ * @param lo1 Lower 64 bits.
100
+ * @param lo2 Middle 64 bits.
101
+ * @param hi Upper 32 bits.
102
+ * @returns The number of leading zeros.
103
+ */
104
+ @inline
105
+ export function __clz160(lo1: u64, lo2: u64, hi: u32): i32 {
106
+ if (hi != 0) {
107
+ return clz(<u64>hi) - 32;
108
+ } else if (lo2 != 0) {
109
+ return 32 + clz(lo2);
110
+ } else {
111
+ return 96 + clz(lo1);
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Counts the trailing zeros in a 160-bit unsigned integer.
117
+ * @param lo1 Lower 64 bits.
118
+ * @param lo2 Middle 64 bits.
119
+ * @param hi Upper 32 bits.
120
+ * @returns The number of trailing zeros.
121
+ */
122
+ @inline
123
+ export function __ctz160(lo1: u64, lo2: u64, hi: u32): i32 {
124
+ if (lo1 != 0) {
125
+ return ctz(lo1);
126
+ } else if (lo2 != 0) {
127
+ return 64 + ctz(lo2);
128
+ } else {
129
+ return 128 + ctz(<u32>hi);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Converts a 160-bit unsigned integer to its decimal string representation.
135
+ * @param value The u160 instance to convert.
136
+ * @returns The decimal string representation of the u160 instance.
137
+ */
138
+ @inline
139
+ export function u160toDecimalString(value: u160): string {
140
+ if (value.isZero()) return "0";
141
+
142
+ let result = "";
143
+ let temp = value.clone();
144
+
145
+ while (!temp.isZero()) {
146
+ let { quotient, remainder } = __udivmod160(temp, u160.fromU64(10));
147
+ let digit = <u8>remainder.lo1; // Assuming remainder < 10
148
+ result = digit.toString() + result;
149
+ temp = quotient;
150
+ }
151
+
152
+ return result;
153
+ }
154
+
155
+ export class u160 {
156
+
157
+ @inline static get Zero(): u160 { return new u160(); }
158
+ @inline static get One(): u160 { return new u160(1, 0, 0); }
159
+ @inline static get Min(): u160 { return new u160(); }
160
+ @inline static get Max(): u160 { return new u160(<u64>0xFFFFFFFFFFFFFFFF, <u64>0xFFFFFFFFFFFFFFFF, <u32>0xFFFFFFFF); }
161
+
162
+ // TODO: fromString
163
+
164
+ @inline
165
+ static fromU160(value: u160): u160 {
166
+ return new u160(value.lo1, value.lo2, value.hi);
167
+ }
168
+
169
+ @inline
170
+ static fromU128(value: u128): u160 {
171
+ return new u160(value.lo, value.hi, 0);
172
+ }
173
+
174
+ @inline
175
+ static fromU64(value: u64): u160 {
176
+ return new u160(value, 0, 0);
177
+ }
178
+
179
+ @inline
180
+ static fromI64(value: i64): u160 {
181
+ let mask = <u64>(value >> 63);
182
+ return new u160(<u64>value, mask, <u32>mask);
183
+ }
184
+
185
+ @inline
186
+ static fromU32(value: u32): u160 {
187
+ return new u160(<u64>value, 0, 0);
188
+ }
189
+
190
+ @inline
191
+ static fromI32(value: i32): u160 {
192
+ let mask = <u64>(value >> 31);
193
+ return new u160(<u64>value, mask, <u32>mask);
194
+ }
195
+
196
+ @inline
197
+ static fromBits(
198
+ lo1: u64, lo2: u64, hi: u32
199
+ ): u160 {
200
+ return new u160(lo1, lo2, hi);
201
+ }
202
+
203
+ @inline
204
+ static fromBytes<T>(array: T, bigEndian: bool = false): u160 {
205
+ if (array instanceof u8[]) {
206
+ return bigEndian
207
+ ? u160.fromBytesBE(<u8[]>array)
208
+ : u160.fromBytesLE(<u8[]>array);
209
+ } else if (array instanceof Uint8Array) {
210
+ return bigEndian
211
+ ? u160.fromUint8ArrayBE(<Uint8Array>array)
212
+ : u160.fromUint8ArrayLE(<Uint8Array>array);
213
+ } else {
214
+ throw new TypeError("Unsupported generic type");
215
+ }
216
+ }
217
+
218
+ @inline
219
+ static fromBytesLE(array: u8[]): u160 {
220
+ assert(array.length == 20, "Invalid byte array length for u160");
221
+ let lo1 = load<u64>(changetype<usize>(array) + 0);
222
+ let lo2 = load<u64>(changetype<usize>(array) + 8);
223
+ let hi = load<u32>(changetype<usize>(array) + 16);
224
+ return new u160(lo1, lo2, hi);
225
+ }
226
+
227
+ @inline
228
+ static fromBytesBE(array: u8[]): u160 {
229
+ assert(array.length == 20, "Invalid byte array length for u160");
230
+ let lo1 = bswap(load<u64>(changetype<usize>(array) + 12));
231
+ let lo2 = bswap(load<u64>(changetype<usize>(array) + 4));
232
+ let hi = bswap(load<u32>(changetype<usize>(array) + 0));
233
+ return new u160(lo1, lo2, hi);
234
+ }
235
+
236
+ @inline
237
+ static fromUint8ArrayLE(array: Uint8Array): u160 {
238
+ assert(array.length == 20, "Invalid Uint8Array length for u160");
239
+ let lo1 = load<u64>(array.dataStart + 0);
240
+ let lo2 = load<u64>(array.dataStart + 8);
241
+ let hi = load<u32>(array.dataStart + 16);
242
+ return new u160(lo1, lo2, hi);
243
+ }
244
+
245
+ @inline
246
+ static fromUint8ArrayBE(array: Uint8Array): u160 {
247
+ assert(array.length == 20, "Invalid Uint8Array length for u160");
248
+ let lo1 = bswap(load<u64>(array.dataStart + 12));
249
+ let lo2 = bswap(load<u64>(array.dataStart + 4));
250
+ let hi = bswap(load<u32>(array.dataStart + 0));
251
+ return new u160(lo1, lo2, hi);
252
+ }
253
+
254
+ @operator('<<')
255
+ static shl(a: u160, shift: u32): u160 {
256
+ shift &= 159;
257
+ if (shift == 0) return a;
258
+
259
+ let lo1 = a.lo1;
260
+ let lo2 = a.lo2;
261
+ let hi = a.hi;
262
+
263
+ if (shift < 64) {
264
+ lo2 = (lo2 << shift) | (lo1 >> (64 - shift));
265
+ hi = (hi << shift) | (<u32>(lo2 >> (64 - shift)));
266
+ lo1 = lo1 << shift;
267
+ } else if (shift < 128) {
268
+ lo1 = 0;
269
+ lo2 = a.lo1 << (shift - 64);
270
+ hi = (a.lo2 << (shift - 64)) | (<u32>(a.hi << (shift - 64)));
271
+ } else {
272
+ lo1 = 0;
273
+ lo2 = 0;
274
+ hi = a.lo1 << (shift - 128);
275
+ }
276
+
277
+ return new u160(lo1, lo2, hi);
278
+ }
279
+
280
+ // TODO: Improve conversion from floating points
281
+ @inline
282
+ static fromF64(value: f64): u160 {
283
+ let mask = <u64>(reinterpret<i64>(value) >> 63);
284
+ return new u160(<u64>value, mask, <u32>mask);
285
+ }
286
+
287
+ @inline
288
+ static fromF32(value: f32): u160 {
289
+ let mask = <u64>(reinterpret<i32>(value) >> 31);
290
+ return new u160(<u64>value, mask, <u32>mask);
291
+ }
292
+
293
+ /**
294
+ * Create 160-bit unsigned integer from generic type T
295
+ * @param value
296
+ * @returns 160-bit unsigned integer
297
+ */
298
+ @inline
299
+ static from<T>(value: T): u160 {
300
+ if (value instanceof bool) return u160.fromU64(<u64>value);
301
+ else if (value instanceof i8) return u160.fromI64(<i64>value);
302
+ else if (value instanceof u8) return u160.fromU64(<u64>value);
303
+ else if (value instanceof i16) return u160.fromI64(<i64>value);
304
+ else if (value instanceof u16) return u160.fromU64(<u64>value);
305
+ else if (value instanceof i32) return u160.fromI32(<i32>value);
306
+ else if (value instanceof u32) return u160.fromU32(<u32>value);
307
+ else if (value instanceof i64) return u160.fromI64(<i64>value);
308
+ else if (value instanceof u64) return u160.fromU64(<u64>value);
309
+ else if (value instanceof f32) return u160.fromF32(<f32>value);
310
+ else if (value instanceof f64) return u160.fromF64(<f64>value);
311
+ else if (value instanceof u128) return u160.fromU128(<u128>value);
312
+ else if (value instanceof u160) return u160.fromU160(<u160>value);
313
+ else if (value instanceof u8[]) return u160.fromBytes(<u8[]>value);
314
+ else if (value instanceof Uint8Array) return u160.fromBytes(<Uint8Array>value);
315
+ else throw new TypeError("Unsupported generic type");
316
+ }
317
+
318
+ // TODO
319
+ // static fromString(str: string): u160
320
+
321
+ constructor(
322
+ public lo1: u64 = 0,
323
+ public lo2: u64 = 0,
324
+ public hi: u32 = 0,
325
+ ) {}
326
+
327
+ @inline
328
+ set(value: u160): this {
329
+ this.lo1 = value.lo1;
330
+ this.lo2 = value.lo2;
331
+ this.hi = value.hi;
332
+ return this;
333
+ }
334
+
335
+ @inline
336
+ setU128(value: u128): this {
337
+ this.lo1 = value.lo;
338
+ this.lo2 = value.hi;
339
+ this.hi = 0;
340
+ return this;
341
+ }
342
+
343
+ @inline
344
+ setI64(value: i64): this {
345
+ let mask: u64 = <u64>(value >> 63);
346
+ this.lo1 = <u64>value;
347
+ this.lo2 = mask;
348
+ this.hi = <u32>mask;
349
+ return this;
350
+ }
351
+
352
+ @inline
353
+ setU64(value: u64): this {
354
+ this.lo1 = value;
355
+ this.lo2 = 0;
356
+ this.hi = 0;
357
+ return this;
358
+ }
359
+
360
+ @inline
361
+ setI32(value: i32): this {
362
+ let mask: u64 = <u64>(value >> 31);
363
+ this.lo1 = <u64>value;
364
+ this.lo2 = mask;
365
+ this.hi = <u32>mask;
366
+ return this;
367
+ }
368
+
369
+ @inline
370
+ setU32(value: u32): this {
371
+ this.lo1 = <u64>value;
372
+ this.lo2 = 0;
373
+ this.hi = 0;
374
+ return this;
375
+ }
376
+
377
+ @inline
378
+ isZero(): bool {
379
+ return !(this.lo1 | this.lo2 | this.hi);
380
+ }
381
+
382
+ @inline @operator.prefix('!')
383
+ static isEmpty(value: u160): bool {
384
+ return value.isZero();
385
+ }
386
+
387
+ @inline @operator.prefix('~')
388
+ not(): u160 {
389
+ return new u160(~this.lo1, ~this.lo2, ~this.hi);
390
+ }
391
+
392
+ @inline @operator.prefix('+')
393
+ pos(): u160 {
394
+ return this;
395
+ }
396
+
397
+ @operator.prefix('-')
398
+ neg(): u160 {
399
+ let lo1 = ~this.lo1;
400
+ let lo2 = ~this.lo2;
401
+ let hi = ~this.hi;
402
+
403
+ let lo1p = lo1 + 1;
404
+ let carry1 = lo1p < lo1 ? 1 : 0;
405
+
406
+ let lo2p = this.lo2 == 0xFFFFFFFFFFFFFFFF ? 0 : this.lo2 + carry1;
407
+ let carry2 = (lo2p < this.lo2) ? 1 : 0;
408
+
409
+ let hi_p = this.hi + carry2;
410
+
411
+ return new u160(lo1p, lo2p, hi_p);
412
+ }
413
+
414
+ @operator.prefix('++')
415
+ preInc(): this {
416
+ let lo1p = this.lo1 + 1;
417
+ let carry1 = lo1p < this.lo1 ? 1 : 0;
418
+
419
+ let lo2p = this.lo2 + carry1;
420
+ let carry2 = lo2p < this.lo2 ? 1 : 0;
421
+
422
+ let hi_p = this.hi + <u32>carry2;
423
+
424
+ this.lo1 = lo1p;
425
+ this.lo2 = lo2p;
426
+ this.hi = hi_p;
427
+
428
+ return this;
429
+ }
430
+
431
+ @operator.prefix('--')
432
+ preDec(): this {
433
+ let lo1p = this.lo1 - 1;
434
+ let borrow1 = this.lo1 == 0 ? 1 : 0;
435
+
436
+ let lo2p = this.lo2 - <u64>borrow1;
437
+ let borrow2 = this.lo2 < <u64>borrow1 ? 1 : 0;
438
+
439
+ let hi_p = this.hi - <u32>borrow2;
440
+
441
+ this.lo1 = lo1p;
442
+ this.lo2 = lo2p;
443
+ this.hi = hi_p;
444
+
445
+ return this;
446
+ }
447
+
448
+ @inline @operator.postfix('++')
449
+ postInc(): u160 {
450
+ let original = this.clone();
451
+ this.preInc();
452
+ return original;
453
+ }
454
+
455
+ @inline @operator.postfix('--')
456
+ postDec(): u160 {
457
+ let original = this.clone();
458
+ this.preDec();
459
+ return original;
460
+ }
461
+
462
+ @operator('+')
463
+ static add(a: u160, b: u160): u160 {
464
+ let lo1 = a.lo1 + b.lo1;
465
+ let carry1 = lo1 < a.lo1 ? 1 : 0;
466
+
467
+ let lo2 = a.lo2 + b.lo2 + <u64>carry1;
468
+ let carry2 = lo2 < a.lo2 || (carry1 == 1 && lo2 == a.lo2) ? 1 : 0;
469
+
470
+ let hi = a.hi + b.hi + <u32>carry2;
471
+ return new u160(lo1, lo2, hi);
472
+ }
473
+
474
+ @operator('-')
475
+ static sub(a: u160, b: u160): u160 {
476
+ let lo1 = a.lo1 - b.lo1;
477
+ let borrow1 = a.lo1 < b.lo1 ? 1 : 0;
478
+
479
+ let lo2 = a.lo2 - b.lo2 - <u64>borrow1;
480
+ let borrow2 = a.lo2 < b.lo2 + <u64>borrow1 ? 1 : 0;
481
+
482
+ let hi = a.hi - b.hi - <u32>borrow2;
483
+ return new u160(lo1, lo2, hi);
484
+ }
485
+
486
+ @inline @operator('|')
487
+ static or(a: u160, b: u160): u160 {
488
+ return new u160(a.lo1 | b.lo1, a.lo2 | b.lo2, a.hi | b.hi);
489
+ }
490
+
491
+ @inline @operator('^')
492
+ static xor(a: u160, b: u160): u160 {
493
+ return new u160(a.lo1 ^ b.lo1, a.lo2 ^ b.lo2, a.hi ^ b.hi);
494
+ }
495
+
496
+ @inline @operator('&')
497
+ static and(a: u160, b: u160): u160 {
498
+ return new u160(a.lo1 & b.lo1, a.lo2 & b.lo2, a.hi & b.hi);
499
+ }
500
+
501
+ @operator('>>')
502
+ static shr(value: u160, shift: i32): u160 {
503
+ shift &= 159;
504
+ if (shift == 0) return value;
505
+
506
+ let off = <u64>shift;
507
+ if (shift < 64) {
508
+ let lo1 = value.lo1 >> off;
509
+ let lo2 = (value.lo2 >> off) | (value.lo1 << (64 - off));
510
+ let hi = (value.hi >> off) | (<u32>((value.lo2 << (32 - off)) & 0xFFFFFFFF)) as u32;
511
+ return new u160(lo1, lo2, hi);
512
+ } else if (shift < 128) {
513
+ let lo1 = 0;
514
+ let lo2 = value.lo1 >> (shift - 64);
515
+ let hi = (value.lo2 >> (shift - 64)) | (<u32>(value.hi << (64 - (shift - 64))) & 0xFFFFFFFF);
516
+ return new u160(lo1, lo2, hi);
517
+ } else {
518
+ let lo1 = 0;
519
+ let lo2 = 0;
520
+ let hi = value.lo1 >> (shift - 128);
521
+ return new u160(lo1, lo2, hi as u32);
522
+ }
523
+ }
524
+
525
+ @inline @operator('>>>')
526
+ static shr_u(value: u160, shift: i32): u160 {
527
+ return u160.shr(value, shift);
528
+ }
529
+
530
+ @inline @operator('==')
531
+ static eq(a: u160, b: u160): bool {
532
+ return (
533
+ a.lo1 == b.lo1 &&
534
+ a.lo2 == b.lo2 &&
535
+ a.hi == b.hi
536
+ );
537
+ }
538
+
539
+ @inline @operator('!=')
540
+ static ne(a: u160, b: u160): bool {
541
+ return !u160.eq(a, b);
542
+ }
543
+
544
+ @operator('<')
545
+ static lt(a: u160, b: u160): bool {
546
+ if (a.hi == b.hi) {
547
+ if (a.lo2 == b.lo2) {
548
+ return a.lo1 < b.lo1;
549
+ }
550
+ return a.lo2 < b.lo2;
551
+ }
552
+ return a.hi < b.hi;
553
+ }
554
+
555
+ @inline @operator('>')
556
+ static gt(a: u160, b: u160): bool {
557
+ return u160.lt(b, a);
558
+ }
559
+
560
+ @inline @operator('<=')
561
+ static le(a: u160, b: u160): bool {
562
+ return !u160.gt(a, b);
563
+ }
564
+
565
+ @inline @operator('>=')
566
+ static ge(a: u160, b: u160): bool {
567
+ return !u160.lt(a, b);
568
+ }
569
+
570
+ // mul: u160 x u160 = u160
571
+ @inline @operator('*')
572
+ static mul(a: u160, b: u160): u160 {
573
+ return __mul160(a.lo1, a.lo2, a.hi, b.lo1, b.lo2, b.hi);
574
+ }
575
+
576
+ @inline
577
+ static popcnt(value: u160): i32 {
578
+ let count = popcnt(value.lo1) + popcnt(value.lo2) + popcnt(value.hi);
579
+ return <i32>count;
580
+ }
581
+
582
+ @inline
583
+ static clz(value: u160): i32 {
584
+ if (value.hi) return <i32>(clz(value.hi) + 0);
585
+ if (value.lo2) return <i32>(clz(value.lo2) + 32);
586
+ if (value.lo1) return <i32>(clz(value.lo1) + 96);
587
+ return <i32>(clz(0) + 160); // All bits are zero
588
+ }
589
+
590
+ @inline
591
+ static ctz(value: u160): i32 {
592
+ if (value.lo1) return <i32>(ctz(value.lo1) + 0);
593
+ if (value.lo2) return <i32>(ctz(value.lo2) + 64);
594
+ if (value.hi) return <i32>(ctz(value.hi) + 128);
595
+ return <i32>(ctz(0) + 160); // All bits are zero
596
+ }
597
+
598
+ /**
599
+ * Convert to 128-bit signed integer
600
+ * @return 160-bit signed integer
601
+ */
602
+ @inline
603
+ toI128(): i128 {
604
+ return new i128(
605
+ this.lo1,
606
+ this.lo2,
607
+ );
608
+ }
609
+
610
+ /**
611
+ * Convert to 128-bit unsigned integer
612
+ * @return 128-bit unsigned integer
613
+ */
614
+ @inline
615
+ toU128(): u128 {
616
+ return new u128(this.lo1, this.lo2);
617
+ }
618
+
619
+ /**
620
+ * Convert to 160-bit unsigned integer
621
+ * @returns 160-bit unsigned integer
622
+ */
623
+ @inline
624
+ toU160(): this {
625
+ return this;
626
+ }
627
+
628
+ /**
629
+ * Convert to 64-bit signed integer
630
+ * @return 64-bit signed integer
631
+ */
632
+ @inline
633
+ toI64(): i64 {
634
+ return <i64>(this.lo1 | (<u64>this.hi << 64));
635
+ }
636
+
637
+ /**
638
+ * Convert to 64-bit unsigned integer
639
+ * @return 64-bit unsigned integer
640
+ */
641
+ @inline
642
+ toU64(): u64 {
643
+ return this.lo1;
644
+ }
645
+
646
+ /**
647
+ * Convert to 32-bit signed integer
648
+ * @return 32-bit signed integer
649
+ */
650
+ @inline
651
+ toI32(): i32 {
652
+ return <i32>this.lo1;
653
+ }
654
+
655
+ /**
656
+ * Convert to 32-bit unsigned integer
657
+ * @return 32-bit unsigned integer
658
+ */
659
+ @inline
660
+ toU32(): u32 {
661
+ return this.hi;
662
+ }
663
+
664
+ /**
665
+ * Convert to 1-bit boolean
666
+ * @return 1-bit boolean
667
+ */
668
+ @inline
669
+ toBool(): bool {
670
+ return <bool>(this.lo1 | this.lo2 | this.hi);
671
+ }
672
+
673
+ @inline
674
+ private toArrayBufferLE(buffer: usize): void {
675
+ store<u64>(buffer, this.lo1, 0 * sizeof<u64>());
676
+ store<u64>(buffer, this.lo2, 1 * sizeof<u64>());
677
+ store<u32>(buffer, this.hi, 2 * sizeof<u64>());
678
+ }
679
+
680
+ @inline
681
+ private toArrayBufferBE(buffer: usize): void {
682
+ store<u32>(buffer, bswap(this.hi), 0 * sizeof<u64>());
683
+ store<u64>(buffer, bswap(this.lo2), 1 * sizeof<u64>());
684
+ store<u64>(buffer, bswap(this.lo1), 3 * sizeof<u64>());
685
+ }
686
+
687
+ @inline
688
+ private toArrayBuffer(buffer: usize, bigEndian: bool = false): void {
689
+ if (bigEndian) {
690
+ this.toArrayBufferBE(buffer);
691
+ } else {
692
+ this.toArrayBufferLE(buffer);
693
+ }
694
+ }
695
+
696
+ /**
697
+ * Convert to generic type `T`. Useful inside other generics methods
698
+ * @param T is <bool | i8 | u8 | i16 | u16 | i32 | u32 | i64 | u64 | f32 | f64 | i128 | u128 | u160 | u8[] | Uint8Array | `StaticArray<u8>` | string>
699
+ * @returns type of `T`
700
+ */
701
+ @inline
702
+ as<T>(): T {
703
+ let dummy!: T;
704
+ if (dummy instanceof bool) return <T>this.toBool();
705
+ else if (dummy instanceof i8) return <T>this.toI64();
706
+ else if (dummy instanceof u8) return <T>this.toU64();
707
+ else if (dummy instanceof i16) return <T>this.toI64();
708
+ else if (dummy instanceof u16) return <T>this.toU64();
709
+ else if (dummy instanceof i32) return <T>this.toI32();
710
+ else if (dummy instanceof u32) return <T>this.toU32();
711
+ else if (dummy instanceof i64) return <T>this.toI64();
712
+ else if (dummy instanceof u64) return <T>this.toU64();
713
+ else if (dummy instanceof i128) return <T>this.toI128();
714
+ else if (dummy instanceof u128) return <T>this.toU128();
715
+ else if (dummy instanceof u160) return <T>this.toU160();
716
+ else if (dummy instanceof u8[]) return <T>this.toBytes();
717
+ else if (dummy instanceof Uint8Array) return <T>this.toUint8Array();
718
+ else if (dummy instanceof StaticArray<u8>) return <T>this.toStaticBytes();
719
+ else if (dummy instanceof String) return <T>this.toString();
720
+ else throw new TypeError('Unsupported generic type');
721
+ }
722
+
723
+ /**
724
+ * Convert to byte array
725
+ * @param bigEndian Little or Big Endian? Default: false
726
+ * @returns Array of bytes
727
+ */
728
+ @inline
729
+ toBytes(bigEndian: bool = false): u8[] {
730
+ let result = new Array<u8>(20);
731
+ this.toArrayBuffer(result.dataStart, bigEndian);
732
+ return result;
733
+ }
734
+
735
+ /**
736
+ * Convert to byte static array
737
+ * @param bigEndian Little or Big Endian? Default: false
738
+ * @returns StaticArray of bytes
739
+ */
740
+ @inline
741
+ toStaticBytes(bigEndian: bool = false): StaticArray<u8> {
742
+ let result = new StaticArray<u8>(20);
743
+ this.toArrayBuffer(changetype<usize>(result), bigEndian);
744
+ return result;
745
+ }
746
+
747
+ /**
748
+ * Convert to Uint8Array
749
+ * @param bigEndian Little or Big Endian? Default: false
750
+ * @returns Uint8Array
751
+ */
752
+ @inline
753
+ toUint8Array(bigEndian: bool = false): Uint8Array {
754
+ let result = new Uint8Array(20);
755
+ this.toArrayBuffer(result.dataStart, bigEndian);
756
+ return result;
757
+ }
758
+
759
+ clone(): u160 {
760
+ return new u160(this.lo1, this.lo2, this.hi);
761
+ }
762
+
763
+ toString(radix: i32 = 10): string {
764
+ assert(radix == 10 || radix == 16, 'radix argument must be either 10 or 16');
765
+ if (this.isZero()) return '0';
766
+
767
+ let result = '';
768
+ if (radix == 16) {
769
+ let shift: i32 = 156 - (u160.clz(this) & ~3);
770
+ while (shift >= 0) {
771
+ let nibble = (<u32>((this >> shift).lo1) & 0xF);
772
+ result += HEX_CHARS.charAt(nibble);
773
+ shift -= 4;
774
+ }
775
+ return result;
776
+ }
777
+ return u160toDecimalString(this);
778
+ }
779
+ }