UNPKG

@fable-org/fable-library-js

Version:

Core library used by F# projects compiled with fable.io

237 lines (236 loc) 8.02 kB
import Decimal from "./lib/big.js"; import { symbol } from "./Numeric.js"; import { FSharpRef } from "./Types.js"; import { Exception, combineHashCodes } from "./Util.js"; import { fromDecimal } from "./BigInt.js"; import * as bigInt from "./BigInt.js"; Decimal.prototype.GetHashCode = function () { return combineHashCodes([this.s, this.e].concat(this.c)); }; Decimal.prototype.Equals = function (x) { return !this.cmp(x); }; Decimal.prototype.CompareTo = function (x) { return this.cmp(x); }; Decimal.prototype[symbol] = function () { const _this = this; return { multiply: (y) => _this.mul(y), toPrecision: (sd) => _this.toPrecision(sd), toExponential: (dp) => _this.toExponential(dp), toFixed: (dp) => _this.toFixed(dp), toHex: () => (Number(_this) >>> 0).toString(16), }; }; export default Decimal; export const get_Zero = new Decimal(0); export const get_One = new Decimal(1); export const get_MinusOne = new Decimal(-1); export const get_MaxValue = new Decimal("79228162514264337593543950335"); export const get_MinValue = new Decimal("-79228162514264337593543950335"); export function compare(x, y) { return x.cmp(y); } export function equals(x, y) { return !x.cmp(y); } export function abs(x) { return x.abs(); } export function sign(x) { return x.lt(get_Zero) ? -1 : x.gt(get_Zero) ? 1 : 0; } export function max(x, y) { return x.gt(y) ? x : y; } export function min(x, y) { return x.lt(y) ? x : y; } export function maxMagnitude(x, y) { return abs(x).gt(abs(y)) ? x : y; } export function minMagnitude(x, y) { return abs(x).lt(abs(y)) ? x : y; } export function clamp(x, min, max) { return x.lt(min) ? min : x.gt(max) ? max : x; } export function round(x, digits = 0) { return x.round(digits, 2 /* ROUND_HALF_EVEN */); } export function truncate(x) { return x.round(0, 0 /* ROUND_DOWN */); } export function ceiling(x) { return x.round(0, x.cmp(0) >= 0 ? 3 /* ROUND_UP */ : 0 /* ROUND_DOWN */); } export function floor(x) { return x.round(0, x.cmp(0) >= 0 ? 0 /* ROUND_DOWN */ : 3 /* ROUND_UP */); } export function pow(x, n) { return x.pow(n); } export function sqrt(x) { return x.sqrt(); } export function op_Addition(x, y) { return x.add(y); } export function op_Subtraction(x, y) { return x.sub(y); } export function op_Multiply(x, y) { return x.mul(y); } export function op_Division(x, y) { return x.div(y); } export function op_Modulus(x, y) { return x.mod(y); } export function op_UnaryNegation(x) { const x2 = new Decimal(x); x2.s = -x2.s || 0; return x2; } export function op_UnaryPlus(x) { return x; } export const add = op_Addition; export const subtract = op_Subtraction; export const multiply = op_Multiply; export const divide = op_Division; export const remainder = op_Modulus; export const negate = op_UnaryNegation; export function toString(x) { return x.toString(); } export function tryParse(str, defValue) { try { defValue.contents = new Decimal(str.trim()); return true; } catch { return false; } } export function parse(str) { const defValue = new FSharpRef(get_Zero); if (tryParse(str, defValue)) { return defValue.contents; } else { throw new Exception(`The input string ${str} was not in a correct format.`); } } export function toNumber(x) { return +x; } export function toChar(x) { const n = toNumber(x); if (n < 0 || n > 65535 || isNaN(n)) { throw new Exception("Value was either too large or too small for a character."); } return String.fromCharCode(n); } export function toInt8(x) { return bigInt.toInt8(fromDecimal(x)); } export function toUInt8(x) { return bigInt.toUInt8(fromDecimal(x)); } export function toInt16(x) { return bigInt.toInt16(fromDecimal(x)); } export function toUInt16(x) { return bigInt.toUInt16(fromDecimal(x)); } export function toInt32(x) { return bigInt.toInt32(fromDecimal(x)); } export function toUInt32(x) { return bigInt.toUInt32(fromDecimal(x)); } export function toInt64(x) { return bigInt.toInt64(fromDecimal(x)); } export function toUInt64(x) { return bigInt.toUInt64(fromDecimal(x)); } export function toInt128(x) { return bigInt.toInt128(fromDecimal(x)); } export function toUInt128(x) { return bigInt.toUInt128(fromDecimal(x)); } export function toNativeInt(x) { return bigInt.toNativeInt(fromDecimal(x)); } export function toUNativeInt(x) { return bigInt.toUNativeInt(fromDecimal(x)); } export function toFloat16(x) { return toNumber(x); } export function toFloat32(x) { return toNumber(x); } export function toFloat64(x) { return toNumber(x); } function decimalToHex(dec, bitSize) { const hex = new Uint8Array(bitSize / 4 | 0); let hexCount = 1; for (let d = 0; d < dec.length; d++) { let value = dec[d]; for (let i = 0; i < hexCount; i++) { const digit = hex[i] * 10 + value | 0; hex[i] = digit & 0xF; value = digit >> 4; } if (value !== 0) { hex[hexCount++] = value; } } return hex.slice(0, hexCount); // digits in reverse order } function hexToDecimal(hex, bitSize) { const dec = new Uint8Array(bitSize * 301 / 1000 + 1 | 0); let decCount = 1; for (let d = hex.length - 1; d >= 0; d--) { let carry = hex[d]; for (let i = 0; i < decCount; i++) { const val = dec[i] * 16 + carry | 0; dec[i] = (val % 10) | 0; carry = (val / 10) | 0; } while (carry > 0) { dec[decCount++] = (carry % 10) | 0; carry = (carry / 10) | 0; } } return dec.slice(0, decCount); // digits in reverse order } function setInt32Bits(hexDigits, bits, offset) { for (let i = 0; i < 8; i++) { hexDigits[offset + i] = (bits >> (i * 4)) & 0xF; } } function getInt32Bits(hexDigits, offset) { let bits = 0; for (let i = 0; i < 8; i++) { bits = bits | (hexDigits[offset + i] << (i * 4)); } return bits; } export function fromIntArray(bits) { return fromInts(bits[0], bits[1], bits[2], bits[3]); } export function fromInts(low, mid, high, signExp) { const isNegative = signExp < 0; const scale = (signExp >> 16) & 0x7F; return fromParts(low, mid, high, isNegative, scale); } export function fromParts(low, mid, high, isNegative, scale) { const bitSize = 96; const hexDigits = new Uint8Array(bitSize / 4); setInt32Bits(hexDigits, low, 0); setInt32Bits(hexDigits, mid, 8); setInt32Bits(hexDigits, high, 16); const decDigits = hexToDecimal(hexDigits, bitSize); scale = scale & 0x7F; const big = new Decimal(0); big.c = Array.from(decDigits.reverse()); big.e = decDigits.length - scale - 1; big.s = isNegative ? -1 : 1; const d = new Decimal(big); return d; } export function getBits(d) { const bitSize = 96; const decDigits = Uint8Array.from(d.c); const hexDigits = decimalToHex(decDigits, bitSize); const low = getInt32Bits(hexDigits, 0); const mid = getInt32Bits(hexDigits, 8); const high = getInt32Bits(hexDigits, 16); const decStr = d.toString(); const dotPos = decStr.indexOf("."); const scale = dotPos < 0 ? 0 : decStr.length - dotPos - 1; const signExp = ((scale & 0x7F) << 16) | (d.s < 0 ? 0x80000000 : 0); return [low, mid, high, signExp]; } // export function makeRangeStepFunction(step: Decimal, last: Decimal) { // const stepComparedWithZero = step.cmp(get_Zero); // if (stepComparedWithZero === 0) { // throw new Exception("The step of a range cannot be zero"); // } // const stepGreaterThanZero = stepComparedWithZero > 0; // return (x: Decimal) => { // const comparedWithLast = x.cmp(last); // if ((stepGreaterThanZero && comparedWithLast <= 0) // || (!stepGreaterThanZero && comparedWithLast >= 0)) { // return [x, op_Addition(x, step)]; // } else { // return undefined; // } // }; // }