UNPKG

bigfloat-esnext

Version:

A library for arbitrary precision floating point arithmetic.

112 lines (111 loc) 4.15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.floor = exports.ceil = exports.exponentiation = exports.sqrt = exports.div = exports.mul = exports.sub = exports.add = exports.abs = exports.neg = void 0; const constants_js_1 = require("./constants.js"); const constructors_js_1 = require("./constructors.js"); const predicates_js_1 = require("./predicates.js"); const relational_js_1 = require("./relational.js"); function neg(a) { return constructors_js_1.make_big_float(-a.coefficient, a.exponent); } exports.neg = neg; function abs(a) { return predicates_js_1.is_negative(a) ? neg(a) : a; } exports.abs = abs; function conform_op(op) { return function (a, b) { const differential = a.exponent - b.exponent; return differential === 0 ? constructors_js_1.make_big_float(op(a.coefficient, b.coefficient), a.exponent) : differential > 0 ? constructors_js_1.make_big_float(op(a.coefficient * constants_js_1.BIGINT_TEN ** BigInt(differential), b.coefficient), b.exponent) : constructors_js_1.make_big_float(op(a.coefficient, b.coefficient * constants_js_1.BIGINT_TEN ** BigInt(-differential)), a.exponent); }; } exports.add = conform_op((a, b) => a + b); exports.sub = conform_op((a, b) => a - b); function mul(multiplicand, multiplier) { return constructors_js_1.make_big_float(multiplicand.coefficient * multiplier.coefficient, multiplicand.exponent + multiplier.exponent); } exports.mul = mul; function div(dividend, divisor, precision = constants_js_1.PRECISION) { if (predicates_js_1.is_zero(dividend) || predicates_js_1.is_zero(divisor)) { return constants_js_1.ZERO; } let { coefficient, exponent } = dividend; exponent -= divisor.exponent; if (typeof precision !== "number") { precision = constructors_js_1.number(precision); } if (exponent > precision) { coefficient = coefficient * constants_js_1.BIGINT_TEN ** BigInt(exponent - precision); exponent = precision; } coefficient = coefficient / divisor.coefficient; return constructors_js_1.make_big_float(coefficient, exponent); } exports.div = div; function sqrt(n) { let x = n; let y = constants_js_1.ONE; while (relational_js_1.gt(exports.sub(x, y), constants_js_1.EPSILON)) { x = div(exports.add(x, y), constants_js_1.TWO); y = div(n, x); } return x; } exports.sqrt = sqrt; function exponentiation(base, exp) { if (relational_js_1.eq(exp, constants_js_1.ZERO)) { return constants_js_1.ONE; } if (predicates_js_1.is_negative(exp)) { return div(constants_js_1.ONE, exponentiation(base, abs(exp))); } if (exp.exponent === 0) { let result = base; let n = 1; while (n !== constructors_js_1.number(exp)) { result = mul(result, base); n += 1; } return result; } if (relational_js_1.gt(exp, constants_js_1.ONE) || relational_js_1.eq(exp, constants_js_1.ONE)) { const temp = exponentiation(base, div(exp, constants_js_1.TWO)); return mul(temp, temp); } let low = constants_js_1.ZERO; let high = constants_js_1.ONE; let sqr = sqrt(base); let acc = sqr; let mid = div(high, constants_js_1.TWO); while (relational_js_1.gt(abs(exports.sub(mid, exp)), constants_js_1.EPSILON)) { sqr = sqrt(sqr); if (relational_js_1.lt(mid, exp) || relational_js_1.eq(mid, exp)) { low = mid; acc = mul(acc, sqr); } else { high = mid; acc = mul(acc, div(constants_js_1.ONE, sqr)); } mid = div(exports.add(low, high), constants_js_1.TWO); } return acc; } exports.exponentiation = exponentiation; function ceil(n) { if (predicates_js_1.is_integer(n)) { return n; } else { return constructors_js_1.make_big_float(constructors_js_1.integer(n).coefficient + constants_js_1.BIGINT_ONE, 0); } } exports.ceil = ceil; function floor(n) { return constructors_js_1.integer(n); } exports.floor = floor;