Thursday, November 8, 2007

x86 Math Bug...

The implementation of sin() and cos() on the Intel x86 platform has an interesting bug:
For many years, the JDK on x86 platforms has used the hardware fsin/fcos x87 instructions in the range [-pi/4, pi/4], a range which encompasses about half of all representable floating-point values. Therefore, in that range the performance of the JDK's transcendental functions should be nearly the same as the performance of the transcendental functions in C, C++, etc. that are using those same fsin/fcos instructions. Benchmarks which focus on testing the trig performance of large values, such as almabench, present a skewed portrait of Java's trigonometric performance. The next question is why don't we just use fsin/fcos over the entire floating-point range? The simple answer is that fsin/fcos can deliver answers that are arbitrarily wrong for the most straightforward way of measuring error in the result.
I'd never heard about this until I read this post on James Gosling's blog. On the native, uncorrected platform, the error can amount to 5 or 6 significant digits – most likely even producing results with the wrong sign!

Java programmers need not fear – the JVM fixes the problem (read the post to see how), but the fix is computationally intensive and reduces performance for angles outside the range of -pi/4 to pi/4 (in radians). Slow, but accurate (and predictable), as opposed to fast, but randomly inaccurate...

No comments:

Post a Comment