@yaffle/bigdecimal
Advanced tools
Comparing version 1.0.26 to 1.0.27
@@ -85,6 +85,7 @@ /*jslint bigint: true, vars: true, indent: 2*/ | ||
BigDecimal.toNumber = function (a) { | ||
return Number(BigDecimal.toBigInt(a)); | ||
return Number(BigInt(BigDecimal.toBigInt(a))); | ||
}; | ||
BigDecimal.toBigInt = function (a) { | ||
const exponent = Number(a.exponent); | ||
const e = a.exponent; | ||
const exponent = typeof e === 'number' ? e : Number(BigInt(e)); | ||
if (exponent === 0) { | ||
@@ -94,4 +95,4 @@ return a.significand; | ||
if (exponent < 0) { | ||
const result = bigIntUnscale(a.significand, -exponent); | ||
if (bigIntScale(result, -exponent) !== a.significand) { | ||
const result = bigIntUnscale(a.significand, 0 - exponent); | ||
if (bigIntScale(result, 0 - exponent) !== BigInt(a.significand)) { | ||
throw new RangeError("The BigDecimal " + a.toString() + " cannot be converted to a BigInt because it is not an integer"); | ||
@@ -106,10 +107,10 @@ } | ||
} | ||
function bigIntMax(a, b) { | ||
return a < b ? b : a; | ||
} | ||
function bigIntMin(a, b) { | ||
return a < b ? a : b; | ||
} | ||
//function bigIntMax(a, b) { | ||
// return a < b ? b : a; | ||
//} | ||
//function bigIntMin(a, b) { | ||
// return a < b ? a : b; | ||
//} | ||
function bigIntAbs(a) { | ||
return a < 0n ? -a : a; | ||
return a < 0n ? 0n - a : a; | ||
} | ||
@@ -121,3 +122,3 @@ // https://github.com/tc39/proposal-bigint/issues/205 | ||
const s = a.toString(16); | ||
const c = s.charCodeAt(0) - "0".charCodeAt(0); | ||
const c = +s.charCodeAt(0) - "0".charCodeAt(0); | ||
if (c <= 0) { | ||
@@ -138,3 +139,3 @@ throw new RangeError(); | ||
} | ||
const number = Number(a); | ||
const number = Number(BigInt(a)); | ||
if (number < (Number.MAX_SAFE_INTEGER + 1) / 16) { | ||
@@ -149,3 +150,3 @@ return Math.floor(Math.log2(number + 0.5) / Math.log2(BASE)) + 1; | ||
const i = Math.floor(e + 0.5); | ||
return a >= cachedPower(i) ? i + 1 : i; | ||
return a >= BigInt(cachedPower(i)) ? i + 1 : i; | ||
} | ||
@@ -155,3 +156,3 @@ function sum(a, b) { | ||
const value = a + b; | ||
if (value >= -Number.MAX_SAFE_INTEGER && value <= +Number.MAX_SAFE_INTEGER) { | ||
if (Math.abs(value) <= +Number.MAX_SAFE_INTEGER) { | ||
return value; | ||
@@ -162,3 +163,3 @@ } | ||
const nv = Number(v); | ||
if (nv >= -Number.MAX_SAFE_INTEGER && nv <= +Number.MAX_SAFE_INTEGER) { | ||
if (Math.abs(nv) <= +Number.MAX_SAFE_INTEGER) { | ||
return nv; | ||
@@ -169,3 +170,3 @@ } | ||
function diff(a, b) { | ||
return sum(a, -b); | ||
return sum(a, typeof b === 'number' ? 0 - b : -BigInt(b)); | ||
} | ||
@@ -217,6 +218,7 @@ const E = Math.ceil(0.5 * Math.log2(Number.MAX_SAFE_INTEGER + 1) / Math.log2(BASE) - 1); | ||
}); | ||
function round(a, rounding) { | ||
if (rounding != null) { | ||
let k = 0; | ||
const dividend = a.significand; | ||
const dividend = BigInt(a.significand); | ||
const exponent = a.exponent; | ||
@@ -238,3 +240,3 @@ const maximumSignificantDigits = rounding.maximumSignificantDigits; | ||
} | ||
k = 0 - Number(sum(exponent, maximumFractionDigits)); | ||
k = 0 - sum(exponent, maximumFractionDigits); | ||
//k = Math.min(k, digits(a.significand) + 1); | ||
@@ -296,28 +298,33 @@ //if (k < 0 && k >= -1024 && BASE === 2) { | ||
BigDecimal.unaryMinus = function (a) { | ||
return create(-a.significand, a.exponent); | ||
return create(-BigInt(a.significand), a.exponent); | ||
}; | ||
BigDecimal.add = function (a, b, rounding = null) { | ||
const bd = diff(a.exponent, b.exponent); | ||
const d = Number(bd); | ||
const as = BigInt(a.significand); | ||
const bs = BigInt(b.significand); | ||
const ae = a.exponent; | ||
const be = b.exponent; | ||
const bd = diff(ae, be); | ||
const d = typeof bd === 'number' ? bd : Number(BigInt(bd)); | ||
if (d !== 0) { // optimization | ||
if (a.significand === 0n) { | ||
if (as === 0n) { | ||
return round(b, rounding); | ||
} | ||
if (b.significand === 0n) { | ||
if (bs === 0n) { | ||
return round(a, rounding); | ||
} | ||
const msdp1 = rounding != null ? rounding.maximumSignificantDigits + 1 : 0; | ||
if (d > 0) { | ||
if (rounding != null && rounding.maximumSignificantDigits != null && d > digits(b.significand) + (rounding.maximumSignificantDigits + 1)) { | ||
return round(create(bigIntScale(a.significand, rounding.maximumSignificantDigits + 1) + (b.significand < 0n ? -1n : 1n), diff(a.exponent, rounding.maximumSignificantDigits + 1)), rounding); | ||
if (msdp1 !== 0 && d > digits(bs) + msdp1) { | ||
return round(create(bigIntScale(as, msdp1) + (bs < 0n ? -1n : 1n), diff(ae, msdp1)), rounding); | ||
} | ||
return round(create(bigIntScale(a.significand, bd) + b.significand, b.exponent), rounding); | ||
return round(create(bigIntScale(as, d) + bs, be), rounding); | ||
} | ||
if (d < 0) { | ||
if (rounding != null && rounding.maximumSignificantDigits != null && 0 - d > digits(a.significand) + (rounding.maximumSignificantDigits + 1)) { | ||
return round(create((a.significand < 0n ? -1n : 1n) + bigIntScale(b.significand, rounding.maximumSignificantDigits + 1), diff(b.exponent, rounding.maximumSignificantDigits + 1)), rounding); | ||
if (msdp1 !== 0 && 0 - d > digits(as) + msdp1) { | ||
return round(create((as < 0n ? -1n : 1n) + bigIntScale(bs, msdp1), diff(be, msdp1)), rounding); | ||
} | ||
return round(create(a.significand + bigIntScale(b.significand, -bd), a.exponent), rounding); | ||
return round(create(as + bigIntScale(bs, 0 - d), ae), rounding); | ||
} | ||
} | ||
return round(create(a.significand + b.significand, a.exponent), rounding); | ||
return round(create(as + bs, ae), rounding); | ||
}; | ||
@@ -328,8 +335,14 @@ BigDecimal.subtract = function (a, b, rounding = null) { | ||
BigDecimal.multiply = function (a, b, rounding = null) { | ||
return normalize(round(create(a.significand * b.significand, sum(a.exponent, b.exponent)), rounding), rounding); | ||
return normalize(round(create(BigInt(a.significand) * BigInt(b.significand), sum(a.exponent, b.exponent)), rounding), rounding); | ||
}; | ||
function bigIntScale(a, scaling) { | ||
if (typeof a !== 'bigint') { | ||
throw new TypeError(); | ||
} | ||
return (BASE === 2 ? (a << cachedBigInt(scaling)) : cachedPower(scaling) * a); | ||
} | ||
function bigIntUnscale(a, unscaling) { | ||
if (typeof a !== 'bigint') { | ||
throw new TypeError(); | ||
} | ||
return (BASE === 2 ? (a >> cachedBigInt(unscaling)) : a / cachedPower(unscaling)); | ||
@@ -352,4 +365,4 @@ } | ||
} | ||
let dividend = (scaling > 0 ? bigIntScale(a.significand, scaling) : a.significand); | ||
let divisor = (scaling < 0 ? bigIntScale(b.significand, -scaling) : b.significand); | ||
let dividend = BigInt(scaling > 0 ? bigIntScale(a.significand, scaling) : a.significand); | ||
let divisor = BigInt(scaling < 0 ? bigIntScale(b.significand, 0 - scaling) : b.significand); | ||
if (divisor < 0n) { | ||
@@ -398,20 +411,27 @@ dividend = -dividend; | ||
function compare(a, b) { | ||
if (a.exponent === b.exponent) { | ||
return a.significand < b.significand ? -1 : (a.significand > b.significand ? +1 : 0); | ||
const as = BigInt(a.significand); | ||
const bs = BigInt(b.significand); | ||
const ae = a.exponent; | ||
const be = b.exponent; | ||
const bd = diff(ae, be); | ||
const d = typeof bd === 'number' ? +bd : Number(BigInt(bd)); | ||
if (d === 0) { | ||
return as < bs ? -1 : (as > bs ? +1 : 0); | ||
} | ||
if (a.significand <= 0n && b.significand >= 0n) { | ||
return !(a.significand === 0n && b.significand === 0n) ? -1 : 0; | ||
if (as <= 0n && bs >= 0n) { | ||
return !(as === 0n && bs === 0n) ? -1 : 0; | ||
} | ||
if (a.significand >= 0n && b.significand <= 0n) { | ||
return (a.significand === 0n && b.significand === 0n) ? 0 : +1; | ||
if (as >= 0n && bs <= 0n) { | ||
return (as === 0n && bs === 0n) ? 0 : +1; | ||
} | ||
if (BASE !== 2) { | ||
const differenceOfLogarithms = Number(sum(diff(a.exponent, b.exponent), (digits(a.significand) - digits(b.significand)))); | ||
const x = sum(bd, (digits(as) - digits(bs))); | ||
const differenceOfLogarithms = typeof x === 'number' ? x : Number(BigInt(x)); | ||
if (differenceOfLogarithms !== 0) { | ||
return a.significand < 0n && b.significand < 0n ? (differenceOfLogarithms > 0 ? -1 : +1) : (differenceOfLogarithms < 0 ? -1 : +1); | ||
return as < 0n && bs < 0n ? (differenceOfLogarithms > 0 ? -1 : +1) : (differenceOfLogarithms < 0 ? -1 : +1); | ||
} | ||
} else { | ||
//TODO: remove when bitLength is fast | ||
const x = a.exponent >= b.exponent ? a.significand : a.significand >> cachedBigInt(diff(b.exponent, a.exponent)); | ||
const y = b.exponent >= a.exponent ? b.significand : b.significand >> cachedBigInt(diff(a.exponent, b.exponent)); | ||
const x = d >= 0 ? as : as >> cachedBigInt(0 - d); | ||
const y = d <= 0 ? bs : bs >> cachedBigInt(d); | ||
if (x < y) { | ||
@@ -425,4 +445,4 @@ return -1; | ||
} | ||
const x = a.exponent <= b.exponent ? a.significand : bigIntScale(a.significand, diff(a.exponent, b.exponent)); | ||
const y = b.exponent <= a.exponent ? b.significand : bigIntScale(b.significand, diff(b.exponent, a.exponent)); | ||
const x = d <= 0 ? as : bigIntScale(as, d); | ||
const y = d >= 0 ? bs : bigIntScale(bs, 0 - d); | ||
return x < y ? -1 : (x > y ? +1 : 0); | ||
@@ -481,5 +501,5 @@ } | ||
function bigDecimalToPlainString(significand, exponent, minFraction, minSignificant) { | ||
let e = exponent + significand.length - 1; | ||
let e = exponent + 0 + significand.length - 1; | ||
let i = significand.length - 1; | ||
while (i >= 0 && significand.charCodeAt(i) === "0".charCodeAt(0)) { | ||
while (i >= 0 && +significand.charCodeAt(i) === "0".charCodeAt(0)) { | ||
i -= 1; | ||
@@ -490,7 +510,7 @@ } | ||
if (e <= -1) { | ||
significand = "0".repeat(0 - e) + significand; | ||
significand = String("0".repeat(0 - e)) + significand; | ||
e = 0; | ||
} | ||
significand += "0".repeat(zeros); | ||
significand += "0".repeat(Math.max(minFraction - (significand.length - (e + 1)), 0)); | ||
significand += String("0".repeat(zeros)); | ||
significand += String("0".repeat(Math.max(minFraction - (significand.length - (e + 1)), 0))); | ||
return significand.slice(0, e + 1) + (significand.length > e + 1 ? "." + significand.slice(e + 1) : ""); | ||
@@ -504,3 +524,3 @@ } | ||
} | ||
return bigDecimalToPlainString(significand, Number(exponent), 0, minSignificant); | ||
return bigDecimalToPlainString(significand, Number(BigInt(exponent)), 0, minSignificant); | ||
} | ||
@@ -520,3 +540,3 @@ function toFixed(significand, exponent, minFraction) { | ||
const a = BigDecimal.abs(rounded); | ||
return sign + toFixed(BigDecimal.toBigInt(a).toString(), -fractionDigits, fractionDigits); | ||
return sign + toFixed(BigDecimal.toBigInt(a).toString(), 0 - fractionDigits, fractionDigits); | ||
}; | ||
@@ -528,3 +548,3 @@ | ||
if (n < 0n) { | ||
return BigDecimal.divide(BigDecimal.BigDecimal(1), exponentiate(x, -n, rounding), rounding); | ||
return BigDecimal.divide(BigDecimal.BigDecimal(1), exponentiate(x, -BigInt(n), rounding), rounding); | ||
} | ||
@@ -548,3 +568,3 @@ let y = undefined; | ||
if (BigDecimal.lessThan(x, BigDecimal.BigDecimal(1))) { | ||
return -logarithm(BigDecimal.divide(BigDecimal.BigDecimal(1), x, rounding), b, rounding); | ||
return 0n - logarithm(BigDecimal.divide(BigDecimal.BigDecimal(1), x, rounding), b, rounding); | ||
} | ||
@@ -632,3 +652,3 @@ const digits = getCountOfDigits(x); | ||
function exponentiate(a, n) { | ||
if (a !== BASE) { | ||
if (+a !== BASE) { | ||
throw new RangeError("a should be BASE");//? | ||
@@ -698,3 +718,3 @@ } | ||
// k >= x / log(BASE) | ||
return Math.ceil(Number(BigDecimal.toBigInt(BigDecimal.round(x, {maximumFractionDigits: 0, roundingMode: "half-even"}))) / Math.log(BASE)); | ||
return Math.ceil(Number(BigInt(BigDecimal.toBigInt(BigDecimal.round(x, {maximumFractionDigits: 0, roundingMode: "half-even"})))) / Math.log(BASE)); | ||
} | ||
@@ -729,4 +749,5 @@ if (name === "log") { | ||
// Hm... https://www.gnu.org/software/libc/manual/html_node/Errors-in-Math-Functions.html | ||
const exponent = Number(x.exponent); | ||
const v = Number(x.significand) * BASE**exponent; | ||
const e = x.exponent; | ||
const exponent = typeof e === 'number' ? e : Number(BigInt(e)); | ||
const v = Number(BigInt(x.significand)) * BASE**exponent; | ||
// some browsers have inaccurate results for Math.sin, Math.cos, Math.tan outside of [-pi/4;pi/4] range | ||
@@ -733,0 +754,0 @@ if ((name !== "sin" && name !== "cos" && name !== "tan") || Math.abs(v) <= Math.PI / 4) { |
{ | ||
"name": "@yaffle/bigdecimal", | ||
"version": "1.0.26", | ||
"version": "1.0.27", | ||
"description": "Arbitrary precision decimal arithmetic library. Polyfill for decimal proposal. Implemented on the top of BigInt.", | ||
@@ -5,0 +5,0 @@ "main": "BigDecimal.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
929
45624