std::exclusive_scan
От ru.cppreference.net
| Определено в заголовке <numeric>
|
||
template< class InputIt, class OutputIt, class T >
OutputIt exclusive_scan( InputIt first, InputIt last,
OutputIt d_first, T init );
|
(1) | (начиная с C++17) (constexpr начиная с C++20) |
template< class ExecutionPolicy,
class ForwardIt1, class ForwardIt2, class T >
ForwardIt2 exclusive_scan( ExecutionPolicy&& policy,
ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first, T init );
|
(2) | (начиная с C++17) |
template< class InputIt, class OutputIt,
class T, class BinaryOp >
OutputIt exclusive_scan( InputIt first, InputIt last,
OutputIt d_first, T init, BinaryOp op );
|
(3) | (начиная с C++17) (constexpr начиная с C++20) |
template< class ExecutionPolicy,
class ForwardIt1, class ForwardIt2,
class T, class BinaryOp >
ForwardIt2 exclusive_scan( ExecutionPolicy&& policy,
ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first, T init, BinaryOp op );
|
(4) | (начиная с C++17) |
1) Эквивалентно
exclusive_scan(first, last, d_first, init, std::plus<>().3) Вычисляет эксклюзивное префиксное суммирование, используя
op. Для каждого целого числа
i в [0, std::distance(first, last)) выполняет следующие операции по порядку:
- Создаёт последовательность, которая состоит из
init, за которым следуют элементы[first,iter)по порядку, гдеiter— следующийi-й итератор отfirst. - Вычисляет обобщённую некоммутативную сумму последовательности относительно
op. - Присваивает результат
*dest, гдеdest— следующийi-й итератор отd_first.
2,4) То же, что и (1,3), но выполняется в соответствии с
policy. Эти перегрузки участвуют в разрешении перегрузки только если значение следующего выражения равно
true:
|
|
(до C++20) |
|
|
(начиная с C++20) |
Обобщённая некоммутативная сумма последовательности элементов относительно бинарной операции binary_op определяется следующим образом:
- Если последовательность содержит только один элемент, сумма равна значению этого элемента.
- В противном случае выполняет следующие операции по порядку:
- Выбирает любые два соседних элемента
elem1иelem2из последовательности. - Вычисляет
binary_op(elem1, elem2)и заменяет два элемента в последовательности результатом. - Повторяет шаги 1 и 2, пока в последовательности не останется только один элемент.
При условии, что binary_op — фактическая бинарная операция:
- Результат недетерминирован, если
binary_opне является ассоциативной (например, сложение чисел с плавающей запятой).
- Если любое из следующих значений не преобразуется в
T, программа считается некорректной:
binary_op(init, *first)binary_op(init, init)binary_op(*first, *first)
- Если выполняется любое из следующих условий, поведение не определено:
Tне является MoveConstructible.binary_opизменяет любой элемент[first,last).binary_opделает недействительным любой итератор или поддиапазон[first,last].
Параметры
| first, last | - | пара итераторов, определяющая диапазон суммируемых элементов |
| d_first | - | начало диапазона назначения; может быть равно first
|
| policy | - | политика выполнения для использования |
| init | - | начальное значение |
| op | - | бинарный FunctionObject, который будет применяться к результату разыменования входных итераторов, результатам других op и init
|
| Требования к типам | ||
-InputIt должен соответствовать требованиям LegacyInputIterator.
| ||
-OutputIt должен соответствовать требованиям LegacyOutputIterator.
| ||
-ForwardIt1, ForwardIt2 должен соответствовать требованиям LegacyForwardIterator.
| ||
Возвращаемое значение
Итератор на элемент, следующий за последним записанным.
Сложность
Пусть N равно std::distance(first, last):
1,2) O(N) применений
std::plus<>().3,4) O(N) применений
op.Исключения
Перегрузки с параметром шаблона с именем ExecutionPolicy сообщают об ошибках следующим образом:
- Если выполнение функции, вызванной в рамках алгоритма, генерирует исключение, и
ExecutionPolicyявляется одной из стандартных политик, вызывается std::terminate. Для любой другойExecutionPolicyповедение определяется реализацией. - Если алгоритму не удаётся выделить память, генерируется std::bad_alloc.
Пример
Запустить этот код
#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
int main()
{
std::vector data{3, 1, 4, 1, 5, 9, 2, 6};
std::cout << "Exclusive sum: ";
std::exclusive_scan(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "),
0);
std::cout << "\nInclusive sum: ";
std::inclusive_scan(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n\nExclusive product: ";
std::exclusive_scan(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "),
1, std::multiplies<>{});
std::cout << "\nInclusive product: ";
std::inclusive_scan(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "),
std::multiplies<>{});
}
Вывод:
Exclusive sum: 0 3 4 8 9 14 23 25
Inclusive sum: 3 4 8 9 14 23 25 31
Exclusive product: 1 3 3 12 12 60 540 1080
Inclusive product: 3 3 12 12 60 540 1080 6480
Смотрите также
| вычисляет разности между соседними элементами в диапазоне (шаблон функции) | |
| суммирует или свёртывает диапазон элементов (шаблон функции) | |
| вычисляет частичную сумму диапазона элементов (шаблон функции) | |
(C++17) |
применяет вызываемый объект, затем вычисляет эксклюзивное сканирование (шаблон функции) |
(C++17) |
аналогично std::partial_sum, включает i-й входной элемент в i-ю сумму (шаблон функции) |