Floating point mismatch between compilers (Visual Studio 2010 and GCC) - c++

I'm trying to solve a cross-platform issue that's cropping up and I'm not sure quite how to go about it. Here's a demonstration program:
#include <cmath>
#include <cstdio>
int main()
{
int xm = 0x3f18492a;
float x = *(float*)&xm;
x = (sqrt(x) + 1) / 2.0f;
printf("%f %x\n", x, *(int*)&x);
}
The output on Windows when compiled in VS2010 is:
0.885638 3f62b92a
The output when compiled with GCC 4.8.1 (ideone.com sample) is:
0.885638 3f62b92b
These small mismatches end up ballooning into a serious problem over the course of a program that needs to run identically on multiple platforms. I'm not concerned so much about "accuracy" as that the results match each other. I tried switching the /fp mode in VS to strict from precise, but that doesn't seem to fix it.
What other avenues should I look at to make this calculation have the same result on both platforms?
UPDATE: Interestingly, if I change the code like this, it matches across the platforms:
#include <cmath>
#include <cstdio>
int main()
{
int xm = 0x3f18492a;
float x = *(float*)&xm;
//x = (sqrt(x) + 1) / 2.0f;
float y = sqrt(x);
float z = y + 1;
float w = z / 2.0f;
printf("%f %x %f %x %f %x %f %x\n", x, *(int*)&x, y, *(int*)&y, z, *(int*)&z, w, *(int*)&w);
}
I'm not sure it's realistic, however, to be walking through the code and changing all floating point operations like this!

Summary: This is generally not supported by compilers, you will have a tough time doing it in a higher-level language, and you will need to use one math library common to all your target platforms.
The C and C++ language standards allow implementations a considerable amount (too much) of flexibility in floating-point operations. Many C and C++ floating-operations are not required to adhere to the IEEE 754-2008 standard in the way that might be intuitive to many programmers.
Even many C and C++ implementations do not provide good support for adhering to the IEEE 754-2008 standard.
Math library implementations are a particular problem. There does not exist any normal library (commercially available or widely-used open source with a known-bounded run-time) that provides correctly rounded results for all standard math functions. (Getting the mathematics right on some of the functions is a very difficult problem.)
sqrt, however, is relatively simple and should return correctly rounded results in an library of reasonable quality. (I am unable to vouch for the Microsoft implementation.) It is more likely the particular problem in the code you show is the compiler’s choice to use varying precisions of floating-point while evaluating expressions.
There may be various switches you can use with various compilers to ask them to conform to certain rules about floating-point behavior. Those may be sufficient for getting elementary operations to perform as expected. If not, assembly language is a way to access well-defined floating-point operations. However, the behavior of library routines will be different between platforms unless you supply a common library. This includes both math library routines (such as pow) and conversions found in routines such as fprintf, fscanf, strtof. You must therefore find one well-designed implementation of each routine you rely on that is supported on all of the platforms you target. (It must be well-designed in the sense that it provides identical behavior on all platforms. Mathematically, it could be somewhat inaccurate, as long as it is within bounds tolerable for your application.)

The Visual Studio compiler tends to generate instructions that use the old x87 FPU(*), but it generates code at the beginning of the executable to set the FPU to the precision of the double format.
GCC can also generate instructions that use the old x87 FPU, but when generating x86-64 code, the default is to use SSE2. On Mac OS X, the default is to use SSE2 even in 32-bit since all Intel Macs have SSE2. When it generates instruction for the 387, GCC does not set the precision of the FPU to the double format, so that computations are made in the 80-bit double-extended format, and then rounded to double when assigned.
As a consequence:
If you use only double computations, Visual Studio should generate a program that computes exactly at the precision of the type, because it is always double(**). And if on the GCC side you use -msse2 -mfpmath=sse, you can expect GCC to also generate code that computes at the precision of doubles, this time by using SSE2 instructions. The computations should match.
Or if you make both GCC and Visual Studio emit SSE2 instructions, again, the computations should match. I am not familiar with Visual Studio but the switch may be /arch:SSE2.
This does not solve the problem with math libraries, which is indeed an unsolved problem. If your computations involve trigonometric or other functions, you must use the same library as part of your project on both sides. I would recommend CRlibm. Less accurate libraries are fine too as long as it's the same library, and it respects the above constraints (using only double or compiled with SSE2 on both sides).
(*) There may be a way to instruct it to generate SSE2 instructions. If you find it, use it: it will solve your particular problem.
(**) modulo exceptions for infinities and subnormals.

C allows intermediate calculation to occurs at the floating point's precision or at a higher one.
The windows result matches the GCC if all calculations occurs using only using float.
The GCC calculation obtains the different (and more accurate) result when all calculations are coded as float, but are allowed to go to double or long double for intermediate results.
So even if everything is IEEE 754 compliant, controlling the allowed intermediate calculations has an effect.
[Edit] I do not think the above really answers the OP stated issue, but is a concern for general FP issues. It is the below, that I think best explains the difference.
MS dev network sqrt
I suspect the difference was that in the windows compilation, it was in C++ mode, thus the sqrt(x) called float sqrt(float). In gcc, it was in C mode and sqrt(x1) called double sqrt(double).
If this is the case, insure C code in windows is compiled in C mode and not C++.
int main() {
{
volatile float f1;
float f2;
double d1;
int xm = 0x3f18492a;
f1 = *(float*) &xm;
f2 = *(float*) &xm;
d1 = *(float*) &xm;
f1 = sqrtf(f1);
f1 = f1 + 1.0f;
f1 = f1 / 2.0f;
printf("f1 %0.17e %a %08X\n", f1, f1, *(int*)&f1);
f2 = (sqrt(f2) + 1) / 2.0;
printf("f2 %0.17e %a %08X\n", f2, f2, *(int*)&f2);
d1 = (sqrt(d1) + 1) / 2.0;
printf("d1 %0.17e %a\n", d1, d1);
return 0;
}
f1 8.85637879371643066e-01 0x1.c57254p-1 3F62B92A
f2 8.85637938976287842e-01 0x1.c57256p-1 3F62B92B
d1 8.85637911452129889e-01 0x1.c572551391bc9p-1

The IEEE 754 specifies that computations can be processed at a higher precision than what is stored in memory then rounded when written back to memory. This causes many issues such as the one you see. In short, the standard does not promise that the same computation carried out on all hardware will return the same answer.
If the value to be computed on is placed on a larger register then one computation is done and then the value is moved off of the register back to memory the result is truncated there. It could then be moved back on to the larger register for another computation.
On the other hand if all the computations are done on the larger register before the value is moved back to memory you will get a different result. You may have to disassemble the code to see what's happening in your case.
With float point work it's important to understand how much precision you need in the final answer and how much precision you are guaranteed to have by the precision (note the two uses of the word) of the variables you choose and never expect anymore precision than you are guaranteed.
In the end when you are comparing results (this is true of any floating point work) you can not look for exact matches, you determine the precision that you require and you check that the difference between two values is less than the precision you require.
Getting back to practicalities, the Intel processors have 80 bit registers for floating point computations that may be used even though you've specified float which is typically 32-bit (but not always).
If you want to have fun try turning on various optimizations and processor options like SSE in your compiler and see what results you get (as well as what comes out of the disassembler).

With my 4.6.3 compiler it generates this code:
main:
.LFB104:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $1063434539, %esi
movl $.LC1, %edi
movsd .LC0(%rip), %xmm0
movl $1, %eax
call printf
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LC0:
.long 1610612736
.long 1072453413
Note that there is ZERO calculations performed in this code, just storing various constants in registers.
I haven't got a Visual stdudio compiler, so I don't know what that produces.

GCC compiler implements so called strict-aliasing semantics, which relies on the fact that in both C and C++ it is generally illegal to perform type-punning through pointer conversions (with few exceptions). Your code contains multiple violations of the requirements of strict-aliasing semantics. So, it is perfectly logical to expect that combination of strict-aliasing semantics and optimizations might produce completely unexpected and seemingly illogical results in GCC (or any other compiler, for that matter).
On top of that, there would be nothing unusual in sqrt producing slightly different results in different implementations.

If you have freedom to change languages, consider using Java with "strictfp". The Java language specification gives very precise rules for order of operations, rounding etc. in strictfp mode.
Exactly matching results across implementations is an objective of the Java standard for strictfp mode. It is not an objective for the C++ standards.

You want them both to be using the IEEE 754 standard.

Related

How to force GCC to assume that a floating-point expression is non-negative?

There are cases where you know that a certain floating-point expression will always be non-negative. For example, when computing the length of a vector, one does sqrt(a[0]*a[0] + ... + a[N-1]*a[N-1]) (NB: I am aware of std::hypot, this is not relevant to the question), and the expression under the square root is clearly non-negative. However, GCC outputs the following assembly for sqrt(x*x):
mulss xmm0, xmm0
pxor xmm1, xmm1
ucomiss xmm1, xmm0
ja .L10
sqrtss xmm0, xmm0
ret
.L10:
jmp sqrtf
That is, it compares the result of x*x to zero, and if the result is non-negative, it does the sqrtss instruction, otherwise it calls sqrtf.
So, my question is: how can I force GCC into assuming that x*x is always non-negative so that it skips the comparison and the sqrtf call, without writing inline assembly?
I wish to emphasize that I am interested in a local solution, and not doing things like -ffast-math, -fno-math-errno, or -ffinite-math-only (though these do indeed solve the issue, thanks to ks1322, harold, and Eric Postpischil in the comments).
Furthemore, "force GCC into assuming x*x is non-negative" should be interpreted as assert(x*x >= 0.f), so this also excludes the case of x*x being NaN.
I am OK with compiler-specific, platform-specific, CPU-specific, etc. solutions.
You can write assert(x*x >= 0.f) as a compile-time promise instead of a runtime check as follows in GNU C:
#include <cmath>
float test1 (float x)
{
float tmp = x*x;
if (!(tmp >= 0.0f))
__builtin_unreachable();
return std::sqrt(tmp);
}
(related: What optimizations does __builtin_unreachable facilitate? You could also wrap if(!x)__builtin_unreachable() in a macro and call it promise() or something.)
But gcc doesn't know how to take advantage of that promise that tmp is non-NaN and non-negative. We still get (Godbolt) the same canned asm sequence that checks for x>=0 and otherwise calls sqrtf to set errno. Presumably that expansion into a compare-and-branch happens after other optimization passes, so it doesn't help for the compiler to know more.
This is a missed-optimization in the logic that speculatively inlines sqrt when -fmath-errno is enabled (on by default unfortunately).
What you want instead is -fno-math-errno, which is safe globally
This is 100% safe if you don't rely on math functions ever setting errno. Nobody wants that, that's what NaN propagation and/or sticky flags that record masked FP exceptions are for. e.g. C99/C++11 fenv access via #pragma STDC FENV_ACCESS ON and then functions like fetestexcept(). See the example in feclearexcept which shows using it to detect division by zero.
The FP environment is part of thread context while errno is global.
Support for this obsolete misfeature is not free; you should just turn it off unless you have old code that was written to use it. Don't use it in new code: use fenv. Ideally support for -fmath-errno would be as cheap as possible but the rarity of anyone actually using __builtin_unreachable() or other things to rule out a NaN input presumably made it not worth developer's time to implement the optimization. Still, you could report a missed-optimization bug if you wanted.
Real-world FPU hardware does in fact have these sticky flags that stay set until cleared, e.g. x86's mxcsr status/control register for SSE/AVX math, or hardware FPUs in other ISAs. On hardware where the FPU can detect exceptions, a quality C++ implementation will support stuff like fetestexcept(). And if not, then math-errno probably doesn't work either.
errno for math was an old obsolete design that C / C++ is still stuck with by default, and is now widely considered a bad idea. It makes it harder for compilers to inline math functions efficiently. Or maybe we're not as stuck with it as I thought: Why errno is not set to EDOM even sqrt takes out of domain arguement? explains that setting errno in math functions is optional in ISO C11, and an implementation can indicate whether they do it or not. Presumably in C++ as well.
It's a big mistake to lump -fno-math-errno in with value-changing optimizations like -ffast-math or -ffinite-math-only. You should strongly consider enabling it globally, or at least for the whole file containing this function.
float test2 (float x)
{
return std::sqrt(x*x);
}
# g++ -fno-math-errno -std=gnu++17 -O3
test2(float): # and test1 is the same
mulss xmm0, xmm0
sqrtss xmm0, xmm0
ret
You might as well use -fno-trapping-math as well, if you aren't ever going to unmask any FP exceptions with feenableexcept(). (Although that option isn't required for this optimization, it's only the errno-setting crap that's a problem here.).
-fno-trapping-math doesn't assume no-NaN or anything, it only assumes that FP exceptions like Invalid or Inexact won't ever actually invoke a signal handler instead of producing NaN or a rounded result. -ftrapping-math is the default but it's broken and "never worked" according to GCC dev Marc Glisse. (Even with it on, GCC does some optimizations which can change the number of exceptions that would be raised from zero to non-zero or vice versa. And it blocks some safe optimizations). But unfortunately, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54192 (make it off by default) is still open.
If you actually ever did unmask exceptions, it might be better to have -ftrapping-math, but again it's very rare that you'd ever want that instead of just checking flags after some math operations, or checking for NaN. And it doesn't actually preserve exact exception semantics anyway.
See SIMD for float threshold operation for a case where the -ftrapping-math default incorrectly blocks a safe optimization. (Even after hoisting a potentially-trapping operation so the C does it unconditionally, gcc makes non-vectorized asm that does it conditionally! So not only does GCC block vectorization, it changes the exception semantics vs. the C abstract machine.) -fno-trapping-math enables the expected optimization.
Pass the option -fno-math-errno to gcc. This fixes the problem without making your code unportable or leaving the realm of ISO/IEC 9899:2011 (C11).
What this option does is not attempting to set errno when a math library function fails:
-fno-math-errno
Do not set "errno" after calling math functions that are executed
with a single instruction, e.g., "sqrt". A program that relies on
IEEE exceptions for math error handling may want to use this flag
for speed while maintaining IEEE arithmetic compatibility.
This option is not turned on by any -O option since it can result
in incorrect output for programs that depend on an exact
implementation of IEEE or ISO rules/specifications for math
functions. It may, however, yield faster code for programs that do
not require the guarantees of these specifications.
The default is -fmath-errno.
On Darwin systems, the math library never sets "errno". There is
therefore no reason for the compiler to consider the possibility
that it might, and -fno-math-errno is the default.
Given that you don't seem to be particularly interested in math routines setting errno, this seems like a good solution.
Without any global options, here is a (low-overhead, but not free) way to get a square root with no branch:
#include <immintrin.h>
float test(float x)
{
return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set1_ps(x * x)));
}
(on godbolt)
As usual, Clang is smart about its shuffles. GCC and MSVC lag behind in that area, and don't manage to avoid the broadcast. MSVC is doing some mysterious moves as well..
There are other ways to turn a float into an __m128, for example _mm_set_ss. For Clang that makes no difference, for GCC that makes the code a little bigger and worse (including a movss reg, reg which counts as a shuffle on Intel, so it doesn't even save on shuffles).
After about a week, I asked on the matter on GCC Bugzilla & they've provided a solution which is the closest to what I had in mind
float test (float x)
{
float y = x*x;
if (std::isless(y, 0.f))
__builtin_unreachable();
return std::sqrt(y);
}
that compiles to the following assembly:
test(float):
mulss xmm0, xmm0
sqrtss xmm0, xmm0
ret
I'm still not quite sure what exactly happens here, though.

Adding double precision values yield different results between separate programs in C++

I have a question about floating point addition. I understand how compilers and processor architecture can lead to floating point arithmetic values. I have seen many questions on here similar to my question, but they all have some variation such as different compiler, different code, different machine, etc. However, I'm am running into an issue when adding doubles in the exact same way in two different programs calling the identical function with the same arguments and it is leading to different results. Both programs are compiled on the same machine with the same compiler/tags. The code looks similar to this:
void function(double tx, double ty, double tz){
double answer;
double x,y;
x = y = answer = 0;
x = tx - ty;
y = ty - tz;
answer = (tx + ty + tz) * (x*y)
}
The values of:
tx,ty,tz
are on the order of [10e-15,10e-30]. Obviously this is a very simplified version of the functions I am actually using, but, is it possible for two programs, running identical floating point arithmetic (not just the same function, the exact same code), on the same machine, with the same compiler/tags, to get different results for the function?
Some possibilities:
The source code of function is identical in the two programs, but it appears with different context, resulting in the compiler compiling it in different ways. For example, the compiler might inline it in one place and not another, and inlining might lead to some expression reduction due to combination with other expressions at the point of the inlined call, and hence different arithmetic is performed. (To test this, move function to a separate source file, compile it separately, and link it with a linker without cross-module optimization. Also, try compiling with optimization disabled.)
You think there are identical inputs to function because they appear the same when printed or viewed in the debugger, but they are actually different due to small differences in the low digits that are not printed. (To test this, print the full values using the hexadecimal floating-point format. To do that, insert std::hexfloat into the output stream, followed by floating-point values. Alternately, use a C printf using the %a format.)
Something else in the programs changes floating-point state, such as rounding mode.
You think you have used an identical compiler, identical sources, identical compilation switches, and so on, but actually have not.
David Schwartz notes that floating-point values can change when they are stored, as occurs when they are simply spilled to the stack. This occurs because some processors and C++ implementations may store floating-point values with extended precision in registers but less precision in memory. Technically, this fits into either 1. (different computation nominally inside function) or 2. (different values passed to function), but it is insidious enough to warrant separate mention.
Well the answer is quite easy. If your computer behaves deterministic it will always return the same results for the same input. That's the basic idea behind programming languages so far. (Unless we are talking about quantum computers, of course.)
So the question reduces to whether you really have the same input.
Although the above function looks strictly functional, there are often hidden inputs that are not that obvious. E.g. you might adjust the rounding mode of your FPU before calling the function. Or you might setup different exception behavior. In both cases the function may behave differently for certain inputs.
So even if your computer isn't non-deterministic (i.e. buggy) the above function might return different results. Although it is not that likely.

Extent of G++ compiler optimization on non-commutative operations

I am concerned about the G++ optimizer's effect on arithmetic operations, specifically integer operations that are not necessarily commutative, eg * and /. This concern arose when I looked at a simple function in gdb that had been compiled with the -O3 flag set; it was all in all a better function, but it's form was completely different then what it had been with no optimization, operations had been removed, and some had been relocated. Here is a simple function with which I will demonstrate the crux of my concern;
int ClipLower(int num, int dig){
int Mult10 = 1;
while (dig != 0){
Mult10 *= 10, dig--;
}
return ((num / Mult10) * Mult10);
}
This function simply clips off the base10 digits below digit 'dig'. My concern is, does the compiler consider things like the fact that math on integers is non-commutative? So, will the compiler try to reduce (num / mult10) * mult10 into num * 1, and of course discard the one?
I am aware that volatile will avoid this situation, but I would still like my code optimized as much as possible. So in essence I am asking if the gnu optimizer will understand that integer math is non-communicative, and further more how much of a concern optimization-gone-awry really is.
also
here is the disassembly for the function at -O4, as you can see, the order of operations is fine
13 return ((num / Mult10) * Mult10);
cltd
idiv %ecx
imul %ecx,%eax
ret
amusingly, the compiler generated a load of no-operations following the function, presumably as padding because it ended up so small.
Here is the list of flags that -O3 in g++ is equivalent to: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
Now if you look carefully, there is also -Ofast which is defined as -O3 + some other, especially -ffast-math. In description of -ffast-math you can read:
This option is not turned on by any -O option besides -Ofast since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that do not require the guarantees of these specifications.
This is done precisely to ensure default compiler flags do not violate rounding error and other floating point standard specifications.
There is also a related question on SO, why don't compilers optimize a*a*a*a*a*a to (a*a*a)^2, the answer is the same. (I cannot find the link atm =/)
Btw, Mult10 *= 10, dig--; are you trying to lose people following your code? =D
EDIT: Another by the way, going over -O3 has no effect. Except that some people say you might overflow some internal variable. I didn't test the overflow but I'm sure -O4 and -O100 are equivalent to -O3 at this point of writing this.
Try it and look at the assembly
Optimization should not effect output, only speed. Rounding should be maintained. But bugs can occur, although much more rarely nowadays.
Generally issues are more likely with floating point. 2/7 with floats might vary slightly.
With ints it should always be 0, no matter what optimization, even if it is multiplied by 7.

C++ handling of excess precision

I'm currently looking at code which does multi-precision floating-point arithmetic. To work correctly, that code requires values to be reduced to their final precision at well-defined points. So even if an intermediate result was computed to an 80 bit extended precision floating point register, at some point it has to be rounded to 64 bit double for subsequent operations.
The code uses a macro INEXACT to describe this requirement, but doesn't have a perfect definition. The gcc manual mentions -fexcess-precision=standard as a way to force well-defined precision for cast and assignment operations. However, it also writes:
‘-fexcess-precision=standard’ is not implemented for languages other than C
Now I'm thinking about porting those ideas to C++ (comments welcome if anyone knows an existing implementation). So it seems I can't use that switch for C++. But what is the g++ default behavior in absence of any switch? Are there more C++-like ways to control the handling of excess precision?
I guess that for my current use case, I'll probably use -mfpmath=sse in any case, which should not incur any excess precision as far as I know. But I'm still curious.
Are there more C++-like ways to control the handling of excess precision?
The C99 standard defines FLT_EVAL_METHOD, a compiler-set macro that defines how excess precision should happen in a C program (many C compilers still behave in a way that does not exactly conform to the most reasonable interpretation of the value of FP_EVAL_METHOD that they define: older GCC versions generating 387 code, Clang when generating 387 code, …). Subtle points in relation with the effects of FLT_EVAL_METHOD were clarified in the C11 standard.
Since the 2011 standard, C++ defers to C99 for the definition of FLT_EVAL_METHOD (header cfloat).
So GCC should simply allow -fexcess-precision=standard for C++, and hopefully it eventually will. The same semantics as that of C are already in the C++ standard, they only need to be implemented in C++ compilers.
I guess that for my current use case, I'll probably use -mfpmath=sse in any case, which should not incur any excess precision as far as I know.
That is the usual solution.
Be aware that C99 also defines FP_CONTRACT in math.h that you may want to look at: it relates to the same problem of some expressions being computed at a higher precision, striking from a completely different side (the modern fused-multiply-add instruction instead of the old 387 instruction set). This is a pragma to decide whether the compiler is allowed to replace source-level additions and multiplications with FMA instructions (this has the effect that the multiplication is virtually computed at infinite precision, because this is how this instruction works, instead of being rounded to the precision of the type as it would be with separate multiplication and addition instructions). This pragma has apparently not been incorporated in the C++ standard (as far as I can see).
The default value for this option is implementation-defined and some people argue for the default to be to allow FMA instructions to be generated (for C compilers that otherwise define FLT_EVAL_METHOD as 0).
You should, in C, future-proof
your code with:
#include <math.h>
#pragma STDC FP_CONTRACT off
And the equivalent incantation in C++ if your compiler documents one.
what is the g++ default behavior in absence of any switch?
I am afraid that the answer to this question is that GCC's behavior, say, when generating 387 code, is nonsensical. See the description of the situation that motivated Joseph Myers to fix the situation for C. If g++ does not implement -fexcess-precision=standard, it probably means that 80-bit computations are randomly rounded to the precision of the type when the compiler happened to have to spill some floating-point registers to memory, leading the program below to print "foo" in some circumstances outside the programmer's control:
if (x == 0.0) return;
... // code that does not modify x
if (x == 0.0) printf("foo\n");
… because the code in the ellipsis caused x, that was held in an 80-bit floating-point register, to be spilt to a 64-bit slot on the stack.
But what is the g++ default behavior in absence of any switch?
I found one answer myself via an experiment, using the following code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
double a = atof("1.2345678");
double b = a*a;
printf("%.20e\n", b - 1.52415765279683990130);
return 0;
}
If b is rounded (-fexcess-precision=standard), then the result is zero. Otherwise (-fexcess-precision=fast) it is something like 8e-17. Compiling with -mfpmath=387 -O3, I could reproduce both cases for gcc-4.8.2. For g++-4.8.2 I get an error for -fexcess-precision=standard if I try that, and without a flag I get the same behavior as -fexcess-precision=fast gives for C. Adding -std=c++11 does not help. So now the suspicion already voiced by Pascal is official: g++ does not necessarily round everywhere it should.

What is floating point speculation and how does it differ from the compiler's floating point model

The Intel C++ compiler provides two options for controlling floating point:
-fp-speculation (fast/safe/strict/off)
-fp-model (precise/fast/strict and source/double/extended)
I think I understand what fp-model does. But what is fp-speculation and how does it relate to fp-model? I have yet to find any intel doc which explains this!
-fp-model influences how floating-point computations are carried out, and can change the numeric result (by licensing unsafe optimizations or by changing the precision at which intermediate results are evaluated).
-fp-speculation does not change the numerical results, but can effect what floating-point flags are raised by an operation (or what traps are taken if floating-point traps are enabled). 99.99% of programmers don't need care about these things, so you can probably run with the default and not worry about it.
Here's a concrete example; suppose you have the following function:
double foo(double x) {
// lots of computation
if (x >= 0) return sqrt(x);
else return x;
}
sqrt is, relatively speaking, slow. It would be nice to hoist the computation of sqrt(x) like this:
double foo(double x) {
const double sqrtx = sqrt(x);
// lots of computation
if (x >= 0) return sqrtx;
else return x;
}
By doing this, we allow the computation of sqrt to proceed simultaneously with other computations, reducing the latency of our function. However, there's a problem; if x is negative, then sqrt(x) raises the invalid flag. In the original program, this could never happen, because sqrt(x) was only computed if x was non-negative. In the modified program, sqrt(x) is computed unconditionally. Thus, if x is negative, the modified program raises the invalid flag, whereas the original program did not.
The -fp-speculation flag gives you a way to tell the compiler whether or not you care about these cases, so it knows whether or not it is licensed to make such transformations.
Out of order execution and speculative execution can result in extraneous exceptions or raise exceptions at the wrong time.
If that matters to you, you can use the fp-speculation option to control speculation of floating-point instructions.
For (a little bit) more information: http://software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/lin/compiler_f/copts/common_options/option_fp_speculation.htm
On Windows OS:
1.Intel compiler floating calculation 32 bit application vs 64 bit application , same code Can give to you different result!!!! No matter what flag you choose:)!!!!
2.Visual studio compiler floating calculation 32 bit vs 64 bit application , same code output same result.