0
votes

I want to achieve exactly same floating-point results in a gcc/Linux ported version of a Windows software. For that reason I want all double operations to be of 64-bit precision. This can be done using for example -mpc64 or -msse2 or -fstore-floats (all with side effects). However one thing I can't fix is transcendental functions like sin/asin etc. The docs say that they internally expect (and use I suppose) long double precision and whatever I do they produce results different from Windows counterparts.

How is it possible for these function to calculate results using 64-bit floating point precision?

UPDATE: I was wrong, it is printf("%.17f") that incorrectly rounds the correct double result, "print x" in gdb shows that the number itself is correct. I suppose I need a different question on this one... perhaps on how to make printf not to treat double internally as extended. Maybe using stringstream will give expected results... Yes it does.

3
Did you use Microsoft's compiler to compile said software for Windows? What were the compilation options w.r.t. floating point? There are a few options there, see Microsoft Visual C++ Floating-Point Optimization on precise, fast, strict and so on. Also, can you look at the disassembly of both versions to see how they differ exactly?Alexey Frunze
Can you be sure these functions are not implemented using lookup tables by the implementer of the standard library?Bingo
It is compiled with precise and the docs say: "Intermediate expressions are computed at the default 53-bit precision". As for lookup tables etc, I have no idea. But docs for gcc says that "Note that some mathematical libraries assume that extended-precision (80-bit) floating-point operations are enabled by default; routines in such libraries could suffer significant loss of accuracy, typically through so-called “catastrophic cancellation”, when this option [mpc64] is used to set the precision to less than extended precision." (c) gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.htmlqueen3

3 Answers

0
votes

Different LibM libraries use different algorithms for elementary functions, so you have to use the same library on both Windows and Linux to achieve exactly the same results. I would suggest to compile FDLibM and statically link it with your software.

0
votes

I found that it is printf("%.17f") that uses incorrect precision to print results (probably extended internally), when I use stringstream << setprecision(17) the result is correct. So the answer is not really related to the question but, at least it works for me.

But I would be glad if someone provides a way to make printf to produce expected results.

0
votes

An excellent solution for the transcendental function problem is to use the GNU MPFR Library. But be aware that Microsoft compilers do not support extended precision floating point. With the Microsoft compiler, double and long double are both 53-bit precision. With gcc, long double is 64-bit precision. To get matching results across Windows/linux, you must either avoid use of long double or avoid use of Microsoft compilers. For many Windows projects, the Windows port of gcc (mingw) works well. This lets the Windows project use 64-bit precision long doubles. A problem with mingw long double support is that mingw uses Microsoft libraries for calls such as printf. For that reason, printing a long double doesn't work correctly. A work-around for this problem is to use mpfr_printf.