GCC Code Coverage Report


Directory: include/kumi/
File: include/kumi/algorithm/scan.hpp
Date: 2026-10-14 16:33:56
Exec Total Coverage
Lines: 30 30 100.0%
Functions: 32 32 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 //======================================================================================================================
2 /*
3 KUMI - Compact Tuple Tools
4 Copyright : KUMI Project Contributors
5 SPDX-License-Identifier: BSL-1.0
6 */
7 //======================================================================================================================
8 #pragma once
9
10 namespace kumi
11 {
12
13 namespace _
14 {
15 template<typename T, typename V, typename F, typename O, std::size_t... I>
16 16 KUMI_HIDDEN_ABI constexpr auto inclusive_scan_left_(
17 kumi::_::adl_tag_t, T&& t, V v, F f, O o, std::index_sequence<I...>)
18 {
19 72 return (kumi::function::scannable{o, kumi::invoke(f, v, get<0>(KUMI_FWD(t)))} >> ... >>
20 152 kumi::bind_back(f, get<I + 1>(KUMI_FWD(t))))();
21 }
22
23 template<typename T, typename V, typename F, typename O, std::size_t... I>
24 16 KUMI_HIDDEN_ABI constexpr auto exclusive_scan_left_(
25 kumi::_::adl_tag_t, T&& t, V v, F f, O o, std::index_sequence<I...>)
26 {
27 192 return (kumi::function::scannable{o, v} >> ... >> kumi::bind_back(f, get<I>(KUMI_FWD(t))))();
28 }
29
30 template<typename T, typename V, typename F, typename O, std::size_t... I>
31 16 KUMI_HIDDEN_ABI constexpr auto inclusive_scan_right_(
32 kumi::_::adl_tag_t, T&& t, V v, F f, O o, std::index_sequence<I...>)
33 {
34 120 return (kumi::bind_front(f, get<I>(KUMI_FWD(t)))
35 88 << ... << kumi::function::scannable{o, kumi::invoke(f, get<kumi::size_v<T> - 1>(KUMI_FWD(t)), v)})();
36 }
37
38 template<typename T, typename V, typename F, typename O, std::size_t... I>
39 16 KUMI_HIDDEN_ABI constexpr auto exclusive_scan_right_(
40 kumi::_::adl_tag_t, T&& t, V v, F f, O o, std::index_sequence<I...>)
41 {
42 176 return (kumi::bind_front(f, get<I + 1>(KUMI_FWD(t))) << ... << kumi::function::scannable{o, v})();
43 }
44 }
45
46 struct inclusive_scan_left_t
47 {
48 template<typename Function, kumi::concepts::product_type T, typename Value>
49 [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t, Value init) const
50 {
51 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t)), init);
52 else if constexpr (kumi::concepts::empty_product_type<T>) return kumi::tuple{};
53 else if constexpr (kumi::concepts::sized_product_type<T, 1>)
54 return kumi::tuple{kumi::invoke(f, init, get<0>(KUMI_FWD(t)))};
55 else
56 {
57 8 return inclusive_scan_left_(kumi::_::adl_tag, KUMI_FWD(t), init, f, kumi::make_tuple,
58 8 std::make_index_sequence<kumi::size_v<T> - 1>{});
59 }
60 }
61
62 template<kumi::concepts::monoid M, kumi::concepts::sized_product_type_or_more<1> T>
63 [[nodiscard]] KUMI_ABI constexpr auto operator()(M&& m, T&& t) const
64 {
65 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(KUMI_FWD(m), kumi::values_of(KUMI_FWD(t)));
66 4 else return (*this)(KUMI_FWD(m), KUMI_FWD(t), m.identity);
67 }
68 };
69
70 struct exclusive_scan_left_t
71 {
72 template<typename Function, kumi::concepts::product_type T, typename Value>
73 [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t, Value init) const
74 {
75 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t)), init);
76 else if constexpr (kumi::concepts::empty_product_type<T>) return kumi::tuple{};
77 else if constexpr (kumi::concepts::sized_product_type<T, 1>) return kumi::tuple{init};
78 else
79 {
80 8 return exclusive_scan_left_(kumi::_::adl_tag, KUMI_FWD(t), init, f, kumi::make_tuple,
81 8 std::make_index_sequence<kumi::size_v<T> - 1>{});
82 }
83 }
84
85 template<kumi::concepts::monoid M, kumi::concepts::sized_product_type_or_more<1> T>
86 [[nodiscard]] KUMI_ABI constexpr auto operator()(M&& m, T&& t) const
87 {
88 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(KUMI_FWD(m), kumi::values_of(KUMI_FWD(t)));
89 4 else return (*this)(KUMI_FWD(m), KUMI_FWD(t), m.identity);
90 }
91 };
92
93 struct inclusive_scan_right_t
94 {
95 template<typename Function, kumi::concepts::product_type T, typename Value>
96 [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t, Value init) const
97 {
98 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(KUMI_FWD(f), kumi::values_of(KUMI_FWD(t)), init);
99 else if constexpr (kumi::concepts::empty_product_type<T>) return kumi::tuple{};
100 else if constexpr (kumi::concepts::sized_product_type<T, 1>)
101 return kumi::tuple{kumi::invoke(f, get<0>(KUMI_FWD(t)), init)};
102 else
103 {
104 8 return inclusive_scan_right_(kumi::_::adl_tag, KUMI_FWD(t), init, f, kumi::make_tuple,
105 8 std::make_index_sequence<kumi::size_v<T> - 1>{});
106 }
107 }
108
109 template<kumi::concepts::monoid M, kumi::concepts::sized_product_type_or_more<1> T>
110 [[nodiscard]] KUMI_ABI constexpr auto operator()(M&& m, T&& t) const
111 {
112 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(KUMI_FWD(m), kumi::values_of(KUMI_FWD(t)));
113 4 else return (*this)(KUMI_FWD(m), KUMI_FWD(t), m.identity);
114 }
115 };
116
117 struct exclusive_scan_right_t
118 {
119 template<typename Function, kumi::concepts::product_type T, typename Value>
120 [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t, Value init) const
121 {
122 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(KUMI_FWD(f), kumi::values_of(KUMI_FWD(t)), init);
123 else if constexpr (kumi::concepts::empty_product_type<T>) return kumi::tuple{};
124 else if constexpr (kumi::concepts::sized_product_type<T, 1>) return kumi::tuple{init};
125 else
126 {
127 8 return exclusive_scan_right_(kumi::_::adl_tag, KUMI_FWD(t), init, f, kumi::make_tuple,
128 8 std::make_index_sequence<kumi::size_v<T> - 1>{});
129 }
130 }
131
132 template<kumi::concepts::monoid M, kumi::concepts::sized_product_type_or_more<1> T>
133 [[nodiscard]] KUMI_ABI constexpr auto operator()(M&& m, T&& t) const
134 {
135 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(KUMI_FWD(m), kumi::values_of(KUMI_FWD(t)));
136 4 else return (*this)(KUMI_FWD(m), KUMI_FWD(t), m.identity);
137 }
138 };
139
140 //====================================================================================================================
141 /**
142 @ingroup kumi_reductions
143
144 @var inclusive_scan_left
145 @brief Callable object computing the inclusive prefix scan of all elements of a product type using a tail recursive
146 call.
147
148 On record types, this function operates on the underlying values, not on the fields themselves.
149
150 @note The first stored value is the result of the application of the function to the provided
151 initial value and the first element of the product_type.
152
153 @qualifier nodiscard
154 @qualifier inline
155 @qualifier constexpr
156
157 @groupheader{Header file}
158 @code
159 #include <kumi/algorithm/scan.hpp>
160 @endcode
161
162 @groupheader{Call Signature}
163
164 @code
165 template<typename Function, product_type T, typename Value>
166 constexpr auto inclusive_scan_left(Function f, T && t, Value init);
167 @endcode
168
169 @code
170 template<monoid M, typename Function, product_type T, typename Value>
171 constexpr auto inclusive_scan_left(M && m, T && t);
172 @endcode
173
174 @subgroupheader{Parameters}
175
176 - `m`: Monoid callable function to apply
177 - `f`: Binary callable function to apply
178 - `t`: Product Type to operate on
179 - `init`: Optional initial value of the scan
180
181 @subgroupheader{Return value}
182
183 - A tuple of prefix partial accumulations where each element 'I' equals
184 `f( f( f(init, get<0>(t)), ...), get<I-1>(t))`
185
186 @groupheader{Helper type}
187
188 @snippet include/kumi/algorithm/scan.hpp inclusive_scan_left_t
189
190 Computes the return type of a call to kumi::inclusive_scan_left
191
192 @groupheader{Examples}
193
194 @tab_begin
195
196 @tab{Tuple}
197 @godbolt{doc/tuple/algo/inclusive_scan_left.cpp}
198
199 @tab{Record}
200 @godbolt{doc/record/algo/inclusive_scan_left.cpp}
201
202 @tab_end
203 **/
204 //====================================================================================================================
205 KUMI_VARIABLE_ABI constexpr inclusive_scan_left_t inclusive_scan_left{};
206
207 //====================================================================================================================
208 /**
209 @ingroup kumi_reductions
210
211 @var exclusive_scan_left
212 @brief Callable object computing the exclusive prefix scan of all elements of a product type using a tail recursive
213 call.
214
215 On record types, this function operates on the underlying values, not on the fields themselves.
216
217 @note The first stored value is the result of the application of the function to the provided
218 initial value and the first element of the product_type.
219
220 @qualifier nodiscard
221 @qualifier inline
222 @qualifier constexpr
223
224 @groupheader{Header file}
225 @code
226 #include <kumi/algorithm/scan.hpp>
227 @endcode
228
229 @groupheader{Call Signature}
230
231 @code
232 template<typename Function, product_type T, typename Value>
233 constexpr auto exclusive_scan_left(Function f, T && t, Value init);
234 @endcode
235
236 @code
237 template<monoid M, typename Function, product_type T, typename Value>
238 constexpr auto exclusive_scan_left(M && m, T && t);
239 @endcode
240
241 @subgroupheader{Parameters}
242
243 - `m`: Monoid callable function to apply
244 - `f`: Binary callable function to apply
245 - `t`: Product Type to operate on
246 - `init`: Optional initial value of the scan
247
248 @subgroupheader{Return value}
249
250 - A tuple of prefix partial accumulations where each element 'I' equals
251 `f( f( f(init, get<0>(t)), ...), get<I-1>(t))`
252
253 @groupheader{Helper type}
254
255 @snippet include/kumi/algorithm/scan.hpp exclusive_scan_left_t
256
257 Computes the return type of a call to kumi::exclusive_scan_left
258
259 @groupheader{Examples}
260
261 @tab_begin
262
263 @tab{Tuple}
264 @godbolt{doc/tuple/algo/exclusive_scan_left.cpp}
265
266 @tab{Record}
267 @godbolt{doc/record/algo/exclusive_scan_left.cpp}
268
269 @tab_end
270 **/
271 //====================================================================================================================
272 KUMI_VARIABLE_ABI constexpr exclusive_scan_left_t exclusive_scan_left{};
273
274 //====================================================================================================================
275 /**
276 @ingroup kumi_reductions
277
278 @var inclusive_scan_right
279 @brief Callable object computing the inclusive suffix scan of all elements of a product type using a non-tail
280 recursive call.
281
282 On record types, this function operates on the underlying values, not on the fields themselves.
283
284 @note The first stored value is the result of the application of the function to the provided
285 initial value and the first element of the product_type.
286
287 @qualifier nodiscard
288 @qualifier inline
289 @qualifier constexpr
290
291 @groupheader{Header file}
292 @code
293 #include <kumi/algorithm/scan.hpp>
294 @endcode
295
296 @groupheader{Call Signature}
297
298 @code
299 template<typename Function, product_type T, typename Value>
300 constexpr auto inclusive_scan_right(Function f, T && t, Value init);
301 @endcode
302
303 @code
304 template<monoid M, typename Function, product_type T, typename Value>
305 constexpr auto inclusive_scan_right(M && m, T && t);
306 @endcode
307
308 @subgroupheader{Parameters}
309
310 - `m`: Monoid callable function to apply
311 - `f`: Binary callable function to apply
312 - `t`: Product Type to operate on
313 - `init`: Optional initial value of the scan
314
315 @subgroupheader{Return value}
316
317 - A tuple of suffix partial accumulations where each element 'I' equals
318 `f(get<0>(t), f(... , f(get<N-1>(t), init))`
319
320 @groupheader{Helper type}
321
322 @snippet include/kumi/algorithm/scan.hpp inclusive_scan_right_t
323
324 Computes the return type of a call to kumi::inclusive_scan_right
325
326 @groupheader{Examples}
327
328 @tab_begin
329
330 @tab{Tuple}
331 @godbolt{doc/tuple/algo/inclusive_scan_right.cpp}
332
333 @tab{Record}
334 @godbolt{doc/record/algo/inclusive_scan_right.cpp}
335
336 @tab_end
337 **/
338 //====================================================================================================================
339 KUMI_VARIABLE_ABI constexpr inclusive_scan_right_t inclusive_scan_right{};
340
341 //====================================================================================================================
342 /**
343 @ingroup kumi_reductions
344
345 @var exclusive_scan_right
346 @brief Callable object computing the exclusive suffix scan of all elements of a product type using a non-tail
347 recursive call.
348
349 On record types, this function operates on the underlying values, not on the fields themselves.
350
351 @note The first stored value is the result of the application of the function to the provided
352 initial value and the first element of the product_type.
353
354 @qualifier nodiscard
355 @qualifier inline
356 @qualifier constexpr
357
358 @groupheader{Header file}
359 @code
360 #include <kumi/algorithm/scan.hpp>
361 @endcode
362
363 @groupheader{Call Signature}
364
365 @code
366 template<typename Function, product_type T, typename Value>
367 constexpr auto exclusive_scan_right(Function f, T && t, Value init);
368 @endcode
369
370 @code
371 template<monoid M, typename Function, product_type T, typename Value>
372 constexpr auto exclusive_scan_right(M && m, T && t);
373 @endcode
374
375 @subgroupheader{Parameters}
376
377 - `m`: Monoid callable function to apply
378 - `f`: Binary callable function to apply
379 - `t`: Product Type to operate on
380 - `init`: Optional initial value of the scan
381
382 @subgroupheader{Return value}
383
384 - A tuple of suffix partial accumulations where each element 'I' equals
385 `f(get<0>(t), f(... , f(get<N-1>(t), init))`
386
387 @groupheader{Helper type}
388
389 @snippet include/kumi/algorithm/scan.hpp exclusive_scan_right_t
390
391 Computes the return type of a call to kumi::exclusive_scan_right
392
393 @groupheader{Examples}
394
395 @tab_begin
396
397 @tab{Tuple}
398 @godbolt{doc/tuple/algo/exclusive_scan_right.cpp}
399
400 @tab{Record}
401 @godbolt{doc/record/algo/exclusive_scan_right.cpp}
402
403 @tab_end
404 **/
405 //====================================================================================================================
406 KUMI_VARIABLE_ABI constexpr exclusive_scan_right_t exclusive_scan_right{};
407
408 namespace result
409 {
410 //! [inclusive_scan_right_t]
411 template<typename Function, kumi::concepts::product_type T, typename... Value>
412 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
413 using inclusive_scan_right_t =
414 decltype(kumi::inclusive_scan_right(std::declval<Function>(), std::declval<T>(), std::declval<Value>()...));
415
416 template<typename Function, kumi::concepts::product_type T, typename... Value>
417 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
418 struct inclusive_scan_right
419 {
420 using type = kumi::result::inclusive_scan_right_t<Function, T, Value...>;
421 };
422
423 //! [inclusive_scan_right_t]
424
425 //! [exclusive_scan_right_t]
426 template<typename Function, kumi::concepts::product_type T, typename... Value>
427 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
428 using exclusive_scan_right_t =
429 decltype(kumi::exclusive_scan_right(std::declval<Function>(), std::declval<T>(), std::declval<Value>()...));
430
431 template<typename Function, kumi::concepts::product_type T, typename... Value>
432 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
433 struct exclusive_scan_right
434 {
435 using type = kumi::result::exclusive_scan_right_t<Function, T, Value...>;
436 };
437
438 //! [exclusive_scan_right_t]
439
440 //! [inclusive_scan_left_t]
441 template<typename Function, kumi::concepts::product_type T, typename... Value>
442 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
443 using inclusive_scan_left_t =
444 decltype(kumi::inclusive_scan_left(std::declval<Function>(), std::declval<T>(), std::declval<Value>()...));
445
446 template<typename Function, kumi::concepts::product_type T, typename... Value>
447 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
448 struct inclusive_scan_left
449 {
450 using type = kumi::result::inclusive_scan_left_t<Function, T, Value...>;
451 };
452
453 //! [inclusive_scan_left_t]
454
455 //! [exclusive_scan_left_t]
456 template<typename Function, kumi::concepts::product_type T, typename... Value>
457 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
458 using exclusive_scan_left_t =
459 decltype(kumi::exclusive_scan_left(std::declval<Function>(), std::declval<T>(), std::declval<Value>()...));
460
461 template<typename Function, kumi::concepts::product_type T, typename... Value>
462 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
463 struct exclusive_scan_left
464 {
465 using type = kumi::result::exclusive_scan_left_t<Function, T, Value...>;
466 };
467
468 //! [exclusive_scan_left_t]
469 }
470 }
471