Why only add?
No need to ask, he's a Smooth operator, smooth operator, smooth operator, smooth operator.
We have seen how to implement a generic sum. If we want to compute the maximum of a sequence, we know what to do:
template<typename Iterator, typename T>
T
max(Iterator a, Iterator a_end, value<T> init)
{
T res = init;
for(; a != a_end; ++a)
res = std::max(res, *a);
return res;
}
Stop, Stop, STOP!
Can't we achieve this in a simpler way?
We can see that max
is structurally identical to sum.
Except the line computing the maximum of two operands instead of their sum.
By consequence, if we parametrize this operation as well,
we obtain a generic function which can do both (and much more ...).
template<typename Iterator, typename T, typename BinOp>
T reduce(Iterator begin, Iterator end, value<T> init, BinOp op)
{
T res = init;
for(; begin != end; ++begin)
res = op(res,*begin);
return res;
}
Using reduce
We get back our sum,
when we pass the built-in addition operator to reduce:
double a[N] = { ... };
double suma = reduce(a, a+N, 0.0, std::plus<double>());
The only difference to our sum implementations
is, that now
res = res + *begin is called
instead of res += *begin.
For built-in types the compiler should produce identical code,
but for user-defined types this can be a performance loss.
This is a topic for a different article.
Of course, products can be computed in exactly the same way:
matrix4 pose = reduce(matrices.begin(), matrices.end(), matrix4::unit(), std::multiplies<matrix4>());
For computing the maximum, we should be able to use std::max ...?
Yes, but with the difference that std::max is a function template and std::plus
is a class template, thus the syntax is slightly different:
double a[N] = { ... };
double maxa = reduce(a, a+N, ???, std::max<double>);
Um ... what about init?
Is there a neutral element for maximum?
Times stay interesting ...