@fable-org/fable-library-js
Version:
Core library used by F# projects compiled with fable.io
307 lines (306 loc) • 11.6 kB
JavaScript
import { fromParts, truncate } from "./Decimal.js";
import { Exception, bigintHash } from "./Util.js";
const isBigEndian = false;
BigInt.prototype.toJSON = function () {
return `${this.toString()}`;
};
const zero = 0n;
const one = 1n;
const two = 2n;
const minusOne = -1n;
export function isBigInt(x) {
return typeof x === "bigint";
}
export function hash(x) {
return bigintHash(x);
}
export function equals(x, y) {
return x === y;
}
export function compare(x, y) {
return x < y ? -1 : x > y ? 1 : 0;
}
export function abs(x) { return x < zero ? -x : x; }
export function sign(x) { return x < zero ? -1 : x > zero ? 1 : 0; }
export function max(x, y) { return x > y ? x : y; }
export function min(x, y) { return x < y ? x : y; }
export function maxMagnitude(x, y) { return abs(x) > abs(y) ? x : y; }
export function minMagnitude(x, y) { return abs(x) < abs(y) ? x : y; }
export function clamp(x, min, max) {
return x < min ? min : x > max ? max : x;
}
export function add(x, y) { return x + y; }
export function subtract(x, y) { return x - y; }
export function multiply(x, y) { return x * y; }
export function divide(x, y) { return x / y; }
export function remainder(x, y) { return x % y; }
export function negate(x) { return -x; }
export function op_UnaryNegation(x) { return -x; }
export function op_LogicalNot(x) { return ~x; }
export function op_UnaryPlus(x) { return x; }
export function op_Addition(x, y) { return x + y; }
export function op_Subtraction(x, y) { return x - y; }
export function op_Multiply(x, y) { return x * y; }
export function op_Division(x, y) { return x / y; }
export function op_Modulus(x, y) { return x % y; }
export function op_RightShift(x, n) { return x >> BigInt(n); }
export function op_LeftShift(x, n) { return x << BigInt(n); }
export function op_BitwiseAnd(x, y) { return x & y; }
export function op_BitwiseOr(x, y) { return x | y; }
export function op_ExclusiveOr(x, y) { return x ^ y; }
export function op_LessThan(x, y) { return x < y; }
export function op_LessThanOrEqual(x, y) { return x <= y; }
export function op_GreaterThan(x, y) { return x > y; }
export function op_GreaterThanOrEqual(x, y) { return x >= y; }
export function op_Equality(x, y) { return x === y; }
export function op_Inequality(x, y) { return x !== y; }
export function get_Zero() { return zero; }
export function get_One() { return one; }
export function get_MinusOne() { return minusOne; }
export function get_IsZero(x) { return x === zero; }
export function get_IsOne(x) { return x === one; }
export function get_IsEven(x) { return isEvenInteger(x); }
export function get_IsPowerOfTwo(x) { return isPow2(x); }
export function get_Sign(x) { return sign(x); }
export function isNegative(x) { return x < zero; }
export function isPositive(x) { return x > zero; }
export function isEvenInteger(x) { return (x % two) === zero; }
export function isOddInteger(x) { return (x % two) !== zero; }
export function isPow2(x) { return (x & (x - one)) === zero; }
export function fromZero() { return zero; }
export function fromOne() { return one; }
export function fromInt8(n) { return BigInt(n); }
export function fromUInt8(n) { return BigInt(n); }
export function fromInt16(n) { return BigInt(n); }
export function fromUInt16(n) { return BigInt(n); }
export function fromInt32(n) { return BigInt(n); }
export function fromUInt32(n) { return BigInt(n); }
export function fromInt64(n) { return n; }
export function fromUInt64(n) { return n; }
export function fromInt128(n) { return n; }
export function fromUInt128(n) { return n; }
export function fromNativeInt(n) { return n; }
export function fromUNativeInt(n) { return n; }
export function fromFloat16(n) { return BigInt(Math.trunc(n)); }
export function fromFloat32(n) { return BigInt(Math.trunc(n)); }
export function fromFloat64(n) { return BigInt(Math.trunc(n)); }
export function fromDecimal(d) { return BigInt(truncate(d).toString()); }
export function fromBigInt(x) { return x; }
export function fromBoolean(b) { return BigInt(b); }
export function fromChar(c) { return BigInt(c.charCodeAt(0)); }
export function fromString(s) { return BigInt(s); }
export function fromByteArray(bytes) {
return fromSignedBytes(bytes, isBigEndian);
}
export function toByteArray(value) {
return toSignedBytes(value, isBigEndian);
}
export function toIntN_unchecked(bits, x, signed) {
return signed ? BigInt.asIntN(bits, x) : BigInt.asUintN(bits, x);
}
export function toIntN(bits, x, signed) {
let higher_bits = abs(x) >> BigInt(bits);
if (higher_bits !== 0n) {
const s = signed ? "a signed" : "an unsigned";
throw new Exception(`Value was either too large or too small for ${s} ${bits}-bit integer.`);
}
return signed ? BigInt.asIntN(bits, x) : BigInt.asUintN(bits, x);
}
export function toInt8(x) { return Number(toIntN(8, x, true)); }
export function toUInt8(x) { return Number(toIntN(8, x, false)); }
export function toInt16(x) { return Number(toIntN(16, x, true)); }
export function toUInt16(x) { return Number(toIntN(16, x, false)); }
export function toInt32(x) { return Number(toIntN(32, x, true)); }
export function toUInt32(x) { return Number(toIntN(32, x, false)); }
export function toInt64(x) { return toIntN(64, x, true); }
export function toUInt64(x) { return toIntN(64, x, false); }
export function toInt128(x) { return toIntN(128, x, true); }
export function toUInt128(x) { return toIntN(128, x, false); }
export function toNativeInt(x) { return toIntN(64, x, true); }
export function toUNativeInt(x) { return toIntN(64, x, false); }
export function toInt8_unchecked(x) { return Number(toIntN_unchecked(8, x, true)); }
export function toUInt8_unchecked(x) { return Number(toIntN_unchecked(8, x, false)); }
export function toInt16_unchecked(x) { return Number(toIntN_unchecked(16, x, true)); }
export function toUInt16_unchecked(x) { return Number(toIntN_unchecked(16, x, false)); }
export function toInt32_unchecked(x) { return Number(toIntN_unchecked(32, x, true)); }
export function toUInt32_unchecked(x) { return Number(toIntN_unchecked(32, x, false)); }
export function toInt64_unchecked(x) { return toIntN_unchecked(64, x, true); }
export function toUInt64_unchecked(x) { return toIntN_unchecked(64, x, false); }
export function toInt128_unchecked(x) { return toIntN_unchecked(128, x, true); }
export function toUInt128_unchecked(x) { return toIntN_unchecked(128, x, false); }
export function toNativeInt_unchecked(x) { return toIntN_unchecked(64, x, true); }
export function toUNativeInt_unchecked(x) { return toIntN_unchecked(64, x, false); }
export function toFloat16(x) { return Number(x); }
export function toFloat32(x) { return Number(x); }
export function toFloat64(x) { return Number(x); }
export function toDecimal(x) {
const isNegative = x < zero;
const bits = abs(x);
const low = Number(BigInt.asUintN(32, bits));
const mid = Number(BigInt.asUintN(32, bits >> 32n));
const high = Number(BigInt.asUintN(32, bits >> 64n));
const scale = 0;
return fromParts(low, mid, high, isNegative, scale);
}
export function toBigInt(x) { return x; }
export function toBoolean(x) { return x !== zero; }
export function toChar(x) {
return String.fromCharCode(toUInt16(x));
}
export function toString(x) { return x.toString(); }
export function tryParse(s, res) {
try {
res.contents = BigInt(s);
return true;
}
catch (err) {
return false;
}
}
export function parse(s) {
return BigInt(s);
}
export function pow(x, n) {
return x ** BigInt(n);
}
export function modPow(x, e, m) {
return (x ** e) % m;
}
export function divRem(x, y, out) {
const div = x / y;
const rem = x % y;
if (out === void 0) {
return [div, rem];
}
else {
out.contents = rem;
return div;
}
}
export function greatestCommonDivisor(x, y) {
while (y > zero) {
const q = x / y;
const r = x - q * y;
x = y;
y = r;
}
return x;
}
export function getBitLength(x) {
return fromFloat64(x === zero ? 1 : log2(abs(x)) + 1);
}
export function log2(x) {
const n = Number(x);
if (Number.isFinite(n))
return Math.log2(n); // fast path
if (x < zero)
return Number.NaN;
let shift = one;
while (x >= (one << shift)) {
shift = shift << one;
}
let log = zero;
while (shift > one) {
shift = shift >> one;
if (x >= (one << shift)) {
log = log + shift;
x = x >> shift;
}
}
return Number(log);
}
export function log10(x) {
return log2(x) * Math.log10(2);
}
export function ln(x) {
return log2(x) * Math.log(2);
}
export function log(x, base) {
return log2(x) / Math.log2(base);
}
export function ilog2(x) {
return BigInt(log2(x));
}
// export function copySign
// export function createChecked
// export function createSaturating
// export function createTruncating
// export function getByteCount
// export function leadingZeroCount
// export function popCount
// export function rotateLeft
// export function rotateRight
// export function trailingZeroCount
// export function tryFormat
// export function tryWriteBytes
// -------------------------------------------------
// Binary serialization
// -------------------------------------------------
const hexCodes = new Uint8Array([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102]);
function fromHexCode(code) {
if (48 <= code && code <= 57)
return code - 48;
if (97 <= code && code <= 102)
return code - 97 + 10;
if (65 <= code && code <= 70)
return code - 65 + 10;
throw Error(`Invalid hex code: ${code}`);
}
function toSignedBytes(x, isBigEndian) {
const isNeg = x < 0n;
if (isNeg) {
const len = log2(-x);
const bits = len + (8 - len % 8);
const pow2 = (1n << BigInt(bits));
x = x + pow2; // two's complement
}
const hex = x.toString(16);
const len = hex.length;
const odd = len % 2;
const first = hex.charCodeAt(0);
const isLow = 48 <= first && first <= 55; // 0..7
const start = (isNeg && isLow) || (!isNeg && !isLow) ? 1 : 0;
const bytes = new Uint8Array(start + (len + odd) / 2);
const inc = isBigEndian ? 1 : -1;
let pos = isBigEndian ? 0 : bytes.length - 1;
if (start > 0) {
bytes[pos] = isNeg ? 255 : 0;
pos += inc;
}
if (odd > 0) {
bytes[pos] = fromHexCode(first);
pos += inc;
}
for (let i = odd; i < len; i += 2, pos += inc) {
const a = fromHexCode(hex.charCodeAt(i));
const b = fromHexCode(hex.charCodeAt(i + 1));
bytes[pos] = (a << 4) | b;
}
return bytes;
}
function fromSignedBytes(bytes, isBigEndian) {
if (bytes == null) {
throw new Exception("bytes is null");
}
const len = bytes.length;
const first = isBigEndian ? 0 : len - 1;
const isNeg = bytes[first] > 127;
const codes = new Uint16Array(len * 2 + 2);
codes[0] = 48; // 0
codes[1] = 120; // x
const inc = isBigEndian ? 1 : -1;
let pos = isBigEndian ? 0 : len - 1;
for (let i = 0; i < bytes.length; i++, pos += inc) {
const byte = bytes[pos];
codes[2 * i + 2] = hexCodes[byte >> 4];
codes[2 * i + 3] = hexCodes[byte & 15];
}
const str = String.fromCharCode.apply(null, codes);
let x = BigInt(str);
if (isNeg) {
const bits = len * 8;
const pow2 = (1n << BigInt(bits));
x = x - pow2; // two's complement
}
return x;
}