Post

std::inclusive_scan

std::inclusive_scan

std::inclusive_scan


Prerequisites


1. What is std::inclusive_scan? (C++17)

std::inclusive_scan is a standard algorithm introduced in C++17 that computes a prefix sum (cumulative sum) over a range.

It transforms a sequence like this:

1
[1, 2, 3, 4]

into:

1
[1, 3, 6, 10]

Each element becomes the sum of all previous elements including itself.

1
2
3
4
5
6
7
#include <numeric>
#include <vector>

std::vector<int> input = {1, 2, 3, 4};
std::vector<int> output(input.size());

std::inclusive_scan(input.begin(), input.end(), output.begin());

Result:

1
[1, 3, 6, 10]
1
output[i] = input[0] + input[1] + ... + input[i]

This is known as a prefix sum.

2. How to work

Function Signature

1
2
3
template<class InputIt, class OutputIt>
OutputIt inclusive_scan(InputIt first, InputIt last,
                        OutputIt d_first);

With Custom Operation

```cpp id=”o4m6q3” template<class InputIt, class OutputIt, class BinaryOp> OutputIt inclusive_scan(InputIt first, InputIt last, OutputIt d_first, BinaryOp op);

1
2
3
4
5
6
7
8
9
10
11
12
13
```cpp
#include <numeric>
#include <vector>

std::vector<int> v = {1, 2, 3, 4};
std::vector<int> out(v.size());

std::inclusive_scan(v.begin(), v.end(), out.begin(),
    [](int a, int b)
    {
        return a * b;
    });
1
[1, 2, 6, 24]

cumulative multiplication

In-place Operation

```cpp id=”t9p9l3” std::inclusive_scan(v.begin(), v.end(), v.begin());

1
2
3
4
5
6
7
8
9
10
11
12
* input and output can be the same container
* modifies original data

## <b>3. Parallel Version (C++17)</b>

```cpp
#include <execution>

std::inclusive_scan(std::execution::par,
                    input.begin(), input.end(),
                    output.begin());
  • supports parallel execution
  • handles dependency internally

4. Versus others

This pattern:

1
result[i] = result[i-1] + 1;

has data dependency.

  • cannot be safely parallelized with transform
  • requires a specialized algorithm

inclusive_scan is designed exactly for this case

AlgorithmDescription
inclusive_scanincludes current element
exclusive_scanexcludes current element
reducereduces entire range to one value
accumulatesequential reduction

inclusive vs exclusive

inclusive_scan
1
2
input  = [1, 2, 3, 4]
output = [1, 3, 6, 10]
exclusive_scan
1
2
input  = [1, 2, 3, 4]
output = [0, 1, 3, 6]
This post is licensed under CC BY 4.0 by the author.