
I'm not 100% sure as to which one is actually correct; but the point is
On 32-bit x86 platforms when using the native code generator, the -fexcess-precision option is always on. This means that floating-point calculations are non-deterministic, because depending on how the program is compiled (optimisation settings, for example), certain calculations might be done at 80-bit precision instead of the intended 32-bit or 64-bit
#9304: Floating point woes; Different behavior on Mac vs Linux -------------------------------------+------------------------------------ Reporter: lerkok | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.8.3 Resolution: | Keywords: floating point Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: 9276 Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by ekmett): that these are IEEE floating point numbers running on the same architecture (Intel X86), and thus should decode in precisely the same way. I personally wouldn't expect that at all. I'd expect it all comes down to whether the optimizer decided to keep the intermediate result in a larger temporary because it ran it through the old x87 hardware or if it decided to go through SSE, etc. This will happen. It will give different answers, even on the same machine and OS at different call sites, when the optimizer spits out different code for different inlinings, etc. Floating point answers are very fragile. A difference of only one ulp is actually pretty good. ;) There is a relevant note in: http://www.haskell.org/ghc/docs/latest/html/users_guide/bugs.html#bugs-ghc precision. Floating-point results may differ when optimisation is turned on. In the worst case, referential transparency is violated, because for example let x = E1 in E2 can evaluate to a different value than E2[E1/x].
One workaround is to use the -msse2 option (see Section 4.16, “Platform- specific Flags”, which generates code to use the SSE2 instruction set instead of the x87 instruction set. SSE2 code uses the correct precision for all floating-point operations, and so gives deterministic results. However, note that this only works with processors that support SSE2 (Intel Pentium 4 or AMD Athlon 64 and later), which is why the option is not enabled by default. The libraries that come with GHC are probably built without this option, unless you built GHC yourself.
Also note I'd suspect a profound lack of interaction of that flag with ghci's bytecode interpreter. The -msse2 thing is probably doing you no good in the REPL. Also as noted above, the libraries that ship with GHC aren't build that way, so if base is doing your multiplication for you, you're probably just smacking into generated code that had -fexcess- precision turned on. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9304#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler