@yaffle/bigdecimal
Advanced tools
Comparing version 1.0.17 to 1.0.19
/*jslint bigint: true, vars: true, indent: 2*/ | ||
// https://github.com/tc39/proposal-decimal | ||
// https://en.wikipedia.org/wiki/Floating-point_arithmetic | ||
// https://en.wikipedia.org/wiki/Fixed-point_arithmetic | ||
// Usage: | ||
@@ -169,20 +173,32 @@ // BigDecimal.BigDecimal(bigint) | ||
} | ||
let last = 0; | ||
let lastValue = 0n; | ||
let cache = {}; | ||
let cacheSize = 0; | ||
function cachedBigInt(k) { | ||
// k === maximumFractionDigits | ||
if (last !== k) { | ||
last = k; | ||
var lastValue = cache[k]; | ||
if (lastValue == null) { | ||
if (cacheSize > 100) { | ||
cache = {}; | ||
cacheSize = 0; | ||
} | ||
lastValue = BigInt(k); | ||
cache[k] = lastValue; | ||
cacheSize += 1; | ||
} | ||
return lastValue; | ||
} | ||
let lastExponent = 0; | ||
let lastPower = 1n; | ||
let cache2 = {}; | ||
let cache2Size = 0; | ||
function cachedPower(k) { | ||
if (lastExponent !== k) { | ||
lastExponent = k; | ||
lastPower = BIGINT_BASE**cachedBigInt(k); | ||
var lastValue = cache2[k]; | ||
if (lastValue == null) { | ||
if (cache2Size > 10) { | ||
cache2 = {}; | ||
cache2Size = 0; | ||
} | ||
lastValue = BIGINT_BASE**BigInt(k); | ||
cache2[k] = lastValue; | ||
cache2Size += 1; | ||
} | ||
return lastPower; | ||
return lastValue; | ||
} | ||
@@ -239,3 +255,3 @@ function round(a, rounding) { | ||
} else { | ||
const divisor = BIGINT_BASE**BigInt(k); | ||
const divisor = BASE === 2 ? 1n << cachedBigInt(k) : cachedPower(k); | ||
quotient = dividend / divisor; | ||
@@ -301,3 +317,3 @@ let twoRemainders = (dividend - divisor * quotient) * 2n; | ||
function bigIntScale(a, scaling) { | ||
return (BASE === 2 ? (a << BigInt(scaling)) : BIGINT_BASE**BigInt(scaling) * a); | ||
return (BASE === 2 ? (a << cachedBigInt(scaling)) : cachedPower(scaling) * a); | ||
} | ||
@@ -379,4 +395,5 @@ BigDecimal.divide = function (a, b, rounding = null) { | ||
} else { | ||
const x = a.exponent >= b.exponent ? a.significand : a.significand >> BigInt(diff(b.exponent, a.exponent)); | ||
const y = b.exponent >= a.exponent ? b.significand : b.significand >> BigInt(diff(a.exponent, b.exponent)); | ||
//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)); | ||
if (x < y) { | ||
@@ -445,3 +462,7 @@ return -1; | ||
let e = exponent + significand.length - 1; | ||
significand = significand.replace(/0+$/g, ""); | ||
let i = significand.length - 1; | ||
while (i >= 0 && significand.charCodeAt(i) === '0'.charCodeAt(0)) { | ||
i -= 1; | ||
} | ||
significand = significand.slice(0, i + 1); | ||
const zeros = Math.max(0, Math.max(e + 1, minSignificant) - significand.length); | ||
@@ -473,3 +494,3 @@ if (e <= -1) { | ||
BigDecimal.prototype.toFixed = function (fractionDigits, roundingMode = "half-up") { | ||
const value = BigDecimal.multiply(this, BigDecimal.BigDecimal(10n**BigInt(fractionDigits))); | ||
const value = BigDecimal.multiply(BigDecimal.BigDecimal(10n**BigInt(fractionDigits)), this); | ||
const sign = BigDecimal.lessThan(value, BigDecimal.BigDecimal(0)) ? "-" : ""; | ||
@@ -668,3 +689,3 @@ const rounded = BigDecimal.round(value, {maximumFractionDigits: 0, roundingMode: roundingMode}); | ||
if (BigDecimal.equal(x, BigDecimal.BigDecimal(specialValue))) { | ||
return f(x, rounding); | ||
return f(x, {maximumSignificantDigits: 1, roundingMode: 'half-even'}); | ||
} | ||
@@ -686,3 +707,4 @@ let result = BigDecimal.BigDecimal(0); | ||
// Hm... https://www.gnu.org/software/libc/manual/html_node/Errors-in-Math-Functions.html | ||
const v = Number(x.significand) * BASE**Number(x.exponent); | ||
const exponent = Number(x.exponent); | ||
const v = Number(x.significand) * BASE**exponent; | ||
const numberValue = Math[name](v); | ||
@@ -779,3 +801,3 @@ if (name !== "sin" && name !== "cos" && name !== "tan" || Math.abs(numberValue) < Math.PI / 4) { | ||
if (!BigDecimal.equal(x, BigDecimal.BigDecimal(0))) { | ||
const logBASEApproximate = BigDecimal.divide(BigDecimal.BigDecimal(Math.log(BASE) * (Number.MAX_SAFE_INTEGER + 1)), BigDecimal.BigDecimal(Number.MAX_SAFE_INTEGER + 1), internalRounding); | ||
const logBASEApproximate = BigDecimal.divide(BigDecimal.BigDecimal(Math.log(BASE) * (Number.MAX_SAFE_INTEGER + 1)), BigDecimal.add(BigDecimal.BigDecimal(Number.MAX_SAFE_INTEGER), BigDecimal.BigDecimal(1)), internalRounding); | ||
const kApproximate = BigDecimal.round(BigDecimal.divide(x, logBASEApproximate, {maximumSignificantDigits: Math.max(Number(getCountOfDigits(x)), 1), roundingMode: "half-even"}), {maximumFractionDigits: 0, roundingMode: "half-even"}); | ||
@@ -808,3 +830,3 @@ if (!BigDecimal.equal(kApproximate, BigDecimal.BigDecimal(0))) { | ||
} | ||
if (BigDecimal.greaterThan(x, BigDecimal.divide(BigDecimal.BigDecimal(Math.floor(Math.PI / 4 * (Number.MAX_SAFE_INTEGER + 1) + 0.5)), BigDecimal.BigDecimal(Number.MAX_SAFE_INTEGER + 1), rounding))) { | ||
if (BigDecimal.greaterThan(x, BigDecimal.divide(BigDecimal.BigDecimal(Math.floor(Math.PI / 4 * (Number.MAX_SAFE_INTEGER + 1) + 0.5)), BigDecimal.add(BigDecimal.BigDecimal(Number.MAX_SAFE_INTEGER), BigDecimal.BigDecimal(1)), rounding))) { | ||
const halfOfPi = BigDecimal.multiply(BigDecimal.BigDecimal(2), BigDecimal.atan(BigDecimal.BigDecimal(1), {maximumSignificantDigits: rounding.maximumSignificantDigits + Number(getCountOfDigits(x)) + 1, roundingMode: "half-even"})); | ||
@@ -811,0 +833,0 @@ const i = BigDecimal.round(BigDecimal.divide(x, halfOfPi, {maximumSignificantDigits: Math.max(Number(getCountOfDigits(x)), 1), roundingMode: "half-even"}), {maximumFractionDigits: 0, roundingMode: "half-even"}); |
{ | ||
"name": "@yaffle/bigdecimal", | ||
"version": "1.0.17", | ||
"version": "1.0.19", | ||
"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
44247
898