js-big-counter
Version:
Big integer/arbitrary-length counter for JavaScript.
1,240 lines (1,166 loc) • 75.6 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define("JSBigCounter", [], factory);
else if(typeof exports === 'object')
exports["JSBigCounter"] = factory();
else
root["JSBigCounter"] = factory();
})((typeof self !== 'undefined' ? self : (typeof global !== 'undefined' ? global : this)), function() {
return /******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/@agrora/decimal/dist/Decimal.js":
/*!******************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/Decimal.js ***!
\******************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const add_1 = __importDefault(__webpack_require__(/*! ./add */ "./node_modules/@agrora/decimal/dist/add.js"));
const common_1 = __webpack_require__(/*! ./common */ "./node_modules/@agrora/decimal/dist/common.js");
const compare_1 = __importDefault(__webpack_require__(/*! ./compare */ "./node_modules/@agrora/decimal/dist/compare.js"));
const divide_1 = __importDefault(__webpack_require__(/*! ./divide */ "./node_modules/@agrora/decimal/dist/divide.js"));
const divideModulo_1 = __importDefault(__webpack_require__(/*! ./divideModulo */ "./node_modules/@agrora/decimal/dist/divideModulo.js"));
const isZero_1 = __importDefault(__webpack_require__(/*! ./isZero */ "./node_modules/@agrora/decimal/dist/isZero.js"));
const max_1 = __importDefault(__webpack_require__(/*! ./max */ "./node_modules/@agrora/decimal/dist/max.js"));
const min_1 = __importDefault(__webpack_require__(/*! ./min */ "./node_modules/@agrora/decimal/dist/min.js"));
const modulo_1 = __importDefault(__webpack_require__(/*! ./modulo */ "./node_modules/@agrora/decimal/dist/modulo.js"));
const multiply_1 = __importDefault(__webpack_require__(/*! ./multiply */ "./node_modules/@agrora/decimal/dist/multiply.js"));
const raise_1 = __importDefault(__webpack_require__(/*! ./raise */ "./node_modules/@agrora/decimal/dist/raise.js"));
const subtract_1 = __importDefault(__webpack_require__(/*! ./subtract */ "./node_modules/@agrora/decimal/dist/subtract.js"));
class Decimal {
constructor(length, scale, value, sign) {
this.length = length;
this.scale = scale;
this.value = value;
this.sign = sign;
}
add(value, scale) {
return Decimal.fromInfo(add_1.default(this, Decimal.from(value), scale));
}
subtract(value, scale) {
return Decimal.fromInfo(subtract_1.default(this, Decimal.from(value), scale));
}
multiply(value, scale) {
return Decimal.fromInfo(multiply_1.default(this, Decimal.from(value), scale));
}
divide(value, scale) {
return Decimal.fromInfo(divide_1.default(this, Decimal.from(value), scale));
}
raise(value, scale) {
return Decimal.fromInfo(raise_1.default(this, Decimal.from(value), scale));
}
modulo(value, scale) {
return Decimal.fromInfo(modulo_1.default(this, Decimal.from(value), scale));
}
divideModulo(value, scale) {
const [quotient, remainder] = divideModulo_1.default(this, Decimal.from(value), scale);
return [Decimal.from(quotient), Decimal.from(remainder)];
}
compareTo(value) {
return compare_1.default(this, Decimal.from(value));
}
isEqualTo(value) {
return this.compareTo(value) === 0;
}
isGreaterThan(value) {
return this.compareTo(value) === 1;
}
isGreaterThanOrEqualTo(value) {
return this.compareTo(value) >= 0;
}
isLowerThan(value) {
return this.compareTo(value) === -1;
}
isLowerThanOrEqualTo(value) {
return this.compareTo(value) <= 0;
}
isZero() {
return isZero_1.default(this);
}
isOne() {
return this.isEqualTo(Decimal.ONE);
}
isMinusOne() {
return this.isEqualTo(Decimal.MINUS_ONE);
}
negate() {
return Decimal.fromInfo(common_1.negate(this));
}
isNegative() {
return this.sign === common_1.DecimalSign.MINUS;
}
isPositive() {
return this.sign === common_1.DecimalSign.PLUS;
}
toString() {
return common_1.createStringFromInfo(this);
}
toInt() {
return parseInt(this.toString(), common_1.DECIMAL_RADIX);
}
toFloat() {
return parseFloat(this.toString());
}
toFixed(scale) {
return common_1.createStringFromInfo(this, scale);
}
static max(...values) {
return Decimal.from(max_1.default(...values.map(Decimal.from)));
}
static min(...values) {
return Decimal.from(min_1.default(...values.map(Decimal.from)));
}
static fromString(decimalString) {
return Decimal.fromInfo(common_1.createInfoFromString(decimalString));
}
static fromInfo(value) {
return new Decimal(value.length, value.scale, value.value, value.sign);
}
static fromNumber(value) {
return Decimal.fromInfo(common_1.createInfoFromString(value.toString(common_1.DECIMAL_RADIX)));
}
static from(value) {
if (value instanceof Decimal) {
return value;
}
if (typeof value === 'string') {
return Decimal.fromString(value);
}
if (typeof value === 'number') {
return Decimal.fromNumber(value);
}
if (common_1.isInfo(value)) {
return Decimal.fromInfo(value);
}
throw Error(`Don't know how to parse value of type ${typeof value} to decimal`);
}
static isDecimal(value) {
return value instanceof Decimal;
}
static isDecimalLike(value) {
return value instanceof Decimal || ['string', 'number'].includes(typeof value) || common_1.isInfo(value);
}
}
Decimal.ZERO = Decimal.fromInfo(common_1.INFO_ZERO);
Decimal.ONE = Decimal.fromInfo(common_1.INFO_ONE);
Decimal.MINUS_ONE = Decimal.fromInfo(common_1.INFO_MINUS_ONE);
exports["default"] = Decimal;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/add.js":
/*!**************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/add.js ***!
\**************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const addUnsigned_1 = __importDefault(__webpack_require__(/*! ./addUnsigned */ "./node_modules/@agrora/decimal/dist/addUnsigned.js"));
const common_1 = __webpack_require__(/*! ./common */ "./node_modules/@agrora/decimal/dist/common.js");
const compare_1 = __importDefault(__webpack_require__(/*! ./compare */ "./node_modules/@agrora/decimal/dist/compare.js"));
const subtractUnsigned_1 = __importDefault(__webpack_require__(/*! ./subtractUnsigned */ "./node_modules/@agrora/decimal/dist/subtractUnsigned.js"));
const { max } = Math;
// bcmath equivalent: bc_add
function add(a, b, scale = max(a.scale, b.scale)) {
let result;
if (a.sign === b.sign) {
result = addUnsigned_1.default(a, b, scale);
result.sign = a.sign;
return result;
}
switch (compare_1.default(a, b, false)) {
case -1:
// n1 is less than n2, subtract n1 from n2.
result = subtractUnsigned_1.default(b, a, scale);
result.sign = b.sign;
break;
case 0:
// They are equal! return zero with the correct scale!
const resultScale = max(scale, max(a.scale, b.scale));
result = common_1.createInfo(1, resultScale);
break;
case 1:
// n2 is less than n1, subtract n2 from n1.
result = subtractUnsigned_1.default(a, b, scale);
result.sign = a.sign;
break;
default:
throw Error('Invalid decimal comparison result');
}
return result;
}
exports["default"] = add;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/addUnsigned.js":
/*!**********************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/addUnsigned.js ***!
\**********************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const common_1 = __webpack_require__(/*! ./common */ "./node_modules/@agrora/decimal/dist/common.js");
const removeLeadingZeroes_1 = __importDefault(__webpack_require__(/*! ./removeLeadingZeroes */ "./node_modules/@agrora/decimal/dist/removeLeadingZeroes.js"));
const { max } = Math;
// bcmath equivalent: _bc_do_add
function addUnsigned(a, b, minScale = 0) {
const maxScale = max(a.scale, b.scale);
const maxLength = max(a.length, b.length) + 1;
const result = common_1.createInfo(maxLength, max(maxScale, minScale));
// Start with the fraction part. Initialize the pointers.
let aLengthLeft = a.scale;
let bLengthLeft = b.scale;
let aPos = (a.length + aLengthLeft - 1);
let bPos = (b.length + bLengthLeft - 1);
let resultPos = (maxScale + maxLength - 1);
// Add the fraction part. First copy the longer fraction
// (ie when adding 1.2345 to 1 we know .2345 is correct already) .
if (aLengthLeft !== bLengthLeft) {
if (aLengthLeft > bLengthLeft) {
// n1 has more dp then n2
for (; aLengthLeft > bLengthLeft; resultPos -= 1, aPos -= 1, aLengthLeft -= 1) {
result.value[resultPos] = a.value[aPos];
}
}
else {
// n2 has more dp then n1
for (; bLengthLeft > aLengthLeft; resultPos -= 1, bPos -= 1, bLengthLeft -= 1) {
result.value[resultPos] = b.value[bPos];
}
}
}
// Now add the remaining fraction part and equal size integer parts.
aLengthLeft += a.length;
bLengthLeft += b.length;
let carry = 0;
let tmp;
for (; aLengthLeft > 0 && bLengthLeft > 0; aPos -= 1, bPos -= 1, resultPos -= 1, aLengthLeft -= 1, bLengthLeft -= 1) {
// add the two numbers together
tmp = a.value[aPos] + b.value[bPos] + carry;
// check if they are >= 10 (impossible to be more then 18)
if (tmp >= common_1.DECIMAL_RADIX) {
carry = 1;
tmp -= common_1.DECIMAL_RADIX; // yep, subtract 10, add a carry
}
else {
carry = 0;
}
result.value[resultPos] = tmp;
}
// Now add carry the [rest of the] longer integer part.
if (aLengthLeft === 0) {
// n2 is a bigger number then n1
for (; bLengthLeft > 0; bLengthLeft -= 1, bPos -= 1, resultPos -= 1) {
tmp = b.value[bPos] + carry;
if (tmp >= common_1.DECIMAL_RADIX) {
carry = 1;
tmp -= common_1.DECIMAL_RADIX;
}
else {
carry = 0;
}
result.value[resultPos] = tmp;
}
}
else {
// n1 is bigger then n2..
for (; aLengthLeft > 0; aLengthLeft -= 1, aPos -= 1, resultPos -= 1) {
tmp = a.value[aPos] + carry;
if (tmp >= common_1.DECIMAL_RADIX) {
carry = 1;
tmp -= common_1.DECIMAL_RADIX;
}
else {
carry = 0;
}
result.value[resultPos] = tmp;
}
}
// Set final carry.
if (carry === 1) {
result.value[resultPos] += 1;
}
return removeLeadingZeroes_1.default(result);
}
exports["default"] = addUnsigned;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/common.js":
/*!*****************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/common.js ***!
\*****************************************************/
/***/ ((__unused_webpack_module, exports) => {
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.DECIMAL_VALIDATION_REGEX = /^[+\-]?\d+(\.\d+)?$/;
exports.DECIMAL_RADIX = 10;
var DecimalSign;
(function (DecimalSign) {
DecimalSign["PLUS"] = "+";
DecimalSign["MINUS"] = "-";
})(DecimalSign = exports.DecimalSign || (exports.DecimalSign = {}));
exports.INFO_ZERO = createInfo();
exports.INFO_ONE = createInfoFromArray([1]);
exports.INFO_MINUS_ONE = negate(createInfoFromArray([1]));
function createInfo(length = 1, scale = 0) {
return { length, scale, sign: DecimalSign.PLUS, value: new Uint8Array(length + scale) };
}
exports.createInfo = createInfo;
function createInfoFromArray(value, length = value.length, scale = value.length - length, offset = 0) {
const info = createInfo(length, scale);
info.value.set(value, offset);
return info;
}
exports.createInfoFromArray = createInfoFromArray;
function createInfoFromString(value) {
if (typeof value !== 'string') {
throw new TypeError(`Invalid ${typeof value} argument passed, string expected`);
}
if (!value.match(exports.DECIMAL_VALIDATION_REGEX)) {
throw Error(`Invalid decimal string ${value} provided`);
}
let normalizedValue = value;
let sign = DecimalSign.PLUS;
const firstChar = value.charAt(0);
if (firstChar === DecimalSign.PLUS || firstChar === DecimalSign.MINUS) {
if (firstChar === DecimalSign.MINUS) {
sign = DecimalSign.MINUS;
}
normalizedValue = normalizedValue.substr(1);
}
normalizedValue = normalizedValue.replace(/^0+([0-9])/, '$1');
const dotIndex = normalizedValue.indexOf('.');
let length = normalizedValue.length;
let scale = 0;
if (dotIndex !== -1) {
scale = length - (dotIndex + 1);
length -= (scale + 1);
normalizedValue = normalizedValue.replace('.', '');
}
return Object.assign({}, createInfoFromArray(normalizedValue.split('').map(c => parseInt(c, exports.DECIMAL_RADIX)), length, scale), { sign });
}
exports.createInfoFromString = createInfoFromString;
function createStringFromInfo(info, scale = info.scale) {
let str = info.value.subarray(0, info.length).join('');
if (scale > 0) {
str += `.${info.value.subarray(info.length, info.length + scale).join('')}`;
}
return (info.sign === DecimalSign.MINUS ? DecimalSign.MINUS : '') + str;
}
exports.createStringFromInfo = createStringFromInfo;
// bcmath equivalent: new_sub_num
function createSubInfo(info, length = info.length, scale = info.scale, offset = 0, targetOffset = 0) {
return createInfoFromArray(info.value.subarray(offset), length, scale, targetOffset);
}
exports.createSubInfo = createSubInfo;
function copyInfo(info) {
return {
sign: info.sign,
length: info.length,
scale: info.scale,
value: new Uint8Array(info.value),
};
}
exports.copyInfo = copyInfo;
function isInfo(value) {
return typeof value === 'object'
&& value !== null
&& typeof value.length === 'number'
&& typeof value.scale === 'number'
&& (typeof value.sign === 'string' && [DecimalSign.PLUS, DecimalSign.MINUS].includes(value.sign))
&& (typeof value.value === 'object' && value.value instanceof Uint8Array);
}
exports.isInfo = isInfo;
function negate(info) {
return Object.assign({}, info, { sign: info.sign === DecimalSign.PLUS ? DecimalSign.MINUS : DecimalSign.PLUS });
}
exports.negate = negate;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/compare.js":
/*!******************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/compare.js ***!
\******************************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
Object.defineProperty(exports, "__esModule", ({ value: true }));
const common_1 = __webpack_require__(/*! ./common */ "./node_modules/@agrora/decimal/dist/common.js");
const { min } = Math;
function compare(a, b, useSign = true, ignoreLast = false) {
// First, compare signs.
if (useSign && a.sign !== b.sign) {
return a.sign === common_1.DecimalSign.PLUS ? 1 : -1;
}
// Now compare the magnitude.
if (a.length !== b.length) {
if (a.length > b.length) { // Magnitude of n1 > n2.
return !useSign || a.sign === common_1.DecimalSign.PLUS ? 1 : -1;
}
return !useSign || a.sign === common_1.DecimalSign.PLUS ? -1 : 1;
}
/* If we get here, they have the same number of integer digits.
check the integer part and the equal length part of the fraction. */
let count = a.length + min(a.scale, b.scale);
let aPos = 0;
let bPos = 0;
while ((count > 0) && (a.value[aPos] === b.value[bPos])) {
aPos += 1;
bPos += 1;
count -= 1;
}
if (ignoreLast && (count === 1) && (a.scale === b.scale)) {
return 0;
}
if (count !== 0) {
if (a.value[aPos] > b.value[bPos]) { // Magnitude of n1 > n2.
return !useSign || a.sign === common_1.DecimalSign.PLUS ? 1 : -1;
}
return !useSign || a.sign === common_1.DecimalSign.PLUS ? -1 : 1;
}
// They are equal up to the last part of the equal part of the fraction.
if (a.scale !== b.scale) {
if (a.scale > b.scale) {
for (count = (a.scale - b.scale); count > 0; count -= 1, aPos += 1) {
if (a.value[aPos] !== 0) { // Magnitude of n1 > n2.
return !useSign || a.sign === common_1.DecimalSign.PLUS ? 1 : -1;
}
}
}
else {
for (count = (b.scale - a.scale); count > 0; count -= 1, bPos += 1) {
if (b.value[bPos] !== 0) { // Magnitude of n1 < n2.
return !useSign || a.sign === common_1.DecimalSign.PLUS ? -1 : 1;
}
}
}
}
// They must be equal!
return 0;
}
exports["default"] = compare;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/divide.js":
/*!*****************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/divide.js ***!
\*****************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const common_1 = __webpack_require__(/*! ./common */ "./node_modules/@agrora/decimal/dist/common.js");
const compare_1 = __importDefault(__webpack_require__(/*! ./compare */ "./node_modules/@agrora/decimal/dist/compare.js"));
const isZero_1 = __importDefault(__webpack_require__(/*! ./isZero */ "./node_modules/@agrora/decimal/dist/isZero.js"));
const removeLeadingZeroes_1 = __importDefault(__webpack_require__(/*! ./removeLeadingZeroes */ "./node_modules/@agrora/decimal/dist/removeLeadingZeroes.js"));
const { min, max, floor } = Math;
// bcmath equivalent: bc_div
function divide(a, b, scale = max(a.scale, b.scale)) {
// var ptrs // return object from one_mul
// Test for divide by zero. (return failure)
if (isZero_1.default(b)) {
throw Error('Division by zero');
}
// Test for zero divide by anything (return zero)
if (isZero_1.default(a)) {
return common_1.createInfo(1, scale);
}
if (compare_1.default(a, b) === 0) {
return common_1.createInfoFromArray([1], 1, scale);
}
let qval;
// Test for divide by 1. If it is we must truncate.
// @todo: check where scale > 0 too.. can't see why not
// (ie bc_is_zero - add bc_is_one function)
if (b.scale === 0) {
if (b.length === 1 && b.value[0] === 1) {
qval = common_1.createInfo(a.length, scale);
qval.sign = (a.sign === b.sign ? common_1.DecimalSign.PLUS : common_1.DecimalSign.MINUS);
qval.value.fill(0, a.length, a.length + scale);
qval.value.set(a.value.subarray(a.length + min(a.scale, scale)));
return qval;
}
}
/* Set up the divide. Move the decimal point on n1 by n2's scale.
Remember, zeros on the end of num2 are wasted effort for dividing. */
let scale2 = b.scale;
let aPos = b.length + scale2 - 1;
for (; (scale2 > 0) && (b.value[aPos] === 0); aPos -= 1) {
scale2 -= 1;
}
const len1 = a.length + scale2;
const scale1 = a.scale - scale2;
const extra = scale1 < scale ? scale - scale1 : 0;
const num1 = new Uint8Array(a.length + a.scale + extra + 2).fill(0);
num1.set(a.value, 1);
let len2 = b.length + scale2;
const num2 = new Uint8Array(len2 + 1);
num2.set(b.value);
// num2[len2] = 0; // will always be 0
aPos = 0;
while (num2[aPos] === 0) {
aPos += 1;
len2 -= 1;
}
let zero;
let qdigits;
// Calculate the number of quotient digits.
if (len2 > len1 + scale) {
qdigits = scale + 1;
zero = true;
}
else {
zero = false;
if (len2 > len1) {
qdigits = scale + 1; // One for the zero integer part.
}
else {
qdigits = len1 - len2 + scale + 1;
}
}
// Allocate and zero the storage for the quotient.
// qval = bc_new_num (qdigits-scale,scale);
qval = common_1.createInfo(qdigits - scale, scale);
const mval = new Uint8Array(len2 + 1);
// TODO: Create a backup of b to restore later, oneMult right now modifies it
const bBackup = common_1.copyInfo(b);
// Now for the full divide algorithm.
if (!zero) { // Normalize
// norm = Libbcmath.cint(10 / (Libbcmath.cint(n2.n_value[n2ptr]) + 1));
// norm = 10 / ((int)*n2ptr + 1)
const norm = floor(10 / (b.value[aPos] + 1));
if (norm !== 1) {
oneMult(num1, 0, len1 + scale1 + extra + 1, norm, num1, 0);
// Libbcmath._one_mult(n2ptr, len2, norm, n2ptr);
oneMult(b.value, aPos, len2, norm, b.value, aPos);
// TODO: b.value is modified after this call, that's why we use the bBackup workaround until it's fixed
}
// Initialize divide loop.
let qdig = 0;
let qptr = len2 > len1 ? len2 - len1 : 0;
// Loop
while (qdig <= len1 + scale - len2) { // Calculate the quotient digit guess.
let qguess;
if (b.value[aPos] === num1[qdig]) {
qguess = 9;
}
else {
qguess = floor((num1[qdig] * 10 + num1[qdig + 1]) / b.value[aPos]);
}
// Test qguess.
if (b.value[aPos + 1] * qguess
> (num1[qdig] * 10 + num1[qdig + 1] - b.value[aPos] * qguess) * 10 + num1[qdig + 2]) {
qguess -= 1;
// And again.
if (b.value[aPos + 1] * qguess
> (num1[qdig] * 10 + num1[qdig + 1] - b.value[aPos] * qguess) * 10 + num1[qdig + 2]) {
qguess -= 1;
}
}
// Multiply and subtract.
let borrow = 0;
if (qguess !== 0) {
mval[0] = 0; // * mval = 0; // @CHECK is this to fix ptr2 < 0?
// _one_mult (n2ptr, len2, qguess, mval+1); // @CHECK
oneMult(b.value, aPos, len2, qguess, mval, 1);
let ptr1 = qdig + len2; // (unsigned char *) num1+qdig+len2;
let ptr2 = len2; // (unsigned char *) mval+len2;
// @todo: CHECK: Does a negative pointer return null?
// ptr2 can be < 0 here as ptr1 = len2, thus count < len2+1 will always fail ?
for (let count = 0; count < len2 + 1; count += 1, ptr1 -= 1) {
let val;
if (ptr2 < 0) {
// val = Libbcmath.cint(num1[ptr1]) - 0 - borrow;
// val = (int) *ptr1 - (int) *ptr2-- - borrow;
val = num1[ptr1] - borrow; // val = (int) *ptr1 - (int) *ptr2-- - borrow;
}
else {
// val = Libbcmath.cint(num1[ptr1]) - Libbcmath.cint(mval[ptr2--]) - borrow;
// val = (int) *ptr1 - (int) *ptr2-- - borrow;
// val = (int) *ptr1 - (int) *ptr2-- - borrow;
val = num1[ptr1] - mval[ptr2] - borrow;
ptr2 -= 1;
}
if (val < 0) {
val += 10;
borrow = 1;
}
else {
borrow = 0;
}
num1[ptr1] = val;
}
}
// Test for negative result.
if (borrow === 1) {
qguess -= 1;
let ptr1 = qdig + len2; // (unsigned char *) num1+qdig+len2;
let ptr2 = len2 - 1; // (unsigned char *) n2ptr+len2-1;
let carry = 0;
for (let count = 0; count < len2; count += 1, ptr1 -= 1) {
let val;
if (ptr2 < 0) {
// val = Libbcmath.cint(num1[ptr1]) + 0 + carry;
// val = (int) *ptr1 + (int) *ptr2-- + carry;
// val = (int) *ptr1 + (int) *ptr2-- + carry;
val = num1[ptr1] + carry;
}
else {
// val = Libbcmath.cint(num1[ptr1]) + Libbcmath.cint(n2.n_value[ptr2--]) + carry;
// val = (int) *ptr1 + (int) *ptr2-- + carry;
// val = (int) *ptr1 + (int) *ptr2-- + carry;
val = num1[ptr1] + b.value[ptr2] + carry;
ptr2 -= 1;
}
if (val > 9) {
val -= 10;
carry = 1;
}
else {
carry = 0;
}
num1[ptr1] = val; // * ptr1-- = val;
}
if (carry === 1) {
// num1[ptr1] = Libbcmath.cint((num1[ptr1] + 1) % 10);
// *ptr1 = (*ptr1 + 1) % 10; // @CHECK
// *ptr1 = (*ptr1 + 1) % 10; // @CHECK
num1[ptr1] = (num1[ptr1] + 1) % 10;
}
}
// We now know the quotient digit.
qval.value[qptr] = qguess; // * qptr++ = qguess;
qptr += 1;
qdig += 1;
}
}
// Clean up and return the number.
qval.sign = (a.sign === b.sign ? common_1.DecimalSign.PLUS : common_1.DecimalSign.MINUS);
if (isZero_1.default(qval)) {
qval.sign = common_1.DecimalSign.PLUS;
}
// TODO: This is part of our bBackup prodecure above
Object.assign(b, bBackup);
return removeLeadingZeroes_1.default(qval);
}
exports["default"] = divide;
/**
* We don't export this one as I essentially don't exactly know what it's for yet.
*
* @param num
* @param nPtr
* @param size
* @param digit
* @param result
* @param rPtr
*/
function oneMult(num, nPtr, size, digit, result, rPtr) {
if (digit === 0) {
result.fill(0, 0, size);
return;
}
if (digit === 1) {
result.set(num.subarray(nPtr, nPtr + size), rPtr);
return;
}
let nptr = nPtr + size - 1;
let rptr = rPtr + size - 1;
let carry;
let value;
carry = 0;
let i = size;
for (; i > 0; i -= 1, nptr -= 1, rptr -= 1) {
value = num[nptr] * digit + carry;
result[rptr] = value % common_1.DECIMAL_RADIX;
carry = floor(value / common_1.DECIMAL_RADIX);
}
if (carry !== 0) {
result[rptr] = carry;
}
}
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/divideModulo.js":
/*!***********************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/divideModulo.js ***!
\***********************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const common_1 = __webpack_require__(/*! ./common */ "./node_modules/@agrora/decimal/dist/common.js");
const divide_1 = __importDefault(__webpack_require__(/*! ./divide */ "./node_modules/@agrora/decimal/dist/divide.js"));
const isZero_1 = __importDefault(__webpack_require__(/*! ./isZero */ "./node_modules/@agrora/decimal/dist/isZero.js"));
const max_1 = __importDefault(__webpack_require__(/*! ./max */ "./node_modules/@agrora/decimal/dist/max.js"));
const multiply_1 = __importDefault(__webpack_require__(/*! ./multiply */ "./node_modules/@agrora/decimal/dist/multiply.js"));
const subtract_1 = __importDefault(__webpack_require__(/*! ./subtract */ "./node_modules/@agrora/decimal/dist/subtract.js"));
// bcmath equivalent: bc_divmod
/**
* Division *and* modulo for numbers. This computes both NUM1 / NUM2 and
* NUM1 % NUM2 and puts the results in QUOT and REM, except that if QUOT
* is NULL then that store will be omitted.
*/
function divideModulo(num1, num2, scale = Math.max(num1.scale, num2.scale)) {
if (isZero_1.default(num2)) {
throw Error('Division by zero');
}
/* Calculate final scale. */
const resultScale = Math.max(num1.scale, num2.scale + scale);
/* Calculate it. */
const quotient = divide_1.default(num1, num2, 0);
const temp = multiply_1.default(quotient, num2, resultScale);
const remainder = subtract_1.default(num1, temp, resultScale);
return [quotient, max_1.default(remainder, common_1.INFO_ZERO)];
}
exports["default"] = divideModulo;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/index.js":
/*!****************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/index.js ***!
\****************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const add_1 = __importDefault(__webpack_require__(/*! ./add */ "./node_modules/@agrora/decimal/dist/add.js"));
exports.add = add_1.default;
const addUnsigned_1 = __importDefault(__webpack_require__(/*! ./addUnsigned */ "./node_modules/@agrora/decimal/dist/addUnsigned.js"));
exports.addUnsigned = addUnsigned_1.default;
const common_1 = __webpack_require__(/*! ./common */ "./node_modules/@agrora/decimal/dist/common.js");
exports.copyInfo = common_1.copyInfo;
exports.createInfo = common_1.createInfo;
exports.createInfoFromArray = common_1.createInfoFromArray;
exports.createInfoFromString = common_1.createInfoFromString;
exports.createStringFromInfo = common_1.createStringFromInfo;
exports.createSubInfo = common_1.createSubInfo;
const compare_1 = __importDefault(__webpack_require__(/*! ./compare */ "./node_modules/@agrora/decimal/dist/compare.js"));
exports.compare = compare_1.default;
const Decimal_1 = __importDefault(__webpack_require__(/*! ./Decimal */ "./node_modules/@agrora/decimal/dist/Decimal.js"));
const divide_1 = __importDefault(__webpack_require__(/*! ./divide */ "./node_modules/@agrora/decimal/dist/divide.js"));
exports.divide = divide_1.default;
const isZero_1 = __importDefault(__webpack_require__(/*! ./isZero */ "./node_modules/@agrora/decimal/dist/isZero.js"));
exports.isZero = isZero_1.default;
const multiply_1 = __importDefault(__webpack_require__(/*! ./multiply */ "./node_modules/@agrora/decimal/dist/multiply.js"));
exports.multiply = multiply_1.default;
const removeLeadingZeroes_1 = __importDefault(__webpack_require__(/*! ./removeLeadingZeroes */ "./node_modules/@agrora/decimal/dist/removeLeadingZeroes.js"));
exports.removeLeadingZeroes = removeLeadingZeroes_1.default;
const subtract_1 = __importDefault(__webpack_require__(/*! ./subtract */ "./node_modules/@agrora/decimal/dist/subtract.js"));
exports.subtract = subtract_1.default;
const subtractUnsigned_1 = __importDefault(__webpack_require__(/*! ./subtractUnsigned */ "./node_modules/@agrora/decimal/dist/subtractUnsigned.js"));
exports.subtractUnsigned = subtractUnsigned_1.default;
exports["default"] = Decimal_1.default;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/isZero.js":
/*!*****************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/isZero.js ***!
\*****************************************************/
/***/ ((__unused_webpack_module, exports) => {
Object.defineProperty(exports, "__esModule", ({ value: true }));
function isZero(a) {
const length = a.length + a.scale;
for (let i = 0; i < length; i += 1) {
if (a.value[i] !== 0) {
return false;
}
}
return true;
}
exports["default"] = isZero;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/max.js":
/*!**************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/max.js ***!
\**************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const compare_1 = __importDefault(__webpack_require__(/*! ./compare */ "./node_modules/@agrora/decimal/dist/compare.js"));
function max(...values) {
if (values.length < 2) {
throw Error('At least two values must be given');
}
if (values.length === 2) {
return compare_1.default(values[0], values[1]) === 1 ? values[0] : values[1];
}
values.sort(compare_1.default);
return values[values.length - 1];
}
exports["default"] = max;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/min.js":
/*!**************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/min.js ***!
\**************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const compare_1 = __importDefault(__webpack_require__(/*! ./compare */ "./node_modules/@agrora/decimal/dist/compare.js"));
function min(...values) {
if (values.length < 2) {
throw Error('At least two values must be given');
}
if (values.length === 2) {
return compare_1.default(values[0], values[1]) === 1 ? values[1] : values[0];
}
values.sort(compare_1.default);
return values[0];
}
exports["default"] = min;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/modulo.js":
/*!*****************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/modulo.js ***!
\*****************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const divideModulo_1 = __importDefault(__webpack_require__(/*! ./divideModulo */ "./node_modules/@agrora/decimal/dist/divideModulo.js"));
// bcmath equivalent: bc_mod
/**
* Division *and* modulo for numbers. This computes both NUM1 / NUM2 and
* NUM1 % NUM2 and puts the results in QUOT and REM, except that if QUOT
* is NULL then that store will be omitted.
*/
const { max } = Math;
function modulo(a, b, scale = max(a.scale, b.scale)) {
return divideModulo_1.default(a, b, scale)[1];
}
exports["default"] = modulo;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/multiply.js":
/*!*******************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/multiply.js ***!
\*******************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const common_1 = __webpack_require__(/*! ./common */ "./node_modules/@agrora/decimal/dist/common.js");
const isZero_1 = __importDefault(__webpack_require__(/*! ./isZero */ "./node_modules/@agrora/decimal/dist/isZero.js"));
const removeLeadingZeroes_1 = __importDefault(__webpack_require__(/*! ./removeLeadingZeroes */ "./node_modules/@agrora/decimal/dist/removeLeadingZeroes.js"));
const subtract_1 = __importDefault(__webpack_require__(/*! ./subtract */ "./node_modules/@agrora/decimal/dist/subtract.js"));
const { min, max, floor } = Math;
const MULTIPLY_BASE_DIGITS = 80;
const MULTIPLY_SMALL_DIGITS = 80 / 4;
function multiply(a, b, scale = max(a.scale, b.scale)) {
// Initialize things.
const aSize = a.length + a.scale;
const bSize = b.length + b.scale;
const fullScale = a.scale + b.scale;
const productScale = min(scale, fullScale);
let product = multiplyRecursive(a, aSize, b, bSize, fullScale);
// Assign to prod and clean up the number.
product.sign = (a.sign === b.sign ? common_1.DecimalSign.PLUS : common_1.DecimalSign.MINUS);
product.length = bSize + aSize + 1 - fullScale;
product.scale = productScale;
// Make sure value fits configured size
if (product.scale < product.value.length) {
product.value = product.value.subarray(0, product.length + product.scale);
}
product = removeLeadingZeroes_1.default(product);
if (isZero_1.default(product)) {
product.sign = common_1.DecimalSign.PLUS;
}
return product;
}
exports["default"] = multiply;
// bcmath equivalent: _bc_simp_mul
function multiplySimple(a, aLength, b, bLength,
// @ts-ignore
fullScale = 0) {
const productLength = aLength + bLength + 1;
const product = common_1.createInfo(productLength);
const aEnd = aLength - 1;
const bEnd = bLength - 1;
let productPos = productLength - 1;
let sum = 0;
let aPos;
let bPos;
for (let i = 0; i < productLength - 1; i += 1, productPos -= 1) {
aPos = aEnd - max(0, i - bLength + 1);
bPos = bEnd - min(i, bLength - 1);
for (; (aPos >= 0) && (bPos <= bEnd); aPos -= 1, bPos += 1) {
sum += a.value[aPos] * b.value[bPos];
}
product.value[productPos] = floor(sum % common_1.DECIMAL_RADIX);
sum = floor(sum / common_1.DECIMAL_RADIX);
}
product.value[productPos] = sum;
return product;
}
exports.multiplySimple = multiplySimple;
// bcmath equivalent: _bc_rec_mul
/**
* Recursive divide and conquer multiply algorithm.
* based on
* Let u = u0 + u1*(b^n)
* Let v = v0 + v1*(b^n)
* Then uv = (B^2n+B^n)*u1*v1 + B^n*(u1-u0)*(v0-v1) + (B^n+1)*u0*v0
*
* B is the base of storage, number of digits in u1,u0 close to equal.
*
* @param a
* @param aLength
* @param b
* @param bLength
* @param fullScale
*/
function multiplyRecursive(a, aLength, b, bLength, fullScale = 0) {
// Base case?
if ((aLength + bLength) < MULTIPLY_BASE_DIGITS ||
aLength < MULTIPLY_SMALL_DIGITS ||
bLength < MULTIPLY_SMALL_DIGITS) {
return multiplySimple(a, aLength, b, bLength, fullScale);
}
// Calculate n -- the u and v split point in digits.
const n = floor((max(aLength, bLength) + 1) / 2);
let a0;
let a1;
let b0;
let b1;
// Split a and b
if (aLength < n) {
a1 = common_1.createInfo();
a0 = common_1.createSubInfo(a, aLength, 0);
}
else {
a1 = common_1.createSubInfo(a, aLength - n, 0);
a0 = common_1.createSubInfo(a, n, 0, aLength - n);
}
if (bLength < n) {
b1 = common_1.createInfo();
b0 = common_1.createSubInfo(b, bLength, 0);
}
else {
b1 = common_1.createSubInfo(b, bLength - n, 0);
b0 = common_1.createSubInfo(b, n, 0, bLength - n);
}
a1 = removeLeadingZeroes_1.default(a1);
a0 = removeLeadingZeroes_1.default(a0);
b1 = removeLeadingZeroes_1.default(b1);
b0 = removeLeadingZeroes_1.default(b0);
const m1Zero = isZero_1.default(a1) || isZero_1.default(b1);
// Calculate sub results ...
const d1 = subtract_1.default(a1, a0);
const d1Length = d1.length;
const d2 = subtract_1.default(b0, b1);
const d2Length = d2.length;
let m1;
let m2;
let m3;
// Do recursive multiplies and shifted adds.
if (m1Zero) {
m1 = common_1.createInfo();
}
else {
// m1 = Libbcmath.bc_init_num(); //allow pass-by-ref
m1 = multiplyRecursive(a1, a1.length, b1, b1.length);
}
if (isZero_1.default(d1) || isZero_1.default(d2)) {
m2 = common_1.createInfo();
}
else {
// m2 = Libbcmath.bc_init_num(); //allow pass-by-ref
m2 = multiplyRecursive(d1, d1Length, d2, d2Length);
}
if (isZero_1.default(a0) || isZero_1.default(b0)) {
m3 = common_1.createInfo();
}
else {
// m3 = Libbcmath.bc_init_num(); //allow pass-by-ref
m3 = multiplyRecursive(a0, a0.length, b0, b0.length);
}
// Initialize product
const productLength = aLength + bLength + 1;
let product = common_1.createInfo(productLength);
if (!m1Zero) {
product = shiftAddSubtract(product, m1, 2 * n);
product = shiftAddSubtract(product, m1, n);
}
product = shiftAddSubtract(product, m3, n);
product = shiftAddSubtract(product, m3, 0);
product = shiftAddSubtract(product, m2, n, d1.sign !== d2.sign);
return product;
}
exports.multiplyRecursive = multiplyRecursive;
// bcmath equivalent: _bc_shift_addsub
/**
* A special adder/subtractor for the recursive divide and conquer
* multiply algorithm. Note: if sub is called, accum must
* be larger that what is being subtracted. Also, accum and val
* must have n_scale = 0. (e.g. they must look like integers.
*
* @param accumulator
* @param info
* @param shift
* @param sub
*/
function shiftAddSubtract(accumulator, info, shift, sub = false) {
const accum = common_1.copyInfo(accumulator);
let count = info.length;
if (info.value[0] === 0) {
count -= 1;
}
if (accum.length + accum.scale < shift + count) {
throw Error('len + scale < shift + count');
}
// Set up pointers and others
// (signed char *)(accum->n_value + accum->n_len + accum->n_scale - shift - 1);
let accPos = accum.length + accum.scale - shift - 1;
let infoPos = info.length - 1; // (signed char *)(val->n_value + val->n_len - 1);
let carry = 0;
if (sub) {
// Subtraction, carry is really borrow.
for (; count >= 0; count -= 1, infoPos -= 1, accPos -= 1) {
accum.value[accPos] -= info.value[infoPos] + carry;
if (accum.value[accPos] < 0) {
carry = 1;
accum.value[accPos] += common_1.DECIMAL_RADIX;
}
else {
carry = 0;
}
}
for (; carry; accPos -= 1) {
accum.value[accPos] -= carry;
if (accum.value[accPos] < 0) {
accum.value[accPos] += common_1.DECIMAL_RADIX;
}
else {
carry = 0;
}
}
}
else {
// Addition
for (; count >= 0; count -= 1, infoPos -= 1, accPos -= 1) {
accum.value[accPos] += info.value[infoPos] + carry;
if (accum.value[accPos] > (common_1.DECIMAL_RADIX - 1)) {
carry = 1;
accum.value[accPos] -= common_1.DECIMAL_RADIX;
}
else {
carry = 0;
}
}
for (; carry; accPos -= 1) {
accum.value[accPos] += carry;
if (accum.value[accPos] > (common_1.DECIMAL_RADIX - 1)) { // if (*accp > (BASE-1))
accum.value[accPos] -= common_1.DECIMAL_RADIX;
}
else {
carry = 0;
}
}
}
return accum;
}
exports.shiftAddSubtract = shiftAddSubtract;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/raise.js":
/*!****************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/raise.js ***!
\****************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const common_1 = __webpack_require__(/*! ./common */ "./node_modules/@agrora/decimal/dist/common.js");
const divide_1 = __importDefault(__webpack_require__(/*! ./divide */ "./node_modules/@agrora/decimal/dist/divide.js"));
const multiply_1 = __importDefault(__webpack_require__(/*! ./multiply */ "./node_modules/@agrora/decimal/dist/multiply.js"));
const { min, max } = Math;
// bcmath equivalent: bc_raise
/**
* Raise NUM1 to the NUM2 power. The result is placed in RESULT.
* Maximum exponent is LONG_MAX. If a NUM2 is not an integer,
* only the integer part is used.
*/
function raise(a, b, scale = max(a.scale, b.scale)) {
/* Check the exponent for scale digits and convert to a long. */
if (b.scale > 0) {
throw Error('Trying to build power with non-integral exponent');
}
let exponent = parseInt(common_1.createStringFromInfo(b), common_1.DECIMAL_RADIX);
if (isNaN(exponent) || (exponent === 0 && (b.length > 1 || b.value[0] !== 0))) {
throw Error('Exponent too large in raise');
}
/* Special case if exponent is a zero. */
if (exponent === 0) {
return common_1.createInfoFromArray([1], scale);
}
let neg;
let rscale;
/* Other initializations. */
if (exponent < 0) {
neg = true;
exponent = -exponent;
rscale = scale;
}
else {
neg = false;
rscale = min(a.scale * exponent, max(scale, a.scale));
}
/* Set initial value of temp. */
let power = common_1.copyInfo(a);
let pwrscale = a.scale;
while ((exponent & 1) === 0) {
pwrscale = 2 * pwrscale;
power = multiply_1.default(power, power, pwrscale);
exponent = exponent >> 1;
}
let temp = common_1.copyInfo(power);
let calcscale = pwrscale;
exponent = exponent >> 1;
/* Do the calculation. */
while (exponent > 0) {
pwrscale = 2 * pwrscale;
power = multiply_1.default(power, power, pwrscale);
if ((exponent & 1) === 1) {
calcscale = pwrscale + calcscale;
temp = multiply_1.default(temp, power, calcscale);
}
exponent = exponent >> 1;
}
let result;
/* Assign the value. */
if (neg) {
result = divide_1.default(common_1.INFO_ONE, temp, rscale);
}
else {
result = temp;
if (result.scale > rscale) {
result.scale = rscale;
if (result.value.length > result.length + result.scale) {
result.value = result.value.subarray(0, result.length + result.scale);
}
}
}
return result;
}
exports["default"] = raise;
/***/ }),
/***/ "./node_modules/@agrora/decimal/dist/removeLeadingZeroes.js":
/*!******************************************************************!*\
!*** ./node_modules/@agrora/decimal/dist/removeLeadingZeroes.js ***!
\******************************************************************/
/***/ ((__unused_webpack_module, exports) => {
Object.defineProperty(exports, "__esModule", ({ value: true }));
// bcmath equivalent: _bc_rm_leading_zeros
function removeLeadingZeroes(info) {
let zeroCount = 0;
while ((info.value[zeroCount] === 0) && (info.length - zeroCount > 1)) {
zeroCount += 1;
}
if (zeroCount > 0) {
return {
length: info.length - zeroCount,