Thinking in C++ Vol 2 - Practical Programming |

Prev |
Home |
Next |

These algorithms are all tucked into the header **<numeric>**,
since they are primarily useful for performing numeric calculations.

T **accumulate**(InputIterator first, InputIterator last, T

result);

T **accumulate**(InputIterator first, InputIterator last, T

result, BinaryFunction f);

The first form is a generalized summation; for each element
pointed to by an iterator **i** in **[first, last)**, it performs the
operation **result = result + *i**, where **result** is of type **T**.
However, the second form is more general; it applies the function **f(result,
*i)** on each element ***i** in the range from beginning to end.

Note the similarity between the second form of **transform( )**
and the second form of **accumulate( )**.

T **inner_product**(InputIterator1 first1, InputIterator1

last1, InputIterator2 first2, T init);

T **inner_product**(InputIterator1 first1, InputIterator1

last1, InputIterator2 first2, T init, BinaryFunction1

op1, BinaryFunction2 op2);

Calculates a generalized inner product of the two ranges **[first1,
last1)** and **[first2, first2 + (last1 - first1))**. The return value is
produced by multiplying the element from the first sequence by the parallel
element in the second sequence and then adding it to the sum. Thus, if you have
two sequences **{1, 1, 2, 2}** and **{1, 2, 3, 4}**, the inner product
becomes

(1*1) + (1*2) + (2*3) + (2*4)

which is 17. The **init** argument is the initial value
for the inner product this is probably zero but may be anything and is especially
important for an empty first sequence, because then it becomes the default
return value. The second sequence must have at least as many elements as the
first.

The second form simply applies a pair of functions to its
sequence. The **op1** function is used in place of addition and **op2**
is used instead of multiplication. Thus, if you applied the second version of **inner_product( )**
to the sequence, the result would be the following operations:

init = op1(init, op2(1,1));

init = op1(init, op2(1,2));

init = op1(init, op2(2,3));

init = op1(init, op2(2,4));

Thus, it s similar to **transform( )**, but two
operations are performed instead of one.

OutputIterator **partial_sum**(InputIterator first,

InputIterator last, OutputIterator result);

OutputIterator **partial_sum**(InputIterator first,

InputIterator last, OutputIterator result,

BinaryFunction op);

Calculates a generalized partial sum. A new sequence is
created, beginning at **result**. Each element is the sum of all the
elements up to the currently selected element in **[first, last)**. For
example, if the original sequence is **{1, 1, 2, 2, 3}**, the generated
sequence is **{1, 1 + 1, 1 + 1 + 2, 1 + 1 + 2 + 2, 1 + 1 + 2 + 2 + 3}**,
that is, **{1, 2, 4, 6, 9}**.

In the second version, the binary function **op** is used
instead of the **+** operator to take all the summation up to that point
and combine it with the new value. For example, if you use **multiplies<int>( )**
as the object for the sequence, the output is **{1, 1, 2, 4, 12}**. Note
that the first output value is always the same as the first input value.

The return value is the end of the output range **[result,
result + (last - first) )**.

OutputIterator **adjacent_difference**(InputIterator first,

InputIterator last, OutputIterator result);

OutputIterator **adjacent_difference**(InputIterator first,

InputIterator last, OutputIterator result, BinaryFunction

op);

Calculates the differences of adjacent elements throughout
the range **[first, last)**. This means that in the new sequence, the value
is the value of the difference of the current element and the previous element
in the original sequence (the first value is unchanged). For example, if the
original sequence is **{1, 1, 2, 2, 3}**, the resulting sequence is **{1, 1
1, 2 1, 2 2, 3 2}**, that is: **{1, 0, 1, 0, 1}**.

The second form uses the binary function **op** instead
of the ** ** operator to perform the differencing. For example, if you
use **multiplies<int>( )** as the function object for the
sequence, the output is **{1, 1, 2, 4, 6}**.

The return value is the end of the output range **[result,
result + (last - first) )**.

#### Example

This program tests all the algorithms in **<numeric>**
in both forms, on integer arrays. You ll notice that in the test of the form
where you supply the function or functions, the function objects used are the
ones that produce the same result as form one, so the results will be exactly
the same. This should also demonstrate a bit more clearly the operations that
are going on and how to substitute your own operations.

//: C06:NumericTest.cpp

#include <algorithm>

#include <iostream>

#include <iterator>

#include <functional>

#include <numeric>

#include "PrintSequence.h"

using namespace std;

int main() {

int a[] = { 1, 1, 2, 2, 3, 5, 7, 9, 11, 13 };

const int ASZ = sizeof a / sizeof a[0];

print(a, a + ASZ, "a", " ");

int r = accumulate(a, a + ASZ, 0);

cout << "accumulate 1: " << r
<< endl;

// Should produce the same result:

r = accumulate(a, a + ASZ, 0, plus<int>());

cout << "accumulate 2: " << r
<< endl;

int b[] = { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2 };

print(b, b + sizeof b / sizeof b[0], "b",
" ");

r = inner_product(a, a + ASZ, b, 0);

cout << "inner_product 1: " <<
r << endl;

// Should produce the same result:

r = inner_product(a, a + ASZ, b, 0,

plus<int>(), multiplies<int>());

cout << "inner_product 2: " <<
r << endl;

int* it = partial_sum(a, a + ASZ, b);

print(b, it, "partial_sum 1", "
");

// Should produce the same result:

it = partial_sum(a, a + ASZ, b, plus<int>());

print(b, it, "partial_sum 2", "
");

it = adjacent_difference(a, a + ASZ, b);

print(b, it, "adjacent_difference 1","
");

// Should produce the same result:

it = adjacent_difference(a, a + ASZ, b, minus<int>());

print(b, it, "adjacent_difference 2","
");

} ///:~

Note that the return value of **inner_product( )**
and **partial_sum( )** is the past-the-end iterator for the resulting
sequence, so it is used as the second iterator in the **print( )**
function.

Since the second form of each function allows you to provide
your own function object, only the first form of the function is purely
numeric. You could conceivably do things that are not intuitively numeric
with **inner_product( )**.

Thinking in C++ Vol 2 - Practical Programming |

Prev |
Home |
Next |