Beginner's Guide

# Standard Library Numeric OperationsNumeric OperationsNumeric Ops

produce one result based on a sequence of input elements
produce a sequence of results with the same number of elements as the input sequence

### `iota` (fill with ascending numbers)`iota` (fill ascending)iotaC++11

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<int> v;
v.resize(9,0);
// fill subrange (as shown in image)
iota(begin(v)+2, begin(v)+7, 1);
for (int x : v) { std::cout << x << ' '; }  // 0 0 1 2 3 4 5 0 0
std::cout << '\n';
// fill entire vector
iota(begin(v), end(v), 3);
for (int x : v) { std::cout << x << ' '; }  // 3 4 5 6 7 8 9 10 11
std::cout << '\n';
}``````
``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<int> v;
v.resize(5,0);
// NOTE: might not be available yet
// in many standard library implementations!
auto const result = std::ranges::iota(v, 3);
std::cout << result.value << '\n';  // 8
for (int x : v) { std::cout << x << ' '; }  // 3 4 5 6 7
std::cout << '\n';
}``````

### `reduce`reduceC++17

The reduction operation `⊕` must be associative and commutative, because the order in which it is applied is not guaranteed.

``````#include <vector>
#include <iostream>
#include <execution>
#include <numeric>

int main () {std::vector<int> v {1,9,7,3,2,8};
auto const sum = reduce(begin(v), end(v));  // 1+9+7+3+2+8 = 30
std::cout << "sum: " << sum << '\n';auto const s47 = reduce(begin(v), end(v), 47);  // 47+1+9+7+3+2+8 = 77
std::cout << "s47: " << s47 << '\n';std::vector<double> w {2.0, 1.5, 3.0, 1.5};
auto const product = reduce(begin(w), end(w), 1.0, std::multiplies<>{});
// double product = 1.0 * 2.0 * 1.5 * 3.0 * 1.5 = 13.5
std::cout << "product: " << product << '\n';// execute in parallel: #include <execution>
auto const psum = reduce(std::execution::par, begin(v), end(v));
std::cout << "psum: " << psum << '\n';}``````

Make sure that the type of the initial value `ω` is either the same as the input elements' type or a type that can represent more values!

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {// narrower initial value type might // lead to loss of information:
std::vector<double> v {1.2, 2.4};
auto const wtf = reduce(begin(v), end(v), 1);
std::cout << wtf << '\n';  // 4                    int ^
auto const sum = reduce(begin(v), end(v), 1.0);
std::cout << sum << '\n';  // 4.6               double ^^^
}``````

### `transform_reduce`transform_reduceC++17

The reduction operation `⊕` must be associative and commutative and the projection `f` must not have side effects / be stateful, because there is no guaranteed order in which they are applied.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<int> v {3,2,4};
auto f = [](int x) { return x*x; };
auto const rf = transform_reduce(begin(v), end(v), 1, std::plus<>{}, f);
// rf = 1 + f(3) + f(2) + f(4) = 30
std::cout << "rf: " << rf << '\n';
}``````

Both operations `⊕` and `⊗` must be associative and commutative because there is no guaranteed order in which they are applied.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<double> x {1.0, 3.0, 5.0};
std::vector<double> y {2.0, 4.0, 8.0};
auto const rx1 = transform_reduce(begin(x), end(x), begin(y), 10.0);
// rx1 = 10 + (1⋅2)+(3⋅4)+(5⋅8) = 64
std::cout << "rx1: " << rx1 << '\n';auto const rx2 = transform_reduce(
begin(x), end(x), begin(y), 0.0,
std::plus<>{}, std::divides<>{});
// rx2 = 0.0 + (1/2)+(3/4)+(5/8) = 1.875
std::cout << "rx2: " << rx2 << '\n';
}``````

### `accumulate` (≈ `reduce`)accumulateC++98

Prefer C++17's `std::reduce` because it can also be executed in parallel.
Use `accumulate` only with a non-commutative or non-associative reduction operation `⊕`.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<int> v {1,9,7,3,2,8};
auto const sum = accumulate(begin(v), end(v), 0);  // 1+9+7+3+2+8 = 30
std::cout << "sum: " << sum << '\n';auto const s47 = accumulate(begin(v), end(v), 47);  // 47+1+9+7+3+2+8 = 77
std::cout << "s47: " << s47 << '\n';std::vector<double> w {2.0, 1.5, 3.0, 1.5};
auto const product = accumulate(begin(w), end(w), 1.0, std::multiplies<>{});
// double product = 1.0 * 2.0 * 1.5 * 3.0 * 1.5 = 13.5
std::cout << "product: " << product << '\n';
}``````

Make sure that the type of the initial value `ω` is either the same as the input elements' type or a type that can represent more values!

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {// narrower initial value type might // lead to loss of information:
std::vector<double> v {1.2, 2.4};
auto const wtf = accumulate(begin(v), end(v), 0);
std::cout << wtf << '\n';  // 3                  int ^
auto const sum = accumulate(begin(v), end(v), 0.0);
std::cout << sum << '\n';  // 3.6             double ^^^
}``````

### `inner_product` (≈ `transform_reduce`)inner_productC++98

Prefer C++17's `std::transform_reduce` because it can also be executed in parallel.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<int> v {4,3,2,1};
std::vector<int> w {10,20,30,40};
auto const ip = inner_product(begin(v), end(v), begin(w), 50);
// ip = 50 + (4⋅10)+(3⋅20)+(2⋅30)+(1⋅40) = 250
std::cout << "ip: " << ip << '\n';std::vector<double> num {1.0, 3.0, 5.0};
std::vector<double> den {2.0, 4.0, 8.0};
auto const res = inner_product(
begin(num), end(num), begin(den), 0.0,
std::plus<>{}, std::divides<>{} );
// res = 0.0 + (1/2)+(3/4)+(5/8) = 1.875
std::cout << "res: " << res << '\n';
}``````

This means that, e.g., target containers must be resized properly.

Standard algorithms don't – and in most cases can't – check if the target range is large enough.

Trying to copy elements beyond the target's capacity will invoke undefined behavior!

### `adjacent_difference`adjacent_difference

The operation `⊖` must not have side effects / be stateful, because the order in which it is applied is not guaranteed.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<int> in {1,2,6,8,3,6};
// make sure output can fit results
std::vector<int> out;
out.resize(in.size());
for (int x : out) { std::cout << x << ' '; }  // 1 1 4 2 -5 3
std::cout << '\n';
// C++17: can supply custom operation
for (int x : out) { std::cout << x << ' '; }  // 1 3 8 14 11 9
std::cout << '\n';
for (int x : out) { std::cout << x << ' '; }  // 1 2 12 48 24 18
std::cout << '\n';
}``````

### `inclusive_scan`inclusive_scanC++17

The binary operation `⊕` must be associative, because the order in which it is applied is not guaranteed.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<int> in {2,1,7,5,3};
// make sure output can fit results
std::vector<int> out;
out.resize(in.size());
inclusive_scan(begin(in), end(in), begin(out));
for (int x : out) { std::cout << x << ' '; }  // 2 3 10 15 18
std::cout << '\n';
inclusive_scan(begin(in), end(in), begin(out), std::minus<>{});
for (int x : out) { std::cout << x << ' '; }  // 2 1 -6 -11 -14
std::cout << '\n';
// with offset '3':
inclusive_scan(begin(in), end(in), begin(out), std::plus<>{}, 3);
for (int x : out) { std::cout << x << ' '; }  // 5 6 13 18 21
std::cout << '\n';
}``````

### `exclusive_scan`exclusive_scanC++17

The binary operation `⊕` must be associative because the order in which it is applied is not guaranteed.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<int> in {2,1,7,5,3};
// make sure output can fit results
std::vector<int> out;
out.resize(in.size());
exclusive_scan(begin(in), end(in), begin(out), 0);
for (int x : out) { std::cout << x << ' '; }  // 0 2 3 10 15
std::cout << '\n';
// with offset '3':
exclusive_scan(begin(in), end(in), begin(out), 3);
for (int x : out) { std::cout << x << ' '; }  // 3 5 6 13 18
std::cout << '\n';
exclusive_scan(begin(in), end(in), begin(out), 0, std::minus<>{});
for (int x : out) { std::cout << x << ' '; }  // 0 -2 -3 -10 -15
std::cout << '\n';
}``````

### `transform_inclusive_scan`transform_inclusive_scanC++17

The operation `⊕` must be associative and the projection `f` must not have side effects / be stateful, because the order in which they are applied is not guaranteed.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {// returns value only if even and 0 if odd
auto even_only = [](int x) { return (x & 1) ? 0 : x; };
std::vector<int> in {2,1,6,4,3};
// make sure output can fit results
std::vector<int> out;
out.resize(in.size());
transform_inclusive_scan(
begin(in), end(in), begin(out), std::plus<>{}, even_only);
for (int x : out) { std::cout << x << ' '; }  // 2 2 8 12 12
std::cout << '\n';
// with offset '3':
transform_inclusive_scan(
begin(in), end(in), begin(out), std::plus<>{}, even_only, 3);
for (int x : out) { std::cout << x << ' '; }  // 5 5 11 15 15
std::cout << '\n';
// with projection f(x) = -x2:
transform_inclusive_scan(
begin(in), end(in), begin(out), std::plus<>{},
[](int x) { return -(x*x); });
for (int x : out) { std::cout << x << ' '; }  // -4 -5 -41 -57 -66
std::cout << '\n';
}``````

### `transform_exclusive_scan`transform_exclusive_scanC++17

The operation `⊕` must be associative and the projection `f` must not have side effects / be stateful, because the order in which they are applied is not guaranteed.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {// returns value only if even and 0 if odd
auto even_only = [](int x) { return (x & 1) ? 0 : x; };
std::vector<int> in {2,1,6,4,3};
// make sure output can fit results
std::vector<int> out;
out.resize(in.size());
transform_exclusive_scan(
begin(in), end(in), begin(out), 0, std::plus<>{}, even_only);
for (int x : out) { std::cout << x << ' '; }  // 0 2 2 8 12
std::cout << '\n';
// with offset '3':
transform_exclusive_scan(
begin(in), end(in), begin(out), 3, std::plus<>{}, even_only);
for (int x : out) { std::cout << x << ' '; }  // 3 5 5 11 15
std::cout << '\n';
// with projection f(x) = -x2:
transform_exclusive_scan(
begin(in), end(in), begin(out), 0, std::plus<>{},
[](int x) { return -(x*x); });
for (int x : out) { std::cout << x << ' '; }  // 0 -4 -5 -41 -57
std::cout << '\n';
}``````

### `partial_sum` (≈ `inclusive_scan`)partial_sumC++98

Prefer C++17's `std::inclusive_scan` because it can also be executed in parallel.
Use `partial_sum` only, if the reduction operation `⊕` is non-associative.

``````#include <vector>
#include <iostream>
#include <numeric>

int main () {std::vector<int> in {1,1,2,2,1,1};
// make sure output can fit results
std::vector<int> out;
out.resize(in.size());
partial_sum(begin(in), end(in), begin(out));
for (int x : out) { std::cout << x << ' '; }  // 1 2 4 6 7 8
std::cout << '\n';
partial_sum(begin(in), end(in), begin(out), std::minus<>{});
for (int x : out) { std::cout << x << ' '; }  // 1 0 -2 -4 -5 -6
std::cout << '\n';
}``````