bigfloat
Version:
Fast arbitrary precision math library for computational geometry.
1,210 lines (1,203 loc) • 50.7 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.bigfloat = {})));
}(this, (function (exports) { 'use strict';
// This file is part of bigfloat, copyright (c) 2015- BusFaster Ltd.
// Released under the MIT license, see LICENSE.
/** Base for calculations, the bigger the better but must fit in 32 bits. */
var limbSize32 = Math.pow(2, 32);
var limbInv32 = Math.pow(2, -32);
var limbsPerDigit32 = Math.log(10) / (32 * Math.log(2));
/** Create a string with the given number of zero digits. */
function zeroes(count) {
return (new Array(count + 1).join('0'));
}
var BaseInfo32 = /** @class */ (function () {
function BaseInfo32(base) {
this.base = base;
/** Average number of digits per limb. */
this.limbDigitsExact = Math.log(limbSize32) / Math.log(this.base);
/** Number of entire digits per limb. */
this.limbDigits = ~~this.limbDigitsExact;
/** Maximum power of base that fits in a limb. */
this.limbBase = Math.pow(this.base, this.limbDigits);
/** String of zeroes for padding an empty limb. */
this.pad = zeroes(this.limbDigits);
}
BaseInfo32.init = function (base) {
return (BaseInfo32.baseTbl[base] || (BaseInfo32.baseTbl[base] = new BaseInfo32(base)));
};
BaseInfo32.baseTbl = {};
return BaseInfo32;
}());
// This file is part of bigfloat, copyright (c) 2015- BusFaster Ltd.
/** Remove leading and trailing insignificant zero digits. */
function trimNumber(str) {
return (str
.replace(/^(-?)0+([1-9a-z]|0(\.|$))/, '$1$2')
.replace(/(\.|(\.[0-9a-z]*[1-9a-z]))0+$/, '$2'));
}
/** Output EXACT value of an IEEE 754 double in any base supported by Number.toString.
* Exponent must be between -2 and 61, and last 3 bits of mantissa must be 0.
* Useful for debugging. */
function numberToString(dbl, base) {
if (base === void 0) { base = 10; }
var _a = BaseInfo32.init(base), pad = _a.pad, limbBase = _a.limbBase;
var sign = '';
var out = '';
var limb;
var limbStr;
if (isNaN(dbl))
return ('NaN');
// For negative numbers, output sign and get absolute value.
if (dbl < 0) {
sign = '-';
dbl = -dbl;
}
if (!isFinite(dbl))
return (sign + 'Inf');
if (dbl < 1) {
out += '0';
}
else {
var iPart = Math.floor(dbl);
dbl -= iPart;
while (iPart) {
// Extract groups of digits starting from the least significant.
limb = iPart % limbBase;
iPart = (iPart - limb) / limbBase;
limbStr = limb.toString(base);
// Prepend digits to result.
out = limbStr + out;
// If more limbs remain, pad with zeroes to group length.
if (iPart)
out = pad.substr(limbStr.length) + out;
}
}
// Is there a fractional part remaining?
if (dbl > 0) {
out += '.';
if (limbBase != limbSize32) {
limbBase = base;
pad = '';
}
while (dbl) {
// Extract groups of digits starting from the most significant.
dbl *= limbBase;
limb = dbl >>> 0;
dbl -= limb;
limbStr = limb.toString(base);
// Append digits to result and pad with zeroes to group length.
out += pad.substr(limbStr.length) + limbStr;
}
}
// Remove trailing zeroes.
return (sign + out.replace(/(\.[0-9a-z]*[1-9a-z])0+$/, '$1'));
}
// This file is part of bigfloat, copyright (c) 2015- BusFaster Ltd.
var BigFloat32 = /** @class */ (function () {
function BigFloat32(value, base) {
/** List of digits in base 2^32, least significant first. */
this.limbList = [];
value ? this.setValue(value, base) : this.setZero();
}
BigFloat32.prototype.clone = function () {
return (new BigFloat32().setBig(this));
};
BigFloat32.prototype.setZero = function () {
this.sign = 1;
this.fractionLen = 0;
this.len = 0;
return (this);
};
BigFloat32.prototype.setValue = function (other, base) {
if (typeof (other) == 'number') {
return (this.setNumber(other));
}
if (other instanceof BigFloat32) {
return (this.setBig(other));
}
return (this.setString(other.toString(), base || 10));
};
BigFloat32.prototype.setBig = function (other) {
var len = other.len;
this.sign = other.sign;
this.fractionLen = other.fractionLen;
this.len = len;
for (var pos = 0; pos < len; ++pos) {
this.limbList[pos] = other.limbList[pos];
}
return (this);
};
/** Set value from a floating point number (probably IEEE 754 double). */
BigFloat32.prototype.setNumber = function (value) {
if (value < 0) {
value = -value;
this.sign = -1;
}
else {
this.sign = 1;
}
var iPart = Math.floor(value);
var fPart = value - iPart;
var fractionLen = 0;
var limbList = this.limbList;
var limb;
var len = 0;
// Handle fractional part.
while (fPart) {
// Extract limbs starting from the most significant.
fPart *= limbSize32;
limb = fPart >>> 0;
fPart -= limb;
// Append limb to value (limbs are reversed later).
limbList[len++] = limb;
++fractionLen;
}
// Reverse array from 0 to len.
var pos = 0;
while (--len > pos) {
limb = limbList[pos];
limbList[pos++] = limbList[len];
limbList[len] = limb;
}
len += pos + 1;
// Handle integer part.
while (iPart) {
// Extract limbs starting from the least significant.
limb = iPart % limbSize32; // Could also be iPart >>> 0
iPart = (iPart - limb) / limbSize32;
// Append limb to value.
limbList[len++] = limb;
}
this.limbList = limbList;
this.fractionLen = fractionLen;
this.len = len;
return (this);
};
BigFloat32.prototype.parseFraction = function (value, base, start, offset, limbBase, limbDigits) {
var limbList = this.limbList;
var pos = value.length;
// Set limbs to zero, because divInt uses them as input.
var limbNum = offset - 1;
while (limbNum) {
limbList[--limbNum] = 0;
}
// Read initial digits so their count becomes divisible by limbDigits.
var posNext = pos - ((pos - start + limbDigits - 1) % limbDigits + 1);
limbList[offset - 1] = parseInt(value.substr(posNext, pos - posNext), base);
this.divInt(Math.pow(base, pos - posNext), offset);
pos = posNext;
// Read rest of the digits in limbDigits sized chunks.
while (pos > start) {
pos -= limbDigits;
limbList[offset - 1] = parseInt(value.substr(pos, limbDigits), base);
// Divide by maximum power of base that fits in a limb.
this.divInt(limbBase, offset);
}
};
BigFloat32.prototype.setString = function (value, base) {
var _a = BaseInfo32.init(base), limbBase = _a.limbBase, limbDigits = _a.limbDigits, limbDigitsExact = _a.limbDigitsExact;
var limbList = this.limbList;
var pos = -1;
var c;
this.sign = 1;
// Handle leading signs and zeroes.
while (1) {
c = value.charAt(++pos);
switch (c) {
case '-':
this.sign = -1;
case '+':
case '0':
continue;
}
break;
}
var posDot = (value.indexOf('.', pos) + 1 || value.length + 1) - 1;
// Handle fractional part.
if (posDot < value.length - 1) {
// Reserve enough limbs to contain digits in fractional part.
var len = ~~((value.length - posDot - 1) / limbDigitsExact) + 1;
this.parseFraction(value, base, posDot + 1, len + 1, limbBase, limbDigits);
this.fractionLen = len;
this.len = len;
// Remove trailing zeroes.
this.trimLeast();
}
else {
this.fractionLen = 0;
this.len = 0;
}
var offset = this.fractionLen;
// Handle integer part.
if (posDot > pos) {
// Read initial digits so their count becomes divisible by limbDigits.
var posNext = pos + (posDot - pos + limbDigits - 1) % limbDigits + 1;
++this.len;
limbList[offset] = parseInt(value.substr(pos, posNext - pos), base);
pos = posNext;
// Read rest of the digits in limbDigits sized chunks.
while (pos < posDot) {
// Multiply by maximum power of base that fits in a limb.
if (this.mulInt(limbBase, limbList, offset, offset, 0))
++this.len;
// Add latest limb.
limbList[offset] += parseInt(value.substr(pos, limbDigits), base);
pos += limbDigits;
}
}
return (this);
};
/** Trim zero limbs from most significant end. */
BigFloat32.prototype.trimMost = function () {
var limbList = this.limbList;
var fractionLen = this.fractionLen;
var len = this.len;
while (len > fractionLen && !limbList[len - 1])
--len;
this.len = len;
};
/** Trim zero limbs from least significant end. */
BigFloat32.prototype.trimLeast = function () {
var limbList = this.limbList;
var len = this.fractionLen;
var pos = 0;
while (pos < len && !limbList[pos])
++pos;
if (pos)
this.truncate(len - pos);
};
/** Multiply by an integer and write output limbs to another list. */
BigFloat32.prototype.mulInt = function (factor, dstLimbList, srcPos, dstPos, overwriteMask) {
if (!factor)
return (0);
var limbList = this.limbList;
var limbCount = this.len;
var limb;
var lo;
var carry = 0;
// limbList is an array of 32-bit ints but split here into 16-bit low
// and high words for multiplying by a 32-bit term, so the intermediate
// 48-bit multiplication results fit into 53 bits of IEEE 754 mantissa.
while (srcPos < limbCount) {
limb = limbList[srcPos++];
// Multiply lower half of limb with factor, making carry temporarily take 48 bits.
carry += factor * (limb & 0xffff);
// Get lowest 16 bits of full product.
lo = carry & 0xffff;
// Right shift by dividing because >> and >>> truncate to 32 bits before shifting.
carry = (carry - lo) / 65536;
// Multiply higher half of limb and combine with lowest 16 bits of full product.
carry += factor * (limb >>> 16);
lo |= carry << 16;
// Lowest 32 bits of full product are added to output limb.
limb = ((dstLimbList[dstPos] & overwriteMask) + lo) >>> 0;
dstLimbList[dstPos++] = limb;
// Highest 32 bits of full product stay in carry, also increment by 1 if previous sum overflowed.
carry = (carry / 65536) >>> 0;
// Bit twiddle equivalent to: if(limb < (lo >>> 0)) ++carry;
carry += (lo ^ (((limb - lo) ^ lo) & ~(limb ^ lo))) >>> 31;
}
// Extend result by one more limb if it overflows.
if (carry)
dstLimbList[dstPos] = carry;
return (carry);
};
BigFloat32.prototype.mulBig = function (multiplier, product) {
if (this.isZero() || multiplier.isZero())
return (product.setZero());
var multiplierLimbs = multiplier.limbList;
var lenMultiplier = multiplier.len;
var productLimbs = product.limbList;
var posProduct = this.len + lenMultiplier;
product.len = posProduct;
// TODO: Only clear from len to len + lenMultiplier
while (posProduct--) {
productLimbs[posProduct] = 0;
}
this.mulInt(multiplierLimbs[0], productLimbs, 0, 0, 0);
for (var posMultiplier = 1; posMultiplier < lenMultiplier; ++posMultiplier) {
this.mulInt(multiplierLimbs[posMultiplier], productLimbs, 0, posMultiplier, 0xffffffff);
}
product.sign = this.sign * multiplier.sign;
product.fractionLen = this.fractionLen + multiplier.fractionLen;
product.trimMost();
product.trimLeast();
return (product);
};
/** Multiply and return product in a new BigFloat32. */
BigFloat32.prototype.mul = function (multiplier, product) {
product = product || new BigFloat32();
if (typeof (multiplier) == 'number') {
multiplier = temp32.setNumber(multiplier);
}
if (product == this)
throw (new Error('Multiplication in place is unsupported'));
return (this.mulBig(multiplier, product));
};
BigFloat32.prototype.absDeltaFrom = function (other) {
if (typeof (other) == 'number') {
other = temp32.setNumber(other);
}
var limbList = this.limbList;
var otherList = other.limbList;
var limbCount = this.len;
var otherCount = other.len;
// Compare lengths.
// Note: leading zeroes in integer part must be trimmed for this to work!
var d = (limbCount - this.fractionLen) - (otherCount - other.fractionLen);
// If lengths are equal, compare each limb from most to least significant.
while (!d && limbCount && otherCount)
d = limbList[--limbCount] - otherList[--otherCount];
if (d)
return (d);
if (limbCount) {
do
d = limbList[--limbCount];
while (!d && limbCount);
}
else if (otherCount) {
do
d = -otherList[--otherCount];
while (!d && otherCount);
}
return (d);
};
BigFloat32.prototype.isZero = function () {
return (this.len == 0);
};
BigFloat32.prototype.getSign = function () {
return (this.len && this.sign);
};
/** Return an arbitrary number with sign matching the result of this - other. */
BigFloat32.prototype.deltaFrom = function (other) {
if (typeof (other) == 'number') {
other = temp32.setNumber(other);
}
return (
// Make positive and negative zero equal.
this.len + other.len && (
// Compare signs.
this.sign - other.sign ||
// Finally compare full values.
this.absDeltaFrom(other) * this.sign));
};
BigFloat32.prototype.addBig = function (addend, sum) {
var augend = this;
var fractionLen = augend.fractionLen;
var len = fractionLen - addend.fractionLen;
if (len < 0) {
len = -len;
fractionLen += len;
augend = addend;
addend = this;
}
sum.sign = this.sign;
sum.fractionLen = fractionLen;
var sumLimbs = sum.limbList;
var augendLimbs = augend.limbList;
var addendLimbs = addend.limbList;
var posAugend = 0;
var posAddend = 0;
var carry = 0;
var limbSum;
// If one input has more fractional limbs, just copy the leftovers to output.
while (posAugend < len) {
sumLimbs[posAugend] = augendLimbs[posAugend];
++posAugend;
}
var lenAddend = addend.len;
len = augend.len - posAugend;
if (len > lenAddend)
len = lenAddend;
// Calculate sum where input numbers overlap.
while (posAddend < len) {
carry += augendLimbs[posAugend] + addendLimbs[posAddend++];
limbSum = carry >>> 0;
carry = carry - limbSum && 1;
sumLimbs[posAugend++] = limbSum;
}
var posSum = posAugend;
if (len < lenAddend) {
len = lenAddend;
augend = addend;
posAugend = posAddend;
augendLimbs = addendLimbs;
}
else
len = augend.len;
// Copy leftover most significant limbs to output, propagating carry.
while (posAugend < len) {
carry += augendLimbs[posAugend++];
limbSum = carry >>> 0;
carry = carry - limbSum && 1;
sumLimbs[posSum++] = limbSum;
}
if (carry)
sumLimbs[posSum++] = carry;
sum.len = posSum;
sum.trimLeast();
return (sum);
};
BigFloat32.prototype.subBig = function (subtrahend, difference) {
var minuend = this;
difference.sign = this.sign;
// Make sure the subtrahend is the smaller number.
if (minuend.absDeltaFrom(subtrahend) < 0) {
minuend = subtrahend;
subtrahend = this;
difference.sign = -this.sign;
}
var fractionLen = minuend.fractionLen;
var len = fractionLen - subtrahend.fractionLen;
var differenceLimbs = difference.limbList;
var minuendLimbs = minuend.limbList;
var subtrahendLimbs = subtrahend.limbList;
var lenMinuend = minuend.len;
var lenSubtrahend = subtrahend.len;
var lenFinal = lenMinuend;
var posMinuend = 0;
var posSubtrahend = 0;
var posDifference = 0;
var carry = 0;
var limbDiff;
if (len >= 0) {
while (posMinuend < len) {
differenceLimbs[posMinuend] = minuendLimbs[posMinuend];
++posMinuend;
}
len += lenSubtrahend;
if (len > lenMinuend)
len = lenMinuend;
posDifference = posMinuend;
}
else {
len = -len;
fractionLen += len;
lenFinal += len;
while (posSubtrahend < len) {
carry -= subtrahendLimbs[posSubtrahend];
limbDiff = carry >>> 0;
carry = -(carry < 0);
differenceLimbs[posSubtrahend++] = limbDiff;
}
len += lenMinuend;
if (len > lenSubtrahend)
len = lenSubtrahend;
posDifference = posSubtrahend;
}
difference.fractionLen = fractionLen;
// Calculate difference where input numbers overlap.
while (posDifference < len) {
carry += minuendLimbs[posMinuend++] - subtrahendLimbs[posSubtrahend++];
limbDiff = carry >>> 0;
carry = -(carry < 0);
differenceLimbs[posDifference++] = limbDiff;
}
// Copy leftover most significant limbs to output, propagating carry.
while (posDifference < lenFinal) {
carry += minuendLimbs[posMinuend++];
limbDiff = carry >>> 0;
carry = -(carry < 0);
differenceLimbs[posDifference++] = limbDiff;
}
difference.len = posDifference;
difference.trimMost();
difference.trimLeast();
return (difference);
};
BigFloat32.prototype.addSub = function (addend, sign, result) {
result = result || new BigFloat32();
if (result == this)
throw (new Error('Addition and subtraction in place is unsupported'));
if (typeof (addend) == 'number') {
addend = temp32.setNumber(addend);
}
if (this.sign * addend.sign * sign < 0) {
return (this.subBig(addend, result));
}
else {
return (this.addBig(addend, result));
}
};
/** Add and return sum in a new BigFloat32. */
BigFloat32.prototype.add = function (addend, sum) {
return (this.addSub(addend, 1, sum));
};
/** Subtract and return difference in a new BigFloat32. */
BigFloat32.prototype.sub = function (subtrahend, difference) {
return (this.addSub(subtrahend, -1, difference));
};
/** Round towards zero, to given number of base 2^32 fractional digits. */
BigFloat32.prototype.truncate = function (fractionLimbCount) {
var diff = this.fractionLen - fractionLimbCount;
if (diff > 0) {
this.fractionLen = fractionLimbCount;
this.len -= diff;
var len = this.len;
var limbList = this.limbList;
for (var pos = 0; pos < len; ++pos) {
limbList[pos] = limbList[pos + diff];
}
}
return (this);
};
BigFloat32.prototype.round = function (decimalCount) {
return (this.truncate(1 + ~~(decimalCount * limbsPerDigit32)));
};
/** Divide by integer, replacing current value by quotient. Return integer remainder. */
BigFloat32.prototype.divInt = function (divisor, pos) {
var limbList = this.limbList;
var limb;
var hi, lo;
var carry = 0;
// If most significant limb is zero after dividing, decrement number of limbs remaining.
if (limbList[pos - 1] < divisor) {
carry = limbList[--pos];
this.len = pos;
}
while (pos--) {
limb = limbList[pos];
carry = carry * 0x10000 + (limb >>> 16);
hi = (carry / divisor) >>> 0;
carry = carry - hi * divisor;
carry = carry * 0x10000 + (limb & 0xffff);
lo = (carry / divisor) >>> 0;
carry = carry - lo * divisor;
limbList[pos] = ((hi << 16) | lo) >>> 0;
}
return (carry);
};
BigFloat32.prototype.fractionToString = function (base, digitList) {
var _a = BaseInfo32.init(base), pad = _a.pad, limbBase = _a.limbBase;
var limbList = this.limbList;
var limbCount = this.fractionLen;
var limbNum = 0;
var limbStr;
if (base & 1) {
throw (new Error('Conversion of floating point values to odd bases is unsupported'));
}
// Skip least significant limbs that equal zero.
while (limbNum < limbCount && !limbList[limbNum])
++limbNum;
if (limbNum >= limbCount)
return;
digitList.push('.');
var fPart = temp32;
fPart.limbList = limbList.slice(limbNum, limbCount);
fPart.len = limbCount - limbNum;
limbNum = 0;
while (limbNum < fPart.len) {
if (fPart.limbList[limbNum]) {
var carry = fPart.mulInt(limbBase, fPart.limbList, limbNum, limbNum, 0);
limbStr = carry.toString(base);
digitList.push(pad.substr(limbStr.length) + limbStr);
}
else
++limbNum;
}
};
BigFloat32.prototype.getExpansion = function (output) {
var limbList = this.limbList;
var len = this.len;
var exp = this.sign;
var pos = this.fractionLen;
while (pos--) {
exp *= limbInv32;
}
while (++pos < len) {
output[pos] = limbList[pos] * exp;
exp *= limbSize32;
}
return (len);
};
BigFloat32.prototype.valueOf = function () {
var limbList = this.limbList;
var result = 0;
var exp = limbInv32 * this.sign;
var len = this.fractionLen;
var pos = 0;
while (pos < len) {
result = result * limbInv32 + limbList[pos++];
}
len = this.len;
while (pos < len) {
result = result * limbInv32 + limbList[pos++];
exp *= limbSize32;
}
return (result * exp);
};
/** Convert to string in any even base supported by Number.toString.
* @return String in lower case. */
BigFloat32.prototype.toString = function (base) {
if (base === void 0) { base = 10; }
var _a = BaseInfo32.init(base), pad = _a.pad, limbBase = _a.limbBase;
var digitList = [];
var limbList = this.limbList;
var limbStr;
if (limbBase != limbSize32) {
var iPart = temp32;
iPart.limbList = limbList.slice(this.fractionLen, this.len);
iPart.len = this.len - this.fractionLen;
// Loop while 2 or more limbs remain, requiring arbitrary precision division to extract digits.
while (iPart.len > 1) {
limbStr = iPart.divInt(limbBase, iPart.len).toString(base);
// Prepend digits into final result, padded with zeroes to 9 digits.
// Since more limbs still remain, whole result will not have extra padding.
digitList.push(pad.substr(limbStr.length) + limbStr);
}
// Prepend last remaining limb and sign to result.
digitList.push('' + (iPart.limbList[0] || 0));
if (this.sign < 0)
digitList.push('-');
digitList.reverse();
// Handle fractional part.
this.fractionToString(base, digitList);
}
else {
var limbNum = this.len;
var fractionPos = this.fractionLen;
if (this.sign < 0)
digitList.push('-');
if (limbNum == fractionPos)
digitList.push('0');
while (limbNum--) {
limbStr = limbList[limbNum].toString(base);
if (limbNum == fractionPos - 1)
digitList.push('.');
digitList.push(pad.substr(limbStr.length) + limbStr);
}
}
// Remove leading and trailing zeroes.
return (trimNumber(digitList.join('')));
};
return BigFloat32;
}());
BigFloat32.prototype.cmp = BigFloat32.prototype.deltaFrom;
var temp32 = new BigFloat32();
// This file is part of bigfloat, copyright (c) 2018- BusFaster Ltd.
var dekkerSplitter = (1 << 27) + 1;
var limbsPerDigit53 = Math.log(10) / (53 * Math.log(2));
/** See Shewchuk page 7. */
/*
function fastTwoSum(a: number, b: number, sum: number[]) {
const estimate = a + b;
sum[0] = b - (estimate - a);
sum[1] = estimate;
return(sum);
}
*/
/** Error-free addition of two floating point numbers.
* See Shewchuk page 8. Note that output order is swapped! */
function twoSum(a, b, sum) {
var estimate = a + b;
var b2 = estimate - a;
var a2 = estimate - b2;
sum[0] = (a - a2) + (b - b2);
sum[1] = estimate;
return (sum);
}
/** Error-free product of two floating point numbers.
* Store approximate result in global variable tempProduct.
* See Shewchuk page 20.
*
* @return Rounding error. */
function twoProduct(a, b) {
tempProduct = a * b;
var a2 = a * dekkerSplitter;
var aHi = a2 - (a2 - a);
var aLo = a - aHi;
var b2 = b * dekkerSplitter;
var bHi = b2 - (b2 - b);
var bLo = b - bHi;
return (aLo * bLo - (tempProduct - aHi * bHi - aLo * bHi - aHi * bLo));
}
/** Arbitrary precision floating point number. Based on a multiple-component
* expansion format and error free transformations.
*
* Maximum exponent is the same as for plain JavaScript numbers,
* least significant representable binary digit is 2^-1074. */
var BigFloat53 = /** @class */ (function () {
/** @param value Initial value, a plain JavaScript floating point number
* (IEEE 754 double precision). */
function BigFloat53(value, base) {
/** List of components ordered by increasing exponent. */
this.limbList = [];
if (value)
this.setValue(value, base);
}
BigFloat53.prototype.clone = function () {
return (new BigFloat53().setBig(this));
};
/** Set value to zero.
*
* @return This object, for chaining. */
BigFloat53.prototype.setZero = function () {
this.len = 0;
return (this);
};
BigFloat53.prototype.setValue = function (other, base) {
if (typeof (other) == 'number') {
return (this.setNumber(other));
}
if (other instanceof BigFloat53) {
return (this.setBig(other));
}
return (this.setString(other.toString(), base || 10));
};
BigFloat53.prototype.setBig = function (other) {
var len = other.len;
this.len = len;
for (var pos = 0; pos < len; ++pos) {
this.limbList[pos] = other.limbList[pos];
}
return (this);
};
/** Set value to a plain JavaScript floating point number
* (IEEE 754 double precision).
*
* @param value New value.
* @return This object, for chaining. */
BigFloat53.prototype.setNumber = function (value) {
this.limbList[0] = value;
this.len = value && 1;
return (this);
};
BigFloat53.prototype.setString = function (value, base) {
temp32$1[0].setValue(value, base);
this.len = temp32$1[0].getExpansion(this.limbList);
this.normalize();
return (this);
};
/** Set value to the sum of two JavaScript numbers.
*
* @param a Augend.
* @param b Addend.
* @return This object, for chaining. */
BigFloat53.prototype.setSum = function (a, b) {
this.len = 2;
twoSum(a, b, this.limbList);
return (this);
};
/** Set value to the product of two JavaScript numbers.
* @param a Multiplicand.
* @param b Multiplier.
* @return This object, for chaining. */
BigFloat53.prototype.setProduct = function (a, b) {
this.len = 2;
this.limbList[0] = twoProduct(a, b);
this.limbList[1] = tempProduct;
return (this);
};
/** See Compress from Shewchuk page 25. */
// TODO: Test.
BigFloat53.prototype.normalize = function () {
var limbList = this.limbList;
var len = this.len;
var limb;
if (len) {
var a = len - 1;
var b = len - 1;
var q = limbList[a];
var err = void 0;
while (a) {
limb = limbList[--a];
err = q;
q += limb;
err = limb - (q - err);
limbList[b] = q;
b -= err && 1;
q = err || q;
}
limbList[b] = q;
while (++b < len) {
limb = limbList[b];
err = q;
q += limb;
err -= q - limb;
limbList[a] = err;
a += err && 1;
}
limbList[a] = q;
this.len = a + (q && 1);
}
return (this);
};
/** Multiply this arbitrary precision float by a number.
* See Scale-Expansion from Shewchuk page 21.
*
* @param b Multiplier, a JavaScript floating point number.
* @param product Arbitrary precision float to overwrite with result.
* @return Modified product object. */
BigFloat53.prototype.mulSmall = function (b, product) {
var limbList = this.limbList;
var productLimbs = product.limbList;
var count = this.len;
var t1, t2, t3;
var srcPos = 0, dstPos = 0;
/** Write output limb and move to next, unless a zero was written. */
function writeLimb(limb) {
productLimbs[dstPos] = limb;
dstPos += limb && 1;
}
writeLimb(twoProduct(limbList[srcPos++], b));
var q = tempProduct;
while (srcPos < count) {
t1 = twoProduct(limbList[srcPos++], b);
t2 = q + t1;
t3 = t2 - q;
writeLimb(q - (t2 - t3) + (t1 - t3));
q = tempProduct + t2;
writeLimb(t2 - (q - tempProduct));
}
productLimbs[dstPos] = q;
product.len = dstPos + (q && 1);
return (product);
};
/** Multiply this by an arbitrary precision multiplier.
* Pass all components of the multiplier to mulSmall and sum the products.
*
* @param multiplier Number or arbitrary precision float.
* @param product Arbitrary precision float to overwrite with result.
* @return Modified product object. */
BigFloat53.prototype.mulBig = function (multiplier, product) {
var limbList = multiplier.limbList;
var pos = multiplier.len;
if (!pos)
return (product.setZero());
--pos;
this.mulSmall(limbList[pos], pos ? temp53[pos & 1] : product);
while (pos) {
--pos;
this.mulSmall(limbList[pos], product).addBig(temp53[~pos & 1], 1, pos ? temp53[pos & 1] : product);
}
return (product);
};
/** Multiply number or arbitrary precision float with this one
* and store result in another BigFloat53.
*
* @param multiplier Number or arbitrary precision float.
* @param product Arbitrary precision float to overwrite with result.
* If omitted, a new one is allocated.
* @return Modified product object. */
BigFloat53.prototype.mul = function (multiplier, product) {
product = product || new BigFloat53();
if (typeof (multiplier) == 'number') {
return (this.mulSmall(multiplier, product));
}
if (product == this)
throw (new Error('Cannot multiply in place'));
return (this.mulBig(multiplier, product));
};
BigFloat53.prototype.isZero = function () {
var limbList = this.limbList;
var pos = this.len;
while (pos--) {
if (limbList[pos])
return (false);
}
return (true);
};
BigFloat53.prototype.getSign = function () {
var t = this.len;
return (t && (t = this.limbList[t - 1]) && (t > 0 ? 1 : -1));
};
/** Return an arbitrary number with sign matching the result of this - other. */
// TODO: Test.
BigFloat53.prototype.deltaFrom = function (other) {
var t = this.len;
var sign = this.getSign();
var diff = sign;
if (typeof (other) != 'number') {
t = other.len;
diff -= t && (t = other.limbList[t - 1]) && (t > 0 ? 1 : -1);
if (diff || !sign)
return (diff);
this.addBig(other, -1, temp53[0]);
}
else {
diff -= other && (other > 0 ? 1 : -1);
if (diff || !sign)
return (diff);
this.addSmall(-other, temp53[0]);
}
t = temp53[0].len;
return (t && temp53[0].limbList[t - 1]);
};
/** Add a number to this arbitrary precision float.
* See Grow-Expansion from Shewchuk page 10.
*
* @param b JavaScript floating point number to add.
* @param sum Arbitrary precision float to overwrite with result.
* @return Modified sum object. */
BigFloat53.prototype.addSmall = function (b, sum) {
var limbList = this.limbList;
var sumLimbs = sum.limbList;
var count = this.len;
var estimate;
var a, b2, err;
var srcPos = 0, dstPos = 0;
while (srcPos < count) {
a = limbList[srcPos++];
estimate = a + b;
b2 = estimate - a;
a -= estimate - b2;
err = a + (b - b2);
sumLimbs[dstPos] = err;
dstPos += err && 1;
b = estimate;
}
sumLimbs[dstPos] = b;
sum.len = dstPos + (b && 1);
return (sum);
};
/** Add another arbitrary precision float (multiplied by sign) to this one.
* See Fast-Expansion-Sum from Shewchuk page 13.
*
* @param sign Multiplier for negating addend to implement subtraction.
* @param sum Arbitrary precision float to overwrite with result.
* @return Modified sum object. */
BigFloat53.prototype.addBig = function (addend, sign, sum) {
var augendLimbs = this.limbList;
var addendLimbs = addend.limbList;
var sumLimbs = sum.limbList;
var count = this.len + addend.len;
var nextAugendPos = 0;
var nextAddendPos = 0;
var nextSumPos = 0;
/** Latest limb of augend. */
var a = augendLimbs[nextAugendPos++];
/** Latest limb of addend. */
var b = addendLimbs[nextAddendPos++] * sign;
/** Magnitude of latest augend limb. */
var a2 = a < 0 ? -a : a;
/** Magnitude of latest addend limb. */
var b2 = b < 0 ? -b : b;
var nextLimb, nextLimb2, prevLimb;
var err;
if (!count)
return (sum.setZero());
// Append sentinel limbs to avoid testing for end of array.
augendLimbs[this.len] = Infinity;
addendLimbs[addend.len] = Infinity;
/** Get next smallest limb from either augend or addend.
* This avoids merging the two limb lists. */
function getNextLimb() {
var result;
if (a2 < b2) {
result = a;
a = augendLimbs[nextAugendPos++];
a2 = a < 0 ? -a : a;
}
else {
result = b;
b = addendLimbs[nextAddendPos++] * sign;
b2 = b < 0 ? -b : b;
}
return (result);
}
var limb = getNextLimb();
while (--count) {
nextLimb = getNextLimb();
prevLimb = limb;
limb += nextLimb;
nextLimb2 = limb - prevLimb;
err = (prevLimb - (limb - nextLimb2)) + (nextLimb - nextLimb2);
sumLimbs[nextSumPos] = err;
nextSumPos += err && 1;
}
sumLimbs[nextSumPos] = limb;
sum.len = nextSumPos + (limb && 1);
return (sum);
};
BigFloat53.prototype.addSub = function (addend, sign, result) {
result = result || new BigFloat53();
if (typeof (addend) == 'number')
return (this.addSmall(sign * addend, result));
return (this.addBig(addend, sign, result));
};
/** Add number or arbitrary precision float to this one
* and store result in another BigFloat53.
*
* @param addend Number or arbitrary precision float.
* @param sum Arbitrary precision float to overwrite with result.
* If omitted, a new one is allocated.
* @return Modified sum object. */
BigFloat53.prototype.add = function (addend, sum) {
return (this.addSub(addend, 1, sum));
};
/** Subtract number or arbitrary precision float from this one
* and store result in another BigFloat53.
*
* @param subtrahend Number or arbitrary precision float.
* @param difference Arbitrary precision float to overwrite with result.
* If omitted, a new one is allocated.
* @return Modified difference object. */
BigFloat53.prototype.sub = function (subtrahend, difference) {
return (this.addSub(subtrahend, -1, difference));
};
/** Round towards zero, to (at least) given number of base 2^53 fractional digits. */
BigFloat53.prototype.truncate = function (fractionLimbCount) {
this.normalize();
var limbList = this.limbList;
var len = this.len;
// Use binary search to find last |limb| < 1.
var lo = 0;
var hi = len;
var mid = 0;
var limb = 0;
while (lo < hi) {
mid = (lo + hi) >> 1;
limb = limbList[mid];
if (limb > -1 && limb < 1) {
lo = mid + 1;
}
else {
hi = mid;
}
}
if (mid && (limb <= -1 || limb >= 1)) {
limb = limbList[--mid];
}
// Slice off limbs before and including it,
// except the fractionLimbCount last ones.
mid -= fractionLimbCount - 1;
if (mid > 0) {
this.len -= mid;
len = this.len;
for (var pos = 0; pos < len; ++pos) {
limbList[pos] = limbList[pos + mid];
}
}
return (this);
};
BigFloat53.prototype.round = function (decimalCount) {
return (this.truncate(1 + ~~(decimalCount * limbsPerDigit53)));
};
BigFloat53.prototype.valueOf = function () {
var limbList = this.limbList;
var len = this.len;
var result = 0;
for (var pos = 0; pos < len; ++pos) {
result += limbList[pos];
}
return (result);
};
/** Convert to string in any even base supported by Number.toString.
* @return String in lower case. */
BigFloat53.prototype.toString = function (base) {
var limbList = this.limbList;
var pos = this.len;
temp32$1[pos & 1].setZero();
while (pos--) {
temp32$1[~pos & 1].add(limbList[pos], temp32$1[pos & 1]);
}
return (temp32$1[~pos & 1].toString(base));
};
return BigFloat53;
}());
BigFloat53.prototype.cmp = BigFloat53.prototype.deltaFrom;
/** Latest approximate product from twoProduct. */
var tempProduct = 0;
/** Temporary values for internal calculations. */
var temp32$1 = [new BigFloat32(), new BigFloat32()];
/** Temporary values for internal calculations. */
var temp53 = [new BigFloat53(), new BigFloat53()];
// This file is part of bigfloat, copyright (c) 2018- BusFaster Ltd.
/** Simpler replacement for the default TypeScript helper.
* Ignores static members and avoids rollup warnings. */
function __extends(child, parent) {
function helper() { this.constructor = child; }
helper.prototype = parent.prototype;
child.prototype = new helper();
}
var BigComplex = /** @class */ (function () {
function BigComplex(real, imag, base) {
this.real = typeof (real) == 'object' ? real : new this.Base(real, base);
this.imag = typeof (imag) == 'object' ? imag : new this.Base(imag, base);
}
BigComplex.prototype.clone = function () {
var other = new this.constructor(this.real.clone(), this.imag.clone());
return (other);
};
BigComplex.prototype.setZero = function () {
this.real.setZero();
this.imag.setZero();
return (this);
};
BigComplex.prototype.setValue = function (other) {
this.real.setValue(other.real);
this.imag.setValue(other.imag);
return (this);
};
BigComplex.prototype.mul = function (multiplier, product) {
product = product || new this.constructor();
if (multiplier instanceof BigComplex) {
this.real.mul(multiplier.real, this.temp1);
this.imag.mul(multiplier.imag, this.temp2);
this.temp1.sub(this.temp2, product.real);
this.real.mul(multiplier.imag, this.temp1);
this.imag.mul(multiplier.real, this.temp2);
this.temp1.add(this.temp2, product.imag);
}
else {
this.real.mul(multiplier, product.real);
this.imag.mul(multiplier, product.imag);
}
return (product);
};
BigComplex.prototype.sqr = function (product) {
product = product || new this.constructor();
this.real.mul(this.real, this.temp1);
this.imag.mul(this.imag, this.temp2);
this.temp1.sub(this.temp2, product.real);
this.real.mul(this.imag, this.temp1);
this.temp1.add(this.temp1, product.imag);
return (product);
};
BigComplex.prototype.add = function (addend, sum) {
sum = sum || new this.constructor();
if (addend instanceof BigComplex) {
this.real.add(addend.real, sum.real);
this.imag.add(addend.imag, sum.imag);
}
else {
this.real.add(addend, sum.real);
}
return (sum);
};
BigComplex.prototype.sub = function (subtrahend, difference) {
difference = difference || new this.constructor();
if (subtrahend instanceof BigComplex) {
this.real.sub(subtrahend.real, difference.real);
this.imag.sub(subtrahend.imag, difference.imag);
}
else {
this.real.sub(subtrahend, difference.real);
}
return (difference);
};
BigComplex.prototype.truncate = function (fractionLimbCount) {
this.real.truncate(fractionLimbCount);
this.imag.truncate(fractionLimbCount);
return (this);
};
return BigComplex;
}());
var BigComplex32 = /** @class */ (function (_super) {
__extends(BigComplex32, _super);
function BigComplex32() {
return _super !== null && _super.apply(this, arguments) || this;
}
return BigComplex32;
}(BigComplex));
var BigComplex53 = /** @class */ (function (_super) {
__extends(BigComplex53, _super);
function BigComplex53() {
return _super !== null && _super.apply(this, arguments) || this;
}
return BigComplex53;
}(BigComplex));
BigComplex32.prototype.Base = B