insaf021 opened a new pull request, #349:
URL: https://github.com/apache/commons-math/pull/349
With the default `JdkMath` backend (`AccurateMath`), on master:
IEEEremainder(1.7976931348623157E308, 1.5) = -Infinity
(StrictMath: 0.5)
IEEEremainder(4.503599627370496E15, 1.5) = 1.0
(StrictMath: -0.5)
IEEEremainder(1.0, 1.0E-300) = 1.1102230246251565E-16
(StrictMath: -1.0368134719602886E-301)
IEEEremainder(1.5, 0.49999999999999994) = 2.220446049250313E-16
(StrictMath: 1.6653345369377348E-16)
The general case evaluates `dividend - divisor * rint(dividend / divisor)`
in doubles. Past 2^53 the rounded quotient is not the nearest integer, `divisor
* n` is itself rounded so the error scales with the dividend rather than the
remainder, and a large quotient overflows the product. Even with |x/y| <= 1000,
974017 of 1000000 random pairs differ from `StrictMath`. `DerivativeStructure`,
`SparseGradient` and `DSCompiler` inherit this through `JdkMath`.
The fix reduces |dividend| modulo 2|divisor| with `%`, which is exact for
doubles, then subtracts |divisor| at most twice to round the quotient to even,
as fdlibm's `__ieee754_remainder` does. Every step is exact and the method
stays pure Java. It matches `StrictMath.IEEEremainder` bit for bit on 100M
pairs covering random bit patterns, subnormal divisors, ties and the overflow
edges, on JDK 21 and 27. The javadoc bullet claiming the result always has the
dividend's sign now applies to a zero result only, since IEEEremainder(3, 2) is
-1.
`testIEEEremainder` compares against an exact BigDecimal reference; on
master:
AccurateMathTest.testIEEEremainder:1376 expected: <0.5> but was:
<-Infinity>
`mvn clean verify` is green across the reactor on JDK 21.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]