I am looking for ways to force gcc to respect a particular order of operations (it does not have to be the order that minimizes floating point error, just whatever order I happen to want) regarding double-precision arithmetic of a particular section of code, while allowing full -O3 -funsafe-math-optimizations
elsewhere. I have seen a few posts on this matter:
Are floating point operations in C associative?
https://devblogs.microsoft.com/cppblog/do-you-prefer-fast-or-precise/
The above links discuss global options, but I'd like to understand if local compiler directives exist. For example, when doing hardware synthesis, it is possible to force the compiler to synthesize a logical expression verbatim without doing any reduction.
For example, consider
#include <iostream>
#include <string>
#include <iomanip>
using std::cout;
int main()
{
double a = 1.0 + 1.3e-16;
double b = 1.0;
double c = 100.0;
double d = (a - b) / c;
double e = a / c - b / c;
cout << std::scientific;
cout << "Calculation d = " << d << "\n";
cout << "Calculation e = " << e << "\n";
double f = 1.0;
double g = 2e-15;
double h = 1.0;
double i = 1e-15;
double j = (f + g) - (h + i);
double k = (f - h) + (g - i);
double m = f + g - h - i;
double n = f - h + g - i;
cout << "Calculation j = " << j << "\n";
cout << "Calculation k = " << k << "\n";
cout << "Calculation m = " << m << "\n";
cout << "Calculation n = " << n << "\n";
}
Using http://cpp.sh, I get
Calculation d = 2.220446e-18
Calculation e = 1.734723e-18
Calculation j = 8.881784e-16
Calculation k = 1.000000e-15
Calculation m = 9.984014e-16
Calculation n = 1.000000e-15
This was independent of the optimization level I used, so it seems that the compiler will calculate things in the order I expect based on the expression, plus even maintains left-right order for the +/- But is this absolutely guaranteed, when optimizations are turned on?
I can think of a scenario for example where one of the operands is already sitting in some useful register whereby it would save some memory move to compute things in a different order than I wrote, but would maintain symbolic correctness.
Basically I can't begin to try different hacks to fix the issue, e.g., I read that declaring sub-products as volatile variables would help, since my example doesn't show the problem. So I'd like to know if this is indeed a non-problem, or if not, what tricks exist.