diff --git a/src/function/special/zeta.js b/src/function/special/zeta.js index 303026601d..aa8b2b978c 100644 --- a/src/function/special/zeta.js +++ b/src/function/special/zeta.js @@ -37,8 +37,11 @@ export const createZeta = /* #__PURE__ */ factory(name, dependencies, ({ typed, s, value => new BigNumber(value), () => { - // relTol is for example 1e-12. Extract the positive exponent 12 from that - return Math.abs(Math.log10(config.relTol)) + // relTol is for example 1e-12. Extract the positive exponent 12 from that. + // Round to guard against floating point errors in Math.log10 for very + // small relTol like 1e-320, which would otherwise yield a non-integer + // digit count (see https://github.com/josdejong/mathjs/issues/3532). + return Math.round(Math.abs(Math.log10(config.relTol))) } ), Complex: zetaComplex diff --git a/test/unit-tests/function/special/zeta.test.js b/test/unit-tests/function/special/zeta.test.js index ad1200edad..59c233ddf0 100644 --- a/test/unit-tests/function/special/zeta.test.js +++ b/test/unit-tests/function/special/zeta.test.js @@ -58,6 +58,20 @@ describe('Riemann Zeta', function () { bigApproxEqual(zeta(math2.bignumber(-Infinity)), math2.bignumber(NaN)) // shouldn't stall }) + it('should calculate the Riemann Zeta Function of a BigNumber when relTol has a non-integer base-10 logarithm', function () { + // See https://github.com/josdejong/mathjs/issues/3532 + // The digit count is derived from Math.abs(Math.log10(config.relTol)). + // For a relTol that is not an exact power of ten (e.g. 5e-8, or 1e-320 + // where floating point rounding makes log10 non-integer), this yielded a + // non-integer digit count that eventually reached factorial/gamma as a + // non-integer BigNumber, throwing "Integer BigNumber expected". + const math2 = math.create() + math2.config({ number: 'BigNumber', relTol: 5e-16, absTol: 5e-19 }) + + assert.doesNotThrow(() => math2.evaluate('zeta(3)')) + approxEqual(Number(math2.evaluate('zeta(3)')), 1.2020569031595942) + }) + it('should calculate the Riemann Zeta Function of a rational number', function () { approxEqual(zeta(0.125), -0.6327756234986952552935) approxEqual(zeta(0.25), -0.81327840526189165652144)