std::exclusive_scan(3)
π std::exclusive_scan(3) π
okay bestie, welcome to the C++ Standard Library page for std::exclusive_scan β she's a <numeric> girlie, she's iconic, and she's about to hand you every prefix sum except the one you're standing on. periodt. π
β¨ SYNOPSIS β¨
Defined in header <numeric>:
template< class InputIt, class OutputIt, class T >
OutputIt exclusive_scan( InputIt first, InputIt last, (1) (since C++17)
OutputIt d_first, T init ); (constexpr since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T >
ForwardIt2 exclusive_scan( ExecutionPolicy&& policy, (2) (since C++17)
ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first, T init );
template< class InputIt, class OutputIt, class T, class BinaryOp >
OutputIt exclusive_scan( InputIt first, InputIt last, (3) (since C++17)
OutputIt d_first, T init, (constexpr since C++20)
BinaryOp op );
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T, class BinaryOp >
ForwardIt2 exclusive_scan( ExecutionPolicy&& policy, (4) (since C++17)
ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first, T init,
BinaryOp op );
π¦ DESCRIPTION π¦
so here's the tea, sip by sip π
- (1) is literally equivalent to
exclusive_scan(first, last, d_first, init, std::plus<>()). - (3) computes the exclusive prefix sum using
op. For each integeriin[0, std::distance(first, last)), it performs the following operations in order:- Creates a sequence which is formed by
initfollowed by the elements of[first, iter)in order, whereiteris the nexti-th iterator offirst. - Computes the generalized noncommutative sum of the sequence over
op. - Assigns the result to
*dest, wheredestis the nexti-th iterator ofd_first.
- Creates a sequence which is formed by
- (2,4) Same as (1,3), but executed according to
policy.
These overloads participate in overload resolution only if std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true (until C++20) β and since C++20 it's std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true. no cap, that's the whole gatekeeping clause πͺ
π the generalized noncommutative sum, explained (iykyk)
The generalized noncommutative sum of a sequence of elements over a binary operation binary_op is defined as follows:
- If the sequence only has one element, the sum is the value of the element. that's it, that's the whole element π
- Otherwise, performs the following operations in order:
- Selects any two adjacent elements
elem1andelem2from the sequence. - Calculates
binary_op(elem1, elem2)and replaces the two elements in the sequence with the result. - Repeats steps 1 and 2 until there is only one element in the sequence.
- Selects any two adjacent elements
Given binary_op as the actual binary operation:
- The result is non-deterministic if the
binary_opis not associative (such as floating-point addition). π yes girl, the order is genuinely chaos β don't come for me, come for the float. - If any of the following values is not convertible to
T, the program is ill-formed:binary_op(init, *first)binary_op(init, init)binary_op(*first, *first)
- If any of the following conditions is satisfied, the behavior is undefined β say it with me, U-B, undefined π«Ά:
Tis not MoveConstructible.binary_opmodifies any element of[first, last).binary_opinvalidates any iterator or subrange of[first, last).
π¨ bestie listen: that undefined-behavior list is not a vibe, it's a warning. Don't let your binary_op touch the input range. Just don't.
π PARAMETERS π
first,lastβ the range of elements to sum β¨d_firstβ the beginning of the destination range; may be equal tofirstπ (yes, in-place is allowed, slay)policyβ the execution policy to use. See execution policy for details.initβ the initial value π±opβ binary FunctionObject that will be applied in to the result of dereferencing the input iterators, the results of otherop, andinit
πΈ TYPE REQUIREMENTS πΈ
InputItmust meet the requirements of LegacyInputIterator.OutputItmust meet the requirements of LegacyOutputIterator.ForwardIt1,ForwardIt2must meet the requirements of LegacyForwardIterator.
β RETURN VALUE β
Iterator to the element past the last element written. she points one past the end, main character energy π
π₯ COMPLEXITY π₯
Given N as std::distance(first, last):
- 1,2)
O(N)applications ofstd::plus<>(). - 3,4)
O(N)applications ofop.
linear, bestie. she ate and left no crumbs π½οΈ
π EXCEPTIONS π
The overloads with a template parameter named ExecutionPolicy report errors as follows:
- If execution of a function invoked as part of the algorithm throws an exception and
ExecutionPolicyis one of the standard policies,std::terminateis called. For any otherExecutionPolicy, the behavior is implementation-defined. - If the algorithm fails to allocate memory,
std::bad_allocis thrown.
π yeah, standard policy + exception = std::terminate. no rescue mission. plan accordingly.
π§ EXAMPLE π§
// Run this code
#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<>{});
}
Output:
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
see how the exclusive one starts with your init and then lags one behind? that's the whole bit. she's the ex-clusive scan for a reason πβ¨
π SEE ALSO π
adjacent_differenceβ computes the differences between adjacent elements in a range (function template)accumulateβ sums up or folds a range of elements (function template)partial_sumβ computes the partial sum of a range of elements (function template)transform_exclusive_scan(C++17) β applies an invocable, then calculates exclusive scan (function template)inclusive_scan(C++17) β similar tostd::partial_sum, includes thei^th input element in thei^th sum (function template)
okay that's the whole page, go forth and scan exclusively π¦π
this vibey lil rewrite comes to you from http://cppreference.com, dated 2024.06.10 β original page std::exclusive_scan(3) in the C++ Standard Library. mwah, bye bestie π
π
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms