0
votes

I need to compute some fairly long expressions that contain common subexpressions. For example, consider the following two expressions:

double dfdx1 = 2 * (-x2 + x1 - sin(b2)*n34 + cos(b2)*sin(c2)*n24 - cos(b2)*cos(c2)*n14 + sin(b1)*m34 - cos(b1)*sin(c1)*m24 + cos(b1)*cos(c1)*m14);

double dfdx2 = -2 * (-x2 + x1 - sin(b2)*n34 + cos(b2)*sin(c2)*n24 - cos(b2)*cos(c2)*n14 + sin(b1)*m34 - cos(b1)*sin(c1)*m24 + cos(b1)*cos(c1)*m14);

Aside from eliminating all the trigonometric functions, one obvious elimination is dfdx2 = -dfdx1. The question is whether the compiler will recognise this. I found that using MATLAB's MuPad generate::optimize() function does not, which rather surprised me.

More generally, will the compiler recognise that f2 = -f1 in the example below:

double f1 = a*a + b*b - c*a - c*b;
double f2 = c*a + c*b - a*a - b*b;

Or will it just eliminate the terms a*a, b*b, c*a and c*b?

I am using the MSVC compiler, but I guess that they all do pretty much the same thing.

1

1 Answers

4
votes

Normally compilers should recognize this and carry out the asked transformation if you enable "fast math" (-ffast-math for gcc). The reason is that floating point operations are not perfectly exact and the order of the evaluation of an expression might matter.

Example (for doubles, all constants are actually considered being results of other operations):

"1e100"+"1.0"-"1e100" results in 0.0 

"1e100"-"1e100"+"1.0" results in 1.0

So the compiler will only reorder expressions if you explicitly allow such transformations.