I am doing some numerical optimization on a scientific application. One thing I noticed is that GCC will optimize the call pow(a,2)
by compiling it into a
Library functions like "pow" are usually carefully crafted to yield the minimum possible error (in generic case). This is usually achieved approximating functions with splines (according to Pascal's comment the most common implementation seems to be using Remez algorithm)
fundamentally the following operation:
pow(x,y);
has a inherent error of approximately the same magnitude as the error in any single multiplication or division.
While the following operation:
float a=someValue;
float b=a*a*a*a*a*a;
has a inherent error that is greater more than 5 times the error of a single multiplication or division (because you are combining 5 multiplications).
The compiler should be really carefull to the kind of optimization it is doing:
pow(a,6)
to a*a*a*a*a*a
it may improve performance, but drastically reduce the accuracy for floating point numbers.a*a*a*a*a*a
to pow(a,6)
it may actually reduce the accuracy because "a" was some special value that allows multiplication without error (a power of 2 or some small integer number)pow(a,6)
to (a*a*a)*(a*a*a)
or (a*a)*(a*a)*(a*a)
there still can be a loss of accuracy compared to pow
function.In general you know that for arbitrary floating point values "pow" has better accuracy than any function you could eventually write, but in some special cases multiple multiplications may have better accuracy and performance, it is up to the developer choosing what is more appropriate, eventually commenting the code so that noone else would "optimize" that code.
The only thing that make sense (personal opinion, and apparently a choice in GCC wichout any particular optimization or compiler flag) to optimize should be replacing "pow(a,2)" with "a*a". That would be the only sane thing a compiler vendor should do.