namespace std::simd {
template<class T, class Abi, class BinaryOperation = std::plus<>>
constexpr T
reduce(const basic_vec<T, Abi>& x,
BinaryOperation binary_op = {}); // (1) C++26
template<class T, class Abi, class BinaryOperation = std::plus<>>
constexpr T
reduce(const basic_vec<T, Abi>& x,
const typename basic_vec<T, Abi>::mask_type& mask,
BinaryOperation binary_op = {},
std::type_identity_t<T> identity_element = /*see below*/); // (2) C++26
template<class T, class BinaryOperation = std::plus<>>
constexpr T
reduce(const T& x,
BinaryOperation binary_op = {}); // (3) C++26
template<class T, class BinaryOperation = std::plus<>>
constexpr T
reduce(const T& x,
std::same_as<bool> auto mask,
BinaryOperation binary_op = {},
std::type_identity_t<T> identity_element = /*see below*/); // (4) C++26
}
概要
basic_vecの全要素を二項演算binary_opで集計し、単一の値を求める。
- (1) :
xの全要素をbinary_opで集計する。 - (2) :
maskで選択された要素のみをbinary_opで集計する。ひとつも選択されていない場合はidentity_element(単位元)を返す。 - (3) : スカラー値
xをそのまま返す(SIMD-genericなコードを書けるようにするためのオーバーロード)。 - (4) :
maskがtrueならxを、falseならidentity_elementを返す。
binary_opは結合的かつ可換な二項演算でなければならず、要素の集計順は規定されない。
テンプレートパラメータ制約
- (1), (2) :
BinaryOperationが説明専用コンセプトreduction-binary-operation<T>のモデルであること - (3), (4) :
Tが「vectorizable type」であり、かつBinaryOperationがreduction-binary-operation<T>のモデルであること - (2), (4) :
BinaryOperationがstd::plus<>・std::multiplies<>・std::bit_and<>・std::bit_or<>・std::bit_xor<>のいずれでもない場合、identity_elementの実引数を指定しなければならない
事前条件
- (1), (2) :
binary_opがxを書き換えないこと - (2), (4) :
Tで表現可能な任意の有限値yについて、identity_elementをbinary_opの単位元として作用させた結果がyと等しくなること
戻り値
- (1) :
xの全要素x[0], …, x[x.size() - 1]をbinary_opで集計した結果を返す。 - (2) :
none_of(mask)がtrueならidentity_elementを返す。そうでなければmaskで選択された要素をbinary_opで集計した結果を返す。 - (3) :
xを返す。 - (4) :
maskがfalseならidentity_elementを、そうでなければxを返す。
例外
- (1), (2) :
binary_opが送出する例外を送出する - (3), (4) : 投げない
備考
- (2), (4) :
identity_elementの既定引数は、BinaryOperationに応じて以下の値となる。std::plus<>:T()std::multiplies<>:T(1)std::bit_and<>:T(~T())std::bit_or<>:T()std::bit_xor<>:T()
例
#include <simd>
#include <print>
#include <functional>
namespace simd = std::simd;
int main()
{
simd::vec<int, 4> v([](int i) { return i + 1; }); // {1, 2, 3, 4}
// 全要素の総和(既定の二項演算はstd::plus<>)
std::println("{}", simd::reduce(v));
// 全要素の積
std::println("{}", simd::reduce(v, std::multiplies<>{}));
// 偶数要素だけの総和
auto mask = (v % 2 == 0);
std::println("{}", simd::reduce(v, mask));
}
出力
10
24
6
バージョン
言語
- C++26
処理系
- Clang: 22 ❌
- GCC: 16.1 ❌
- Visual C++: 2026 Update 2 ❌
関連項目
参照
- P1928R15 std::simd — merge data-parallel types from the Parallelism TS 2
- C++26で追加された
- P3690R1 Consistency fix: Make simd reductions SIMD-generic
- スカラー「vectorizable type」を受け取るオーバーロード (3), (4) が追加され、SIMD-genericなコードを書けるようになった