@yaffle/bigdecimal
Advanced tools
Comparing version 1.0.24 to 1.0.25
@@ -714,6 +714,3 @@ /*jslint bigint: true, vars: true, indent: 2*/ | ||
if (a < 1/0 && a > MIN_NORMALIZED_VALUE) { | ||
const e = getExponent(a); | ||
const s = numberValue / 2**e; | ||
const e1 = getExponent(Number.MAX_SAFE_INTEGER + 1) - 1; | ||
result = create(BigInt(s * 2**e1), e - e1);//TODO: ? | ||
result = BigDecimal.BigDecimal(numberValue); | ||
} | ||
@@ -793,2 +790,8 @@ } | ||
function fromNumberApproximate(number) { | ||
return BigDecimal.divide(BigDecimal.BigDecimal(Math.floor(number * (Number.MAX_SAFE_INTEGER + 1))), | ||
BigDecimal.add(BigDecimal.BigDecimal(Number.MAX_SAFE_INTEGER), BigDecimal.BigDecimal(1)), | ||
{maximumSignificantDigits: Math.floor(Math.log2(Number.MAX_SAFE_INTEGER + 1) / Math.log2(BASE) + 0.5), roundingMode: "half-even"}); | ||
} | ||
BigDecimal.exp = tryToMakeCorrectlyRounded(0, function exp(x, rounding) { | ||
@@ -802,3 +805,3 @@ //! k = round(x / ln(BASE)); | ||
if (!BigDecimal.equal(x, BigDecimal.BigDecimal(0))) { | ||
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 logBASEApproximate = fromNumberApproximate(Math.log(BASE)); | ||
const kApproximate = BigDecimal.round(BigDecimal.divide(x, logBASEApproximate, {maximumSignificantDigits: Math.max(Number(getCountOfDigits(x)), 1), roundingMode: "half-even"}), {maximumFractionDigits: 0, roundingMode: "half-even"}); | ||
@@ -830,8 +833,10 @@ if (!BigDecimal.equal(kApproximate, BigDecimal.BigDecimal(0))) { | ||
function divideByHalfOfPI(x, rounding) { // x = k*pi/2 + r + 2*pi*n, where |r| < pi/4 | ||
if (BigDecimal.lessThan(x, BigDecimal.BigDecimal(0))) { | ||
throw new RangeError(); | ||
} | ||
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 quarterOfPiApproximated = fromNumberApproximate(Math.PI / 4); | ||
if (BigDecimal.greaterThan(BigDecimal.abs(x), quarterOfPiApproximated)) { | ||
//TODO: FIX | ||
const halfOfPi = BigDecimal.multiply(BigDecimal.BigDecimal(2), BigDecimal.atan(BigDecimal.BigDecimal(1), {maximumSignificantDigits: rounding.maximumSignificantDigits + significandDigits(x) + Number(getCountOfDigits(x)) + 1 + Math.ceil(42 / Math.log2(BASE)), roundingMode: "half-even"})); | ||
const internalRounding = { | ||
maximumSignificantDigits: rounding.maximumSignificantDigits + significandDigits(x) + Number(getCountOfDigits(x)) + 1 + Math.ceil(42 / Math.log2(BASE)), | ||
roundingMode: "half-even" | ||
}; | ||
const halfOfPi = BigDecimal.multiply(BigDecimal.BigDecimal(2), BigDecimal.atan(BigDecimal.BigDecimal(1), internalRounding)); | ||
const i = BigDecimal.round(BigDecimal.divide(x, halfOfPi, {maximumSignificantDigits: Math.max(Number(getCountOfDigits(x)), 1), roundingMode: "half-even"}), {maximumFractionDigits: 0, roundingMode: "half-even"}); | ||
@@ -844,19 +849,8 @@ const remainder = BigDecimal.subtract(x, BigDecimal.multiply(i, halfOfPi)); | ||
BigDecimal.sin = tryToMakeCorrectlyRounded(0, function (x, rounding) { | ||
if (BigDecimal.lessThan(x, BigDecimal.BigDecimal(0))) { | ||
return BigDecimal.unaryMinus(BigDecimal.sin(BigDecimal.unaryMinus(x), rounding)); | ||
} | ||
function _cos(x, rounding, subtractHalfOfPi) { | ||
const tmp = divideByHalfOfPI(x, rounding); | ||
const a = tmp.remainder; | ||
const k = tmp.k; | ||
if (k === 1) { | ||
return BigDecimal.cos(a, rounding); | ||
} | ||
if (k === 2) { | ||
return BigDecimal.unaryMinus(BigDecimal.sin(a, rounding)); | ||
} | ||
if (k === 3) { | ||
return BigDecimal.unaryMinus(BigDecimal.cos(a, rounding)); | ||
} | ||
const k = (tmp.k + (subtractHalfOfPi ? -1 + 4 : 0)) % 4; | ||
// https://en.wikipedia.org/wiki/Lookup_table#Computing_sines | ||
// https://en.wikipedia.org/wiki/Trigonometric_functions#Power_series_expansion | ||
const internalRounding = { | ||
@@ -866,3 +860,3 @@ maximumSignificantDigits: rounding.maximumSignificantDigits + Math.ceil(Math.log2(rounding.maximumSignificantDigits + 0.5) / Math.log2(BASE)), | ||
}; | ||
let n = 1; | ||
let n = k === 1 || k === 3 ? 1 : 0; | ||
let term = BigDecimal.BigDecimal(1); | ||
@@ -879,39 +873,14 @@ let sum = term; | ||
} | ||
return BigDecimal.multiply(a, sum); | ||
if (k === 1 || k === 2) { | ||
sum = BigDecimal.unaryMinus(sum); | ||
} | ||
return k === 1 || k === 3 ? BigDecimal.multiply(a, sum) : sum; | ||
} | ||
BigDecimal.sin = tryToMakeCorrectlyRounded(0, function (x, rounding) { | ||
return _cos(x, rounding, true); | ||
}, "sin"); | ||
BigDecimal.cos = tryToMakeCorrectlyRounded(0, function (x, rounding) { | ||
if (BigDecimal.lessThan(x, BigDecimal.BigDecimal(0))) { | ||
return BigDecimal.cos(BigDecimal.unaryMinus(x), rounding); | ||
} | ||
const tmp = divideByHalfOfPI(x, rounding); | ||
const a = tmp.remainder; | ||
const k = tmp.k; | ||
if (k === 1) { | ||
return BigDecimal.unaryMinus(BigDecimal.sin(a, rounding)); | ||
} | ||
if (k === 2) { | ||
return BigDecimal.unaryMinus(BigDecimal.cos(a, rounding)); | ||
} | ||
if (k === 3) { | ||
return BigDecimal.sin(a, rounding); | ||
} | ||
// https://en.wikipedia.org/wiki/Trigonometric_functions#Power_series_expansion | ||
const internalRounding = { | ||
maximumSignificantDigits: rounding.maximumSignificantDigits + Math.ceil(Math.log2(rounding.maximumSignificantDigits + 0.5) / Math.log2(BASE)), | ||
roundingMode: "half-even" | ||
}; | ||
let n = 0; | ||
let term = BigDecimal.BigDecimal(1); | ||
let sum = term; | ||
let lastSum = BigDecimal.BigDecimal(0); | ||
const aa = BigDecimal.multiply(a, a); | ||
while (!BigDecimal.equal(lastSum, sum)) { | ||
n += 2; | ||
term = BigDecimal.multiply(term, aa); | ||
term = BigDecimal.divide(term, BigDecimal.BigDecimal(-n * (n - 1)), internalRounding); | ||
lastSum = sum; | ||
sum = BigDecimal.add(sum, term, internalRounding); | ||
} | ||
return sum; | ||
return _cos(x, rounding, false); | ||
}, "cos"); | ||
@@ -967,3 +936,3 @@ | ||
const k = Math.floor(Math.log2(Number.MAX_SAFE_INTEGER + 1) / Math.log2(BASE)) - 1; | ||
const xn = BigDecimal.toNumber(BigDecimal.round(BigDecimal.multiply(y, exponentiate(BASE, k)), {maximumFractionDigits: 0, roundingMode: 'half-even'})) / BASE**k; | ||
const xn = BigDecimal.toNumber(BigDecimal.round(BigDecimal.multiply(y, exponentiate(BASE, k)), {maximumFractionDigits: 0, roundingMode: "half-even"})) / BASE**k; | ||
const r = n === 2 ? Math.sqrt(xn) : (n === 3 ? Math.cbrt(xn) : Math.exp(Math.log(xn) / n)); | ||
@@ -970,0 +939,0 @@ const resultSignificantDigits = 8 * (rounding.maximumSignificantDigits || (rounding.maximumFractionDigits + Math.ceil(significandDigits(x) / n)) || 1); |
{ | ||
"name": "@yaffle/bigdecimal", | ||
"version": "1.0.24", | ||
"version": "1.0.25", | ||
"description": "Arbitrary precision decimal arithmetic library. Polyfill for decimal proposal. Implemented on the top of BigInt.", | ||
@@ -5,0 +5,0 @@ "main": "BigDecimal.js", |
@@ -52,2 +52,5 @@ # BigDecimal | ||
BigDecimal.sqrt(a, rounding) | ||
BigDecimal.cbrt(a, rounding) | ||
The `rounding` argument may look like `{maximumFractionDigits: 10, roundingMode: "half-even"}` or `{maximumSignificantDigits: 10, roundingMode: "half-even"}`, | ||
@@ -54,0 +57,0 @@ where the `roundingMode` can be: |
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
111
46274
921