CodeNebula
C++26stlexpert

std::simd::reduce (C++26 Addition)

C++26 · The Next Frontier · Compiler flag: -std=c++26

Explanation

Reduces all elements of a SIMD vector into a single scalar value using a specified binary operation (e.g., addition, multiplication, min, max). Enables efficient horizontal reductions across vector lanes.

Real-World Scenario

Compute the sum of all elements in a vectorized dot product or find the maximum value across a batch of distance calculations.

Quick Snippet

snippet.cpp
#include <simd>

std::simd<float> values = {1.0f, 2.0f, 3.0f, 4.0f};
float sum = std::reduce(values);                    // 10.0f (default: addition)
float product = std::reduce(values, std::multiplies{}); // 24.0f

Full Example

simd_reduce.cpp
// CodeNebula - C++26 Example: std::simd::reduce Horizontal Operations
// Compile: g++ -std=c++26 -Wall -Wextra -o example simd_reduce.cpp
// Note: Requires C++26 compiler support

#include <iostream>
#include <array>
#include <cstddef>
#include <algorithm>
#include <numeric>

// Horizontal (reduce) operations collapse all lanes of a SIMD vector into
// a single scalar. C++26's std::simd provides:
//   reduce(simd_vec)              - sum all lanes
//   reduce(simd_vec, std::plus)   - sum (explicit)
//   reduce(simd_vec, std::multiplies) - product
//   hmin(simd_vec), hmax(simd_vec)    - horizontal min/max

namespace simd_sim {
    template <typename T, std::size_t N = 4>
    struct simd {
        std::array<T, N> data{};
        static constexpr std::size_t size() { return N; }
        simd() = default;
        explicit simd(T val) { data.fill(val); }
        simd(std::initializer_list<T> il) {
            std::size_t i = 0;
            for (auto v : il) { if (i < N) data[i++] = v; }
        }
        T operator[](std::size_t i) const { return data[i]; }
    };

    // Horizontal sum (default reduce)
    template <typename T, std::size_t N>
    T reduce(const simd<T,N>& v) {
        return std::accumulate(v.data.begin(), v.data.end(), T{0});
    }

    // Horizontal product
    template <typename T, std::size_t N>
    T reduce_mul(const simd<T,N>& v) {
        return std::accumulate(v.data.begin(), v.data.end(), T{1}, std::multiplies<T>{});
    }

    // Horizontal min and max
    template <typename T, std::size_t N>
    T hmin(const simd<T,N>& v) { return *std::min_element(v.data.begin(), v.data.end()); }

    template <typename T, std::size_t N>
    T hmax(const simd<T,N>& v) { return *std::max_element(v.data.begin(), v.data.end()); }
}

int main() {
    using Vec = simd_sim::simd<float, 4>;

    Vec v{3.0f, 1.0f, 4.0f, 1.5f};

    std::cout << "Vector: [3, 1, 4, 1.5]\n";
    std::cout << "reduce (sum):     " << simd_sim::reduce(v)     << "\n";
    std::cout << "reduce (product): " << simd_sim::reduce_mul(v) << "\n";
    std::cout << "hmin:             " << simd_sim::hmin(v)       << "\n";
    std::cout << "hmax:             " << simd_sim::hmax(v)       << "\n";

    // Practical use: dot product via multiply + reduce
    Vec a{1.0f, 2.0f, 3.0f, 4.0f};
    Vec b{5.0f, 6.0f, 7.0f, 8.0f};
    // In real C++26: auto dot = std::reduce(a * b);
    simd_sim::simd<float, 4> prod;
    for (std::size_t i = 0; i < 4; ++i)
        prod.data[i] = a[i] * b[i];
    float dot = simd_sim::reduce(prod);
    std::cout << "dot(a, b):        " << dot << "\n";

    return 0;
}

// Expected output:
// Vector: [3, 1, 4, 1.5]
// reduce (sum):     9.5
// reduce (product): 18
// hmin:             1
// hmax:             4
// dot(a, b):        70
Run command
g++ -std=c++26 -Wall -Wextra -o example simd_reduce.cpp