These functions are found in the #include <numeric> library. In this document, let T represent any type name.
This function assigns initial assigns *itr_first = initial and then for each successive entry, that entry is assigned the result after performing ++initial.
Thus, by default, assuming that the iterators are referring to a container storing int,
std::iota( itr_first, itr_last, 0 );
fills the entries of the range with $0, 1, 2, 3, \ldots$. The algorithm can be implemented as follows:
while ( itr_first != itr_last ) { *itr_first = initial; ++itr_first; ++initial; }
These calculates an inner product and are equivalent to:
while ( itr_1_first != itr_1_last ) { // First declaration initial += *itr_1_first * *itr_2_first; // Second declaration // initial = plus( initial, multiplies( *itr_1_first, *itr_2_first ) ); ++itr_1_first; ++itr_2_first; }
Note that we assume that there are sufficiently many entries in the range starting at itr_2_first.
Note that the following are equivalent calls if we #include <functional> with
std::cout << std::inner_product( itr_1_first, itr_1_last, itr_2_first, initial ) << std::endl; std::cout << std::inner_product( itr_1_first, itr_1_last, itr_2_first, initial, std::multiplies<T>(), std::plus<T>() ) << std::endl;
These function adds the values on the range to the initial value. They are equivalent to:
while ( itr_first != itr_last ) { // First declaration initial += *itr_first // Second declaration // initial = plus( initial, *itr_first ); ++itr_first; }
The following two are equivalent:
std::cout << std::accumulate( itr_first, itr_last, initial ) << std::endl; std::cout << std::accumulate( itr_first, itr_last, initial, std::plus<T>() ) << std::endl;
These functions are similar to std::accumulate, but the operations can be spread across multiple threads; thus, half the range may be added on one core, the other half on another, and then the results are added to initial. If a function is passed, it must be both commutative and associative: that is,
plus( x, y ) == plus( y, x ) plus( x, plus( y, z ) ) == plus( plus( x, y ), z )
The function "plus" is often described to as the "reduction".
These are similar to std::inner_product, only they can be run in parallel. The function plus(...) must be both commutative and associative. Very often, the function "multiplies" is called "transform" and the function "plus" is called the "reduction"; hence the name of the function.
This is similar to std::accumulate, only the function transform(...) is applied to each entry of the range before it is passed to reduce(...), the function that parallels plus(...) in std::accumulate. The function reduce(...) must be both commutative and associative.
The returned iterator defines the right-hand side of the range encompassing the output.
This calculates a partial sum, copying the partial sum to the location specified by itr_out. It is equivalent to:
// Assuming the range is not empty T value{ *itr_first }; *itr_out = value; ++itr_first; ++itr_out; while ( itr_first != itr_last ) { // First declaration value += *itr_first; // Second declaration // value = plus( value, *itr_first ); *itr_out = value; ++itr_first; ++itr_out; }
The returned iterator defines the right-hand side of the range encompassing the output.
This is similar to partial sum, but can be performed in parallel and is slightly more general. The first is equivalent to:
// Assuming the range is not empty T value{ *itr_first }; *itr_out = value; ++itr_first; ++itr_out; while ( itr_first != itr_last ) { // First declaration value += *itr_first; // Second declaration // value = plus( value, *itr_first ); *itr_out = value; ++itr_first; ++itr_out; }
The third is equivalent to:
while ( itr_first != itr_last ) { // Third declaration initial = plus( initial, *itr_first ); *itr_out = initial; ++itr_first; ++itr_out; }
The first can be implemented as the third using std::plus<T>() and 0, while the second can be implemented as the third so long as the initial value is the identity element for the function at hand; for example, 0 for std::plus and 1 for std::multiplies.
The returned iterator defines the right-hand side of the range encompassing the output.
For example, the output of
std::vector<int> u{ 2, 3, 2, 3, 1, 1, 2, 3, 5, 2 }; std::cout << u << std::endl; std::vector<int> v( 10 ); std::inclusive_scan( u.begin(), u.end(), v.begin() ); std::cout << v << std::endl; std::inclusive_scan( u.begin(), u.end(), v.begin(), std::multiplies<int>() ); std::cout << v << std::endl; std::inclusive_scan( u.begin(), u.end(), v.begin(), std::multiplies<int>(), 100 ); std::cout << v << std::endl;
is
{2, 3, 2, 3, 1, 1, 2, 3, 5, 2} {2, 5, 7, 10, 11, 12, 14, 17, 22, 24} {2, 6, 12, 36, 36, 36, 72, 216, 1080, 2160} {200, 600, 1200, 3600, 3600, 3600, 7200, 21600, 108000, 216000}
This is similar to partial sum, but can be performed in parallel and is slightly more general. The first is equivalent to:
while ( itr_first != itr_last ) { *itr_out = initial; // First declaration initial += *itr_first; // Second declaration // initial = plus( initial, *itr_first ); ++itr_first; ++itr_out; }
The third is equivalent to:
while ( itr_first != itr_last ) { // Third declaration initial = plus( initial, *itr_first ); *itr_out = initial; ++itr_first; ++itr_out; }
The first can be implemented as the third using std::plus<T>() and 0, while the second can be implemented as the third so long as the initial value is the identity element for the function at hand; for example, 0 for std::plus and 1 for std::multiplies.
The returned iterator defines the right-hand side of the range encompassing the output. Note that the last entry in the original range does not affect the output.
For example, the output of
std::vector<int> u{ 2, 3, 2, 3, 1, 1, 2, 3, 5, 2 }; std::cout << u << std::endl; std::vector<int> v( 10 ); std::exclusive_scan( u.begin(), u.end(), v.begin(), 17 ); std::cout << v << std::endl; std::exclusive_scan( u.begin(), u.end(), v.begin(), 17, std::multiplies<int>() ); std::cout << v << std::endl;
is
{2, 3, 2, 3, 1, 1, 2, 3, 5, 2} {17, 19, 22, 24, 27, 28, 29, 31, 34, 39} {17, 34, 102, 204, 612, 612, 612, 1224, 3672, 18360}
Assuming that the input ranges are not empty, these copy the first entry of the input to the first entry of the output, and all subsequent entries of the output are the difference between the corresponding entry in the input range minus the previous entry in the input range.
These are equivalent to:
// Assuming the range is not empty T last{ *itr_first }; *itr_out = last; ++itr_first; while ( itr_first != itr_last ) { T next{ *itr_first }; // First declaration *itr_out = next - last; // Second declaration // *itr_out = minus( next, last ); last = next; ++itr_first; ++itr_out; }