Previous fileTop of DocumentContentsIndex pageNext file
Apache C++ Standard Library User's Guide

13.6 Scalar-Producing Algorithms

The next category of algorithms reduces an entire sequence to a single scalar value. Remember that two of these algorithms, std::accumulate() and std::inner_product(), are declared in the <numeric> header file, not the <algorithm> header file as are the other generic algorithms.


NOTE -- The example functions described in the following sections are in the file alg5.cpp.

13.6.1 Count the Number of Elements That Satisfy a Condition

The algorithms std::count() and std::count_if() are used to discover the number of elements that match a given value or that satisfy a given predicate, respectively. Each algorithm comes in two forms. The newer form returns the number of matches found, while the older one takes as argument a reference to a counting value, typically an integer, and increments this value. In the latter case the std::count() function itself yields no value.

The newer form of these functions is currently mandated by the standard. The older form is retained for two reasons: first, for backward compatibility, since older versions of the standard contained it; and second, because the newer form requires that a compiler support partial specialization, which most (but not all) compilers now do.

The example code fragment illustrates the use of the older form of these algorithms. The call on std::count() counts the number of occurrences of the letter e in a sample string, while the invocation of std::count_if() counts the number of vowels.

Note that if your compiler does not support partial specialization, you don't have the form of the std::count() algorithms that return the sum as a function result, but only the form that adds to the last argument in its parameter list, which is passed by reference. This means successive calls on these functions can be used to produce a cumulative sum. This also means that you must initialize the variable passed to this last argument location prior to calling one of these algorithms.

13.6.2 Reduce Sequence to a Single Value

The result generated by the std::accumulate() algorithm is the value produced by placing a binary operator between each element of a sequence, and evaluating the result. By default the operator is the addition operator, operator+, but this can be replaced by any binary function. An initial value or identity must be provided. This value is returned for empty sequences, and is otherwise used as the left argument for the first calculation.

The example program illustrates the use of std::accumulate() to produce the sum and product of a vector of int values. In the first case the identity is zero, and the default operator+() is used. In the second invocation, the identity is 1, and the multiplication operator named times is explicitly passed as the fourth argument:

Neither the identity value nor the result of the binary function is required to match the container type. This is illustrated in the example program by the invocation of std::accumulate() shown in the second example above. Here the identity is an empty list. The function, shown after the example program, takes as argument a list and an int value, and repeatedly inserts values into the list. The values inserted represent a decreasing sequence from the argument down to 1. For the example input, the same vector as in the first example, the resulting list contains the 15 values 1 2 1 3 2 1 4 3 2 1 5 4 3 2 1.

13.6.3 Generalized Inner Product

Assume we have two sequences of n elements each: a1, a2, ... an and b1, b2, ... bn. The inner product of the sequences is the sum of the parallel products, that is, the value a1 * b1 + a2 * b2 + ... + an * bn. Inner products occur in a number of scientific calculations. For example, the inner product of a row times a column is the heart of the traditional matrix multiplication algorithm. A generalized inner product uses the same structure, but permits the addition and multiplication operators to be replaced by arbitrary binary functions. The C++ Standard Library includes the following algorithm for computing an inner product:

The first three arguments to the std::inner_product() algorithm define the two input sequences. The second sequence is specified only by the beginning iterator, and is assumed to contain at least as many elements as the first sequence. The next argument is an initial value, or identity, used for the summation operator. This is similar to the identity used in the std::accumulate() algorithm. In the generalized inner product function, the last two arguments are the binary functions that are used in place of the addition operator and the multiplication operator, respectively.

In the example program, the second invocation illustrates the use of alternative functions as arguments. The multiplication is replaced by an equality test, while the addition is replaced by a logical or. The result is true if any of the pairs are equal, and false otherwise. Using an and in place of the or would have resulted in a test which was true only if all pairs were equal; in effect, the same as the equal() algorithm described in the next section.

13.6.4 Test Two Sequences for Pairwise Equality

The std::equal() algorithm tests two sequences for pairwises equality. By using an alternative binary predicate, it can also be used for a wide variety of other pair-wise tests of parallel sequences, such as a pairwise test that returns a boolean result. The std::mismatch() algorithm gives the location of elements that fail that test (Section 13.3.7).

The arguments of the std::equal() algorithm are simple input iterators:

The std::equal() algorithm assumes, but does not verify, that the second sequence contains at least as many elements as the first. A true result is generated if all values test equal to their corresponding element. The alternative version of the algorithm substitutes an arbitrary boolean function for the equality test, and returns true if all pair-wise elements satisfy the predicate. In the sample program, this is illustrated by replacing the predicate with the std::greater_equal() function; in this fashion, true is returned only if all values in the first sequence are greater than or equal to their corresponding value in the second sequence.

13.6.5 Lexical Comparison

A lexical comparison is commonly used to determine the dictionary order of words. In this procedure, the elements or characters of two sequences are compared in pair-wise fashion. As long as characters within a pair match, the algorithm advances to the next pair. When characters within a pair fail to match, the earlier character determines the smaller word. For example, everybody is smaller than everything, since the b in the former word alphabetically precedes the t in the latter. Should one or the other sequence terminate before the other, the terminated sequence is considered the smaller. For example, every precedes both everybody and everything, but comes after eve. Finally, if both sequences terminate at the same time and pair-wise characters match in all cases, the two words are considered equal.

The std::lexicographical_compare() algorithm implements the concept of lexical comparison, returning true if the first sequence is smaller than the second, and false otherwise. The algorithm is generalized to any sequence. Thus, the std::lexicographical_compare() algorithm can be used with arrays, strings, vectors, lists, or any other data structures of the C++ Standard Library.

Unlike most other algorithms that take two sequences as argument, the std::lexicographical_compare() algorithm uses a first and a past-end iterator for both sequences. A variation on the algorithm also takes a fifth argument, which is the binary function used to compare corresponding elements from the two sequences.

The example program illustrates the std::lexicographical_compare() algorithm in use with character sequences, and arrays of integer values.



Previous fileTop of DocumentContentsIndex pageNext file