CodeNebula
C++26stlexpert

std::simd_mask (C++26 Addition)

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

Explanation

A companion type to `std::simd` that represents a vector of boolean values. Used for conditional SIMD operations, enabling element-wise selection and masked computation without branching.

Real-World Scenario

In a particle system, filter out particles that have expired (lifetime <= 0) and only update the active ones, all in a single vectorized pass.

Quick Snippet

snippet.cpp
#include <simd>

std::simd<float> values = {1.0f, -2.0f, 3.0f, -4.0f};
std::simd_mask<float> positive = values > 0.0f; // {true, false, true, false}
auto clamped = std::simd::where(positive, values); // Keeps only positive elements

Full Example

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

#include <iostream>
#include <array>
#include <cstddef>

// std::simd_mask<T, Abi> is a boolean mask paired with std::simd<T>.
// Key operations:
//   mask = (simd_a > simd_b)   - comparison yields a mask
//   where(mask, a) = b         - conditional assignment
//   any_of(mask), all_of(mask) - horizontal boolean queries

namespace simd_sim {
    template <typename T, std::size_t N = 4>
    struct simd {
        std::array<T, N> data{};
        simd() = default;
        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]; }
    };

    template <std::size_t N = 4>
    struct simd_mask {
        std::array<bool, N> bits{};
        bool operator[](std::size_t i) const { return bits[i]; }
    };

    template <typename T, std::size_t N>
    simd_mask<N> operator>(const simd<T,N>& a, const simd<T,N>& b) {
        simd_mask<N> m;
        for (std::size_t i = 0; i < N; ++i) m.bits[i] = (a.data[i] > b.data[i]);
        return m;
    }

    template <typename T, std::size_t N>
    simd<T,N> where_select(const simd_mask<N>& m, const simd<T,N>& a, const simd<T,N>& b) {
        simd<T,N> r;
        for (std::size_t i = 0; i < N; ++i) r.data[i] = m[i] ? a.data[i] : b.data[i];
        return r;
    }

    template <std::size_t N>
    bool any_of(const simd_mask<N>& m) {
        for (std::size_t i = 0; i < N; ++i) if (m[i]) return true; return false;
    }
    template <std::size_t N>
    bool all_of(const simd_mask<N>& m) {
        for (std::size_t i = 0; i < N; ++i) if (!m[i]) return false; return true;
    }
}

int main() {
    using Vec = simd_sim::simd<float, 4>;
    Vec a{3.0f, 1.0f, 4.0f, 1.0f};
    Vec b{2.0f, 7.0f, 1.0f, 5.0f};

    auto mask = a > b;
    std::cout << "mask (a > b): [";
    for (std::size_t i = 0; i < 4; ++i) std::cout << (i?", ":"") << mask[i];
    std::cout << "]\n";

    Vec result = simd_sim::where_select(mask, a, b);
    std::cout << "max(a,b):     [";
    for (std::size_t i = 0; i < 4; ++i) std::cout << (i?", ":"") << result[i];
    std::cout << "]\n";

    std::cout << "any_of(mask): " << simd_sim::any_of(mask) << "\n";
    std::cout << "all_of(mask): " << simd_sim::all_of(mask) << "\n";
    return 0;
}

// Expected output:
// mask (a > b): [1, 0, 1, 0]
// max(a,b):     [3, 7, 4, 5]
// any_of(mask): 1
// all_of(mask): 0
Run command
g++ -std=c++26 -Wall -Wextra -o example simd_mask.cpp