Line data Source code
1 1 : const Int128Min = -170141183460469231731687303715884105728n;
2 1 : const Int128Max = 170141183460469231731687303715884105727n;
3 1 : const UInt128Max = 340282366920938463463374607431768211455n;
4 :
5 1 : export class Int128 {
6 1 : static encodeLE(v: bigint) {
7 1 : if (v < Int128Min || v > Int128Max) throw Error("Input has to be between -(2^127) and (2^127)-1");
8 :
9 1 : const biguint = BigInt.asUintN(128, v);
10 1 : const buf = new ArrayBuffer(16);
11 1 : const bufView = new DataView(buf, 0, 16);
12 1 : bufView.setBigUint64(0, biguint & 0xffffffffffffffffn, true);
13 1 : bufView.setBigUint64(8, biguint >> 64n, true);
14 1 : return new Uint32Array(buf);
15 1 : }
16 :
17 1 : static decodeLE(buf: Uint32Array, offset = 0) {
18 1 : if (buf.byteLength < (offset + 16)) throw Error("Buffer out of range.");
19 :
20 1 : const bufView = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
21 1 : let biguint = bufView.getBigUint64(offset, true);
22 1 : biguint |= bufView.getBigUint64(offset + 8, true) << 64n;
23 1 : return BigInt.asIntN(128, biguint);
24 1 : }
25 1 : }
26 :
27 1 : export class UInt128 {
28 1 : static encodeLE(v: bigint) {
29 1 : if (v < 0n || v > UInt128Max) throw Error("Input has to be between 0 and (2^128)-1");
30 :
31 1 : const buf = new ArrayBuffer(16);
32 1 : const bufView = new DataView(buf, 0, 16);
33 1 : bufView.setBigUint64(0, v & 0xffffffffffffffffn, true);
34 1 : bufView.setBigUint64(8, v >> 64n, true);
35 1 : return new Uint32Array(buf);
36 1 : }
37 :
38 1 : static decodeLE(buf: Uint32Array, offset = 0) {
39 1 : if (buf.byteLength < (offset + 16)) throw Error("Buffer out of range.");
40 :
41 1 : const bufView = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
42 1 : let biguint = bufView.getBigUint64(offset, true);
43 1 : biguint |= bufView.getBigUint64(offset + 8, true) << 64n;
44 1 : return biguint;
45 1 : }
46 1 : }
47 :
48 1 : export class Decimal128 {
49 1 : static format(num: bigint, scale: number) {
50 : // Get int part
51 1 : const factor = BigInt(Math.pow(10, scale));
52 1 : const intPart = num / factor;
53 : // Get fraction part
54 1 : let fractionPart = num - (intPart * factor);
55 1 : if (fractionPart < 0n) fractionPart = ~fractionPart;
56 1 : const fractionStr = fractionPart.toString();
57 :
58 : // Cut trailing zeros
59 1 : let end = fractionStr.length;
60 1 : for (; end > 0 && fractionStr.charCodeAt(end - 1) == 0x30; --end);
61 :
62 : // Render with or without decimal dot
63 1 : if (end == 0) {
64 1 : return `${intPart.toString()}`;
65 : } else {
66 1 : return `${intPart.toString()}.${fractionStr.substring(0, end)}`;
67 : }
68 1 : }
69 1 : }
|