bigfloat-esnext
Version:
A library for arbitrary precision floating point arithmetic.
112 lines (111 loc) • 4.15 kB
JavaScript
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;
;