Consider the two following functions:
std::pair<double,Vector> myMatrixOperation1(Matrix const& A, Vector const& V) {
Vector AV = A*V;
double norm_A_V = std::sqrt(dot(V,AV));
return make_pair(norm_A_V,AV);
}
std::pair<double,Vector> myMatrixOperation2(Matrix const& A, Vector const& V) {
return make_pair( norm(V,A) , A*V );
}
double norm(Vector const& V, Matrix const& innerProductMatrix) {
double norm_A_V = std::sqrt(dot(V,innerProductMatrix*V));
}
They obviously do the same thing, except that the Matrix-Vector product is garanteed to be computed only once in the first function.
However, the second function is more readable because it was refactored in order to have a complete separation of concerns: the concept of the norm of a vector with respect to an arbitrary inner product was abstracted into a separate function.
Now the problem is that without any optimisation, the Matrix-Vector product is now computed twice.
My question is the following: Is the compiler smart enought to compute the Matrix-Vector product only once ? And if yes, what do I need to do ?
I suppose that at least I need to inline the norm() function. Also, regarding operator*(Matrix const& A, Vector const& V), is lazy evaluation of any help ? (Side-note: I am using the Eigen Library)
Note: I am aware of a similar question: Will the compiler optimize repeated math computations?. However, please note that my problem is harder for the compiler, since operator*(Matrix const& A, Vector const& V) is not a built-in, and hence the compiler should need some garantees about it
Edit:
After further thinking an this citation from Wikipedia (http://en.wikipedia.org/wiki/Optimizing_compiler):
For example, in some languages functions are not permitted to have side effects. Therefore, if a program makes several calls to the same function with the same arguments, the compiler can immediately infer that the function's result need be computed only once. In languages where functions are allowed to have side effects, another strategy is possible. The optimizer can determine which function has no side effects, and restrict such optimizations to side effect free functions. This optimization is only possible when the optimizer has access to the called function.
it seems like the compiler can replace the second function by the first one provided operator+ is pure (that is: no side effect). According to https://stackoverflow.com/a/5464114/1583122, in C++, purity can be garanteed to the compiler by telling it that a function is constexpr, has only constexpr function calls, and has const arguments. So I think it would be possible for a compiler to garantee such an optimization, provided some requirements are met. Further, note that restrictions on constexpr functions have been greatly reduced in C++14