std::reduce
Определено в заголовке <numeric> | ||
|---|---|---|
| (1) | ||
template< class InputIt >
typename std::iterator_traits<InputIt>::value_type
reduce( InputIt first, InputIt last ); |
(с C++17) (до C++20) | |
template< class InputIt >
constexpr typename std::iterator_traits<InputIt>::value_type
reduce( InputIt first, InputIt last );
| (с C++20) | |
template< class ExecutionPolicy, class ForwardIt >
typename std::iterator_traits<ForwardIt>::value_type
reduce( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last );
| (2) | (с C++17) |
| (3) | ||
template< class InputIt, class T > T reduce( InputIt first, InputIt last, T init ); |
(с C++17) (до C++20) | |
template< class InputIt, class T > constexpr T reduce( InputIt first, InputIt last, T init ); | (с C++20) | |
template< class ExecutionPolicy, class ForwardIt, class T >
T reduce( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, T init );
| (4) | (с C++17) |
| (5) | ||
template< class InputIt, class T, class BinaryOp > T reduce( InputIt first, InputIt last, T init, BinaryOp binary_op ); |
(с C++17) (до C++20) | |
template< class InputIt, class T, class BinaryOp > constexpr T reduce( InputIt first, InputIt last, T init, BinaryOp binary_op ); | (с C++20) | |
template< class ExecutionPolicy, class ForwardIt, class T, class BinaryOp >
T reduce( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, T init, BinaryOp binary_op );
| (6) | (с C++17) |
reduce(first, last, typename std::iterator_traits<InputIt>::value_type{})
reduce(first, last, init, std::plus<>())
[first, last), возможно, переупорядочивая и агрегируя неопределённым образом, вместе с начальным значением init по binary_op. policy. Эти перегрузки не участвуют в разрешении перегрузки, если |
| (до C++20) |
|
| (с C++20) |
Поведение не определено, если binary_op не ассоциативна или не коммутативна.
Поведение неопределено, если binary_op изменяет любой элемент или делает недействительным любой итератор в [first, last), включая конечный итератор.
Параметры
| first, last | - | диапазон элементов, к которым будет применено алгоритм |
| init | - | начальное значение обобщённой суммы |
| policy | - | стратегия выполнения. Подробнее см. стратегия выполнения. |
| binary_op | - | бинарный Функциональный объект, который будет применяться в неопределённом порядке к результату обращения по ссылке к входным итераторам, результатам других binary_op и init. |
| Требования к типу | ||
-InputIt должно соответствовать требованиям ЛегасиInputIterator. |
||
-ForwardIt должно соответствовать требованиям ЛегасиForwardIterator. |
||
-T должно соответствовать требованиям MoveConstructible. и binary_op(init, *first), binary_op(*first, init), binary_op(init, init), и binary_op(*first, *first) должны быть преобразуемы к T. |
||
Возвращаемое значение
Обобщённая сумма init и *first, *(first + 1), ... *(last - 1) по binary_op,
где обобщённая сумма GSUM(op, a1, ..., aN) определяется следующим образом:
- если N = 1, a1
- если N > 1, op(GSUM(op, b1, ..., bK), GSUM(op, bM, ..., bN)) где
- b1, ..., bN могут быть любой перестановкой a1, ..., aN и
- 1 < K + 1 = M ≤ N
другими словами, reduce ведет себя как std::accumulate за исключением того, что элементы диапазона могут быть сгруппированы и переупорядочены произвольным образом
Сложность
O(last - first) применений binary_op.
Исключение
Перегрузки с параметром шаблона ExecutionPolicy сообщают об ошибках следующим образом:
- Если выполнение функции, вызванной как часть алгоритма, выбрасывает исключение, и
ExecutionPolicyявляется одной из стандартных стратегий,std::terminateвызывается. Для любой другойExecutionPolicy, поведение определяется реализацией. - Если алгоритм не может выделить память,
std::bad_allocвыбрасывается.
Примечания
Если диапазон пуст, возвращается init, не изменённая.
Пример
сравнение std::reduce и std::accumulate:
#if PARALLEL
#include <execution>
#define SEQ std::execution::seq,
#define PAR std::execution::par,
#else
#define SEQ
#define PAR
#endif
#include <chrono>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <utility>
#include <vector>
int main()
{
std::cout.imbue(std::locale("en_US.UTF-8"));
std::cout << std::fixed << std::setprecision(1);
auto eval = [](auto fun)
{
const auto t1 = std::chrono::high_resolution_clock::now();
const auto [name, result] = fun();
const auto t2 = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double, std::milli> ms = t2 - t1;
std::cout << std::setw(28) << std::left << name << "sum: "
<< result << "\t time: " << ms.count() << " ms\n";
};
{
const std::vector<double> v(100'000'007, 0.1);
eval([&v]{ return std::pair{"std::accumulate (double)",
std::accumulate(v.cbegin(), v.cend(), 0.0)}; } );
eval([&v]{ return std::pair{"std::reduce (seq, double)",
std::reduce(SEQ v.cbegin(), v.cend())}; } );
eval([&v]{ return std::pair{"std::reduce (par, double)",
std::reduce(PAR v.cbegin(), v.cend())}; } );
}
{
const std::vector<long> v(100'000'007, 1);
eval([&v]{ return std::pair{"std::accumulate (long)",
std::accumulate(v.cbegin(), v.cend(), 0l)}; } );
eval([&v]{ return std::pair{"std::reduce (seq, long)",
std::reduce(SEQ v.cbegin(), v.cend())}; } );
eval([&v]{ return std::pair{"std::reduce (par, long)",
std::reduce(PAR v.cbegin(), v.cend())}; } );
}
}Возможный вывод:
// POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3; ./a.out std::accumulate (double) sum: 10,000,000.7 time: 356.9 ms std::reduce (seq, double) sum: 10,000,000.7 time: 140.1 ms std::reduce (par, double) sum: 10,000,000.7 time: 140.1 ms std::accumulate (long) sum: 100,000,007 time: 46.0 ms std::reduce (seq, long) sum: 100,000,007 time: 67.3 ms std::reduce (par, long) sum: 100,000,007 time: 63.3 ms // POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3 -DPARALLEL; ./a.out std::accumulate (double) sum: 10,000,000.7 time: 353.4 ms std::reduce (seq, double) sum: 10,000,000.7 time: 140.7 ms std::reduce (par, double) sum: 10,000,000.7 time: 24.7 ms std::accumulate (long) sum: 100,000,007 time: 42.4 ms std::reduce (seq, long) sum: 100,000,007 time: 52.0 ms std::reduce (par, long) sum: 100,000,007 time: 23.1 ms
См. также
| суммирует или сворачивает диапазон элементов (шаблон функции) |
|
| применяет функцию к диапазону элементов, сохраняя результаты в целевом диапазоне (шаблон функции) |
|
|
(C++17) | применяет вызываемый объект, затем сворачивает вне очереди (шаблон функции) |
|
(C++23) | сворачивает слева диапазон элементов (niebloid) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/reduce