UNPKG

clvm

Version:

Javascript implementation of chia lisp

224 lines (220 loc) 8.01 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.limbs_for_int = exports.bigint_to_bytes = exports.pow = exports.int_to_bytes = exports.bigint_from_bytes = exports.int_from_bytes = void 0; const __type_compatibility__1 = require("./__type_compatibility__"); function int_from_bytes(b, option) { if (!b || b.length === 0) { return 0; } else if (b.length * 8 > 52) { throw new Error("Cannot convert Bytes to Integer larger than 52bit. Use bigint_from_bytes instead."); } const signed = (option && typeof option.signed === "boolean") ? option.signed : false; let unsigned32 = 0; const ui8array = b.raw(); const dv = new DataView(ui8array.buffer, ui8array.byteOffset, ui8array.byteLength); const bytes4Remain = dv.byteLength % 4; const bytes4Length = (dv.byteLength - bytes4Remain) / 4; let order = 1; for (let i = bytes4Length - 1; i >= 0; i--) { const byte32 = dv.getUint32(i * 4 + bytes4Remain); unsigned32 += byte32 * order; order = Number(BigInt(order) << BigInt(32)); } if (bytes4Remain > 0) { if (bytes4Length === 0) { order = 1; } for (let i = bytes4Remain - 1; i >= 0; i--) { const byte = ui8array[i]; unsigned32 += byte * order; order = Number(BigInt(order) << BigInt(8)); } } // If the first bit is 1, it is recognized as a negative number. if (signed && (ui8array[0] & 0x80)) { return unsigned32 - Number(BigInt(1) << BigInt(b.length * 8)); } return unsigned32; } exports.int_from_bytes = int_from_bytes; function bigint_from_bytes(b, option) { if (!b || b.length === 0) { return BigInt(0); } const signed = (option && typeof option.signed === "boolean") ? option.signed : false; let unsigned32 = BigInt(0); const ui8array = b.raw(); const dv = new DataView(ui8array.buffer, ui8array.byteOffset, ui8array.byteLength); const bytes4Remain = dv.byteLength % 4; const bytes4Length = (dv.byteLength - bytes4Remain) / 4; let order = BigInt(1); for (let i = bytes4Length - 1; i >= 0; i--) { const byte32 = dv.getUint32(i * 4 + bytes4Remain); unsigned32 += BigInt(byte32) * order; order <<= BigInt(32); } if (bytes4Remain > 0) { if (bytes4Length === 0) { order = BigInt(1); } for (let i = bytes4Remain - 1; i >= 0; i--) { const byte = ui8array[i]; unsigned32 += BigInt(byte) * order; order <<= BigInt(8); } } // If the first bit is 1, it is recognized as a negative number. if (signed && (ui8array[0] & 0x80)) { return unsigned32 - (BigInt(1) << BigInt(b.length * 8)); } return unsigned32; } exports.bigint_from_bytes = bigint_from_bytes; function int_to_bytes(v, option) { if (v > Number.MAX_SAFE_INTEGER || v < Number.MIN_SAFE_INTEGER) { throw new Error(`The int value is beyond ${v > 0 ? "MAX_SAFE_INTEGER" : "MIN_SAFE_INTEGER"}: ${v}`); } if (v === 0) { return __type_compatibility__1.Bytes.NULL; } const signed = (option && typeof option.signed === "boolean") ? option.signed : false; if (!signed && v < 0) { throw new Error("OverflowError: can't convert negative int to unsigned"); } let byte_count = 1; const div = signed ? 1 : 0; const b16 = 65536; if (v > 0) { let right_hand = (v + 1) * (div + 1); while ((b16 ** ((byte_count - 1) / 2 + 1)) < right_hand) { byte_count += 2; } right_hand = (v + 1) * (div + 1); while (2 ** (8 * byte_count) < right_hand) { byte_count++; } } else if (v < 0) { let right_hand = (-v + 1) * (div + 1); while ((b16 ** ((byte_count - 1) / 2 + 1)) < right_hand) { byte_count += 2; } right_hand = -v * 2; while (2 ** (8 * byte_count) < right_hand) { byte_count++; } } const extraByte = signed && v > 0 && ((v >> ((byte_count - 1) * 8)) & 0x80) > 0 ? 1 : 0; const u8 = new Uint8Array(byte_count + extraByte); for (let i = 0; i < byte_count; i++) { const j = extraByte ? i + 1 : i; u8[j] = (v >> (byte_count - i - 1) * 8) & 0xff; } return new __type_compatibility__1.Bytes(u8); } exports.int_to_bytes = int_to_bytes; // The reason to use `pow` instead of `**` is that some transpiler automatically converts `**` into `Math.pow` // which cannot be used against bigint. function pow(base, exp) { return base ** exp; // The code below was once tested, but it is 100x slower than '**' operator. // So I gave up to use it. /* if(exp === BigInt(0)){ return BigInt(1); } else if(exp === BigInt(1)){ return base; } else if(exp < BigInt(0)){ throw new RangeError("BigInt negative exponent"); } const stack: Array<[bigint, bigint]> = []; stack.push([base, exp]); let retVal: bigint = BigInt(1); while(stack.length){ [base, exp] = stack.pop() as [bigint, bigint]; if(exp === BigInt(0)){ continue; } else if(exp === BigInt(1)){ retVal *= base; continue; } if(exp % BigInt(2)){ stack.push([base*base, exp/BigInt(2)]); stack.push([base, BigInt(1)]); } else{ stack.push([base*base, exp/BigInt(2)]); } } return retVal; */ } exports.pow = pow; function bigint_to_bytes(v, option) { if (v === BigInt(0)) { return __type_compatibility__1.Bytes.NULL; } const signed = (option && typeof option.signed === "boolean") ? option.signed : false; if (!signed && v < BigInt(0)) { throw new Error("OverflowError: can't convert negative int to unsigned"); } let byte_count = 1; const div = BigInt(signed ? 1 : 0); const b32 = BigInt(4294967296); if (v > 0) { let right_hand = (v + BigInt(1)) * (div + BigInt(1)); while (pow(b32, BigInt((byte_count - 1) / 4 + 1)) < right_hand) { byte_count += 4; } right_hand = (v + BigInt(1)) * (div + BigInt(1)); while (pow(BigInt(2), (BigInt(8) * BigInt(byte_count))) < right_hand) { byte_count++; } } else if (v < 0) { let right_hand = (-v + BigInt(1)) * (div + BigInt(1)); while (pow(b32, BigInt((byte_count - 1) / 4 + 1)) < right_hand) { byte_count += 4; } right_hand = -v * BigInt(2); while (pow(BigInt(2), (BigInt(8) * BigInt(byte_count))) < right_hand) { byte_count++; } } const extraByte = (signed && v > 0 && ((v >> (BigInt(byte_count - 1) * BigInt(8))) & BigInt(0x80)) > BigInt(0)) ? 1 : 0; const total_bytes = byte_count + extraByte; const u8 = new Uint8Array(total_bytes); const dv = new DataView(u8.buffer); const byte4Remain = byte_count % 4; const byte4Length = (byte_count - byte4Remain) / 4; let bitmask = BigInt(0xffffffff); for (let i = 0; i < byte4Length; i++) { const num = Number((v >> BigInt(32) * BigInt(i)) & bitmask); const pointer = extraByte + byte4Remain + (byte4Length - 1 - i) * 4; dv.setUint32(pointer, num); } v >>= BigInt(32) * BigInt(byte4Length); bitmask = BigInt(0xff); for (let i = 0; i < byte4Remain; i++) { const num = Number((v >> BigInt(8) * BigInt(i)) & bitmask); const pointer = extraByte + byte4Remain - 1 - i; dv.setUint8(pointer, num); } return new __type_compatibility__1.Bytes(u8); } exports.bigint_to_bytes = bigint_to_bytes; /** * Return the number of bytes required to represent this integer. * @param {number} v */ function limbs_for_int(v) { if (v === 0 || v === BigInt(0)) { return 0; } return ((v >= 0 ? v : -v).toString(2).length + 7) >> 3; } exports.limbs_for_int = limbs_for_int;