CodeNebula
C++17stladvanced

std::inclusive_scan

C++17 · Practical Modern · Compiler flag: -std=c++17

Explanation

Computes a running total (prefix sum) where each output element includes the corresponding input element. Supports parallel execution and custom binary operations.

Real-World Scenario

Generate cumulative page view counts for a real-time analytics dashboard.

Quick Snippet

snippet.cpp
#include <numeric>
#include <vector>

std::vector<int> daily = {100, 150, 200, 80};
std::vector<int> cumulative(daily.size());
std::inclusive_scan(daily.begin(), daily.end(), cumulative.begin());
// cumulative: {100, 250, 450, 530}

Full Example

inclusive_scan.cpp
// CodeNebula - C++17 Example: std::inclusive_scan
// Compile: g++ -std=c++17 -Wall -Wextra -o example inclusive_scan.cpp

// Demonstrates std::inclusive_scan, which computes running totals (prefix sums)
// where each output element includes the current input element. Unlike
// std::partial_sum, inclusive_scan allows out-of-order execution, making it
// suitable for parallel execution policies.

#include <iostream>
#include <numeric>
#include <vector>
#include <functional>

void print(const std::string& label, const std::vector<int>& v) {
    std::cout << "  " << label << ": ";
    for (int x : v) std::cout << x << " ";
    std::cout << std::endl;
}

void print_d(const std::string& label, const std::vector<double>& v) {
    std::cout << "  " << label << ": ";
    for (double x : v) std::cout << x << " ";
    std::cout << std::endl;
}

int main()
{
    // ------------------------------------------------------------------
    // 1. Basic inclusive scan (running sum)
    // ------------------------------------------------------------------
    std::cout << "=== basic inclusive scan (sum) ===" << std::endl;
    std::vector<int> input = {1, 2, 3, 4, 5};
    std::vector<int> result(input.size());

    // output[i] = input[0] + input[1] + ... + input[i]
    std::inclusive_scan(input.begin(), input.end(), result.begin());

    print("input ", input);
    print("scan  ", result);
    // {1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5} = {1, 3, 6, 10, 15}

    // ------------------------------------------------------------------
    // 2. Inclusive scan with custom operation (running product)
    // ------------------------------------------------------------------
    std::cout << "\n=== inclusive scan (product) ===" << std::endl;
    std::vector<int> factors = {1, 2, 3, 4, 5};
    std::vector<int> products(factors.size());

    std::inclusive_scan(factors.begin(), factors.end(), products.begin(),
                        std::multiplies<>{});

    print("input   ", factors);
    print("product ", products);
    // {1, 1*2, 1*2*3, 1*2*3*4, 1*2*3*4*5} = {1, 2, 6, 24, 120}

    // ------------------------------------------------------------------
    // 3. Inclusive scan with initial value
    // ------------------------------------------------------------------
    std::cout << "\n=== inclusive scan with init ===" << std::endl;
    std::vector<int> data = {10, 20, 30};
    std::vector<int> with_init(data.size());

    std::inclusive_scan(data.begin(), data.end(), with_init.begin(),
                        std::plus<>{}, 100);  // init = 100

    print("input    ", data);
    print("scan+100 ", with_init);
    // {100+10, 100+10+20, 100+10+20+30} = {110, 130, 160}

    // ------------------------------------------------------------------
    // 4. Running maximum
    // ------------------------------------------------------------------
    std::cout << "\n=== running maximum ===" << std::endl;
    std::vector<int> vals = {3, 1, 4, 1, 5, 9, 2, 6};
    std::vector<int> maxes(vals.size());

    std::inclusive_scan(vals.begin(), vals.end(), maxes.begin(),
        [](int a, int b) { return a > b ? a : b; });

    print("input  ", vals);
    print("max_so_far", maxes);
    // {3, 3, 4, 4, 5, 9, 9, 9}

    // ------------------------------------------------------------------
    // 5. In-place scan
    // ------------------------------------------------------------------
    std::cout << "\n=== in-place scan ===" << std::endl;
    std::vector<int> inplace = {5, 3, 8, 2, 7};
    print("before", inplace);
    std::inclusive_scan(inplace.begin(), inplace.end(), inplace.begin());
    print("after ", inplace);

    // ------------------------------------------------------------------
    // 6. Practical: cumulative scores
    // ------------------------------------------------------------------
    std::cout << "\n=== cumulative scores ===" << std::endl;
    std::vector<int> scores = {15, 22, 18, 25, 20};
    std::vector<int> cumulative(scores.size());
    std::inclusive_scan(scores.begin(), scores.end(), cumulative.begin());

    print("round scores", scores);
    print("total after ", cumulative);

    return 0;
}

/*
Expected output:

=== basic inclusive scan (sum) ===
  input : 1 2 3 4 5
  scan  : 1 3 6 10 15

=== inclusive scan (product) ===
  input   : 1 2 3 4 5
  product : 1 2 6 24 120

=== inclusive scan with init ===
  input    : 10 20 30
  scan+100 : 110 130 160

=== running maximum ===
  input  : 3 1 4 1 5 9 2 6
  max_so_far: 3 3 4 4 5 9 9 9

=== in-place scan ===
  before: 5 3 8 2 7
  after : 5 8 16 18 25

=== cumulative scores ===
  round scores: 15 22 18 25 20
  total after : 15 37 55 80 100
*/
Run command
g++ -std=c++17 -Wall -Wextra -o example inclusive_scan.cpp