UNPKG

bigfloat.js

Version:

A library for arbitrary precision floating point arithmetic.

168 lines (167 loc) 6.35 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; exports.__esModule = true; exports.scientific = exports.string = exports.make = exports.fraction = exports.integer = exports.normalize = exports.number = exports.make_big_float = void 0; var jsbi_1 = __importDefault(require("jsbi")); var arithmetic_js_1 = require("./arithmetic.js"); var constants_js_1 = require("./constants.js"); var predicates_js_1 = require("./predicates.js"); function make_big_float(coefficient, exponent) { if (jsbi_1["default"].EQ(coefficient, constants_js_1.BIGINT_ZERO)) { return constants_js_1.ZERO; } var new_big_float = Object.create(null); new_big_float.coefficient = coefficient; new_big_float.exponent = exponent; return Object.freeze(new_big_float); } exports.make_big_float = make_big_float; function number(a) { if (typeof a !== "number" && typeof a !== "string") { if (a instanceof jsbi_1["default"]) { return jsbi_1["default"].toNumber(a); } else if (predicates_js_1.is_big_float(a)) { return a.exponent === 0 ? jsbi_1["default"].toNumber(a.coefficient) : jsbi_1["default"].toNumber(a.coefficient) * Math.pow(10, a.exponent); } } return Number(a); } exports.number = number; function normalize(a) { var coefficient = a.coefficient, exponent = a.exponent; // If the exponent is zero, it is already normal. if (exponent !== 0) { if (exponent > 0) { coefficient = jsbi_1["default"].multiply(coefficient, jsbi_1["default"].exponentiate(constants_js_1.BIGINT_TEN, jsbi_1["default"].BigInt(exponent))); exponent = 0; } else { var quotient = void 0; var remainder = void 0; // tslint:disable-next-line: no-bitwise while (exponent <= -7) { quotient = jsbi_1["default"].divide(coefficient, constants_js_1.BIGINT_TEN_MILLION); remainder = jsbi_1["default"].remainder(coefficient, constants_js_1.BIGINT_TEN_MILLION); if (!jsbi_1["default"].EQ(remainder, constants_js_1.BIGINT_ZERO)) { break; } coefficient = quotient; exponent += 7; } while (exponent < 0) { quotient = jsbi_1["default"].divide(coefficient, constants_js_1.BIGINT_TEN); remainder = jsbi_1["default"].remainder(coefficient, constants_js_1.BIGINT_TEN); if (!jsbi_1["default"].EQ(remainder, constants_js_1.BIGINT_ZERO)) { break; } coefficient = quotient; exponent += 1; } } } return make_big_float(coefficient, exponent); } exports.normalize = normalize; function integer(a) { // The integer function is like the normalize function except that it throws // away significance. It discards the digits after the decimal point. var coefficient = a.coefficient, exponent = a.exponent; // If the exponent is zero, it is already an integer. if (exponent === 0) { return a; } // If the exponent is positive, // multiply the coefficient by 10 ** exponent. if (exponent > 0) { return make_big_float(jsbi_1["default"].multiply(coefficient, jsbi_1["default"].exponentiate(constants_js_1.BIGINT_TEN, jsbi_1["default"].BigInt(exponent))), 0); } // If the exponent is negative, divide the coefficient by 10 ** -exponent. // This truncates the unnecessary bits. This might be a zero result. return make_big_float(jsbi_1["default"].divide(coefficient, jsbi_1["default"].exponentiate(constants_js_1.BIGINT_TEN, jsbi_1["default"].BigInt(-exponent))), 0); } exports.integer = integer; function fraction(a) { return arithmetic_js_1.sub(a, integer(a)); } exports.fraction = fraction; function make(a, b) { var number_pattern = /^(-?\d+)(?:\.(\d*))?(?:e(-?\d+))?$/; // . Capturing groups // . [1] int // . [2] frac // . [3] exp if (a instanceof jsbi_1["default"]) { return make_big_float(a, Number(b) || 0); } else if (typeof a === "string" || typeof a === "number") { a = String(a); if (Number.isSafeInteger(Number(b))) { return make(jsbi_1["default"].BigInt(parseInt(a, Number(b))), 0); } var parts = a.match(number_pattern); if (parts) { var frac = parts[2] || ""; return make(jsbi_1["default"].BigInt(parts[1] + frac), (Number(parts[3]) || 0) - frac.length); } } else if (predicates_js_1.is_big_float(a)) { return a; } return constants_js_1.ZERO; } exports.make = make; function string(a, radix) { if (predicates_js_1.is_zero(a)) { return "0"; } if (radix && predicates_js_1.is_big_float(radix)) { radix = normalize(radix); return radix && radix.exponent === 0 ? integer(a).coefficient.toString(jsbi_1["default"].toNumber(radix.coefficient)) : undefined; } a = normalize(a); var s = (jsbi_1["default"].LT(a.coefficient, constants_js_1.BIGINT_ZERO) ? -a.coefficient : a.coefficient).toString(); if (a.exponent < 0) { var point = s.length + a.exponent; if (point <= 0) { s = "0".repeat(1 - point) + s; point = 1; } s = s.slice(0, point) + "." + s.slice(point); } else if (a.exponent > 0) { s += "0".repeat(a.exponent); } if (jsbi_1["default"].LT(a.coefficient, constants_js_1.BIGINT_ZERO)) { s = "-" + s; } return s; } exports.string = string; function scientific(a) { if (predicates_js_1.is_zero(a)) { return "0"; } a = normalize(a); var s = String(jsbi_1["default"].LT(a.coefficient, constants_js_1.BIGINT_ZERO) ? -a.coefficient : a.coefficient); var e = a.exponent + s.length - 1; if (s.length > 1) { s = s.slice(0, 1) + "." + s.slice(1); } if (e !== 0) { s += "e" + e; } if (jsbi_1["default"].LT(a.coefficient, constants_js_1.BIGINT_ZERO)) { s = "-" + s; } return s; } exports.scientific = scientific;