| 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 | namespace _ | ||
| 13 | { | ||
| 14 | template<typename F, typename T, typename V, std::size_t... I> | ||
| 15 | 10 | KUMI_HIDDEN_ABI constexpr auto fold_left_(kumi::_::adl_tag_t, F f, T&& t, V v, std::index_sequence<I...>) | |
| 16 | { | ||
| 17 |
10/10✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 10 taken 6 times.
✓ Branch 14 taken 2 times.
✓ Branch 18 taken 2 times.
✓ Branch 22 taken 2 times.
✓ Branch 26 taken 2 times.
✓ Branch 30 taken 2 times.
|
158 | return (kumi::function::foldable{v} >> ... >> kumi::bind_back(f, get<I>(KUMI_FWD(t))))(); |
| 18 | 6 | } | |
| 19 | |||
| 20 | template<typename F, typename T, typename V, std::size_t... I> | ||
| 21 | 10 | KUMI_HIDDEN_ABI constexpr auto fold_right_(kumi::_::adl_tag_t, F f, T&& t, V v, std::index_sequence<I...>) | |
| 22 | { | ||
| 23 |
8/8✓ Branch 8 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 14 taken 2 times.
✓ Branch 17 taken 2 times.
✓ Branch 20 taken 2 times.
✓ Branch 23 taken 2 times.
✓ Branch 26 taken 2 times.
✓ Branch 29 taken 2 times.
|
148 | return (kumi::bind_front(f, get<I>(KUMI_FWD(t))) << ... << kumi::function::foldable{v})(); |
| 24 | 6 | } | |
| 25 | } | ||
| 26 | |||
| 27 | struct fold_left_t | ||
| 28 | { | ||
| 29 | template<typename Function, kumi::concepts::product_type T, typename Value> | ||
| 30 | [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t, Value init) const | ||
| 31 | { | ||
| 32 |
1/1✓ Branch 1 taken 2 times.
|
4 | if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t)), init); |
| 33 | else if constexpr (kumi::concepts::empty_product_type<T>) return init; | ||
| 34 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
|
4 | else return fold_left_(kumi::_::adl_tag, f, KUMI_FWD(t), init, kumi::function::indexes_for<T>{}); |
| 35 | } | ||
| 36 | |||
| 37 | template<typename Function, kumi::concepts::non_empty_product_type T> | ||
| 38 | [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t) const | ||
| 39 | { | ||
| 40 | 1 | if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t))); | |
| 41 | else if constexpr (kumi::concepts::sized_product_type<T, 1>) return get<0>(KUMI_FWD(t)); | ||
| 42 | else | ||
| 43 |
1/1✓ Branch 1 taken 2 times.
|
2 | return fold_left_(kumi::_::adl_tag, f, KUMI_FWD(t), get<0>(KUMI_FWD(t)), |
| 44 | 2 | kumi::function::shift_index_sequence<1, kumi::size_v<T> - 1>{}); | |
| 45 | } | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct fold_right_t | ||
| 49 | { | ||
| 50 | template<typename Function, kumi::concepts::product_type T, typename Value> | ||
| 51 | [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t, Value init) const | ||
| 52 | { | ||
| 53 |
1/1✓ Branch 1 taken 2 times.
|
4 | if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t)), init); |
| 54 | else if constexpr (kumi::concepts::empty_product_type<T>) return init; | ||
| 55 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
|
4 | else return fold_right_(kumi::_::adl_tag, f, KUMI_FWD(t), init, kumi::function::indexes_for<T>{}); |
| 56 | } | ||
| 57 | |||
| 58 | template<typename Function, kumi::concepts::non_empty_product_type T> | ||
| 59 | [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t) const | ||
| 60 | { | ||
| 61 | 1 | if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t))); | |
| 62 | else if constexpr (kumi::concepts::sized_product_type<T, 1>) return get<0>(KUMI_FWD(t)); | ||
| 63 | else | ||
| 64 |
1/1✓ Branch 1 taken 2 times.
|
2 | return fold_right_(kumi::_::adl_tag, f, KUMI_FWD(t), get<0>(KUMI_FWD(t)), |
| 65 | 2 | kumi::function::shift_index_sequence<1, kumi::size_v<T> - 1>{}); | |
| 66 | } | ||
| 67 | }; | ||
| 68 | |||
| 69 | //==================================================================================================================== | ||
| 70 | /** | ||
| 71 | @ingroup kumi_reductions | ||
| 72 | |||
| 73 | @var fold_left | ||
| 74 | @brief Callable object computing the generalized combination of all elements using a tail recursive call. | ||
| 75 | |||
| 76 | On record types, this function operates on the underlying values, not on the fields themselves. | ||
| 77 | |||
| 78 | @qualifier nodiscard | ||
| 79 | @qualifier inline | ||
| 80 | @qualifier constexpr | ||
| 81 | |||
| 82 | @groupheader{Header file} | ||
| 83 | @code | ||
| 84 | #include <kumi/algorithm/fold.hpp> | ||
| 85 | @endcode | ||
| 86 | |||
| 87 | @groupheader{Call Signature} | ||
| 88 | |||
| 89 | @code | ||
| 90 | template<typename Function, product_type T, typename Value> | ||
| 91 | constexpr auto fold_left(Function && f, T && t, Value init); | ||
| 92 | @endcode | ||
| 93 | |||
| 94 | @code | ||
| 95 | template<typename Function, product_type T> | ||
| 96 | constexpr auto fold_left(Function && f, T && t); | ||
| 97 | @endcode | ||
| 98 | |||
| 99 | @subgroupheader{Parameters} | ||
| 100 | |||
| 101 | - `f`: Binary callable function to apply | ||
| 102 | - `t`: Product type to operate on | ||
| 103 | - `init`: Optional initial value of the fold, first element is used otherwise | ||
| 104 | |||
| 105 | @subgroupheader{Return value} | ||
| 106 | |||
| 107 | - The resulting value of the application of the function `f( f( f(init, get<0>(t)), ...), get<N-1>(t))` | ||
| 108 | |||
| 109 | @groupheader{Helper type} | ||
| 110 | |||
| 111 | @snippet include/kumi/algorithm/fold.hpp fold_left_t | ||
| 112 | |||
| 113 | Computes the return type of a call to kumi::fold_left | ||
| 114 | |||
| 115 | @groupheader{Examples} | ||
| 116 | |||
| 117 | @tab_begin | ||
| 118 | |||
| 119 | @tab{Tuple} | ||
| 120 | @godbolt{doc/tuple/algo/fold_left.cpp} | ||
| 121 | |||
| 122 | @tab{Record} | ||
| 123 | @godbolt{doc/record/algo/fold_left.cpp} | ||
| 124 | |||
| 125 | @tab_end | ||
| 126 | **/ | ||
| 127 | //==================================================================================================================== | ||
| 128 | KUMI_VARIABLE_ABI constexpr fold_left_t fold_left{}; | ||
| 129 | |||
| 130 | //==================================================================================================================== | ||
| 131 | /** | ||
| 132 | @ingroup kumi_reductions | ||
| 133 | |||
| 134 | @var fold_right | ||
| 135 | @brief Callable object computing the generalized combination of all elements using a non-tail recursive call. | ||
| 136 | |||
| 137 | On record types, this function operates on the underlying values, not on the fields themselves. | ||
| 138 | |||
| 139 | @qualifier nodiscard | ||
| 140 | @qualifier inline | ||
| 141 | @qualifier constexpr | ||
| 142 | |||
| 143 | @groupheader{Header file} | ||
| 144 | @code | ||
| 145 | #include <kumi/algorithm/fold.hpp> | ||
| 146 | @endcode | ||
| 147 | |||
| 148 | @groupheader{Call Signature} | ||
| 149 | |||
| 150 | @code | ||
| 151 | template<typename Function, product_type T, typename Value> | ||
| 152 | constexpr auto fold_right(Function && f, T && t, Value init); | ||
| 153 | @endcode | ||
| 154 | |||
| 155 | @code | ||
| 156 | template<typename Function, product_type T> | ||
| 157 | constexpr auto fold_right(Function && f, T && t); | ||
| 158 | @endcode | ||
| 159 | |||
| 160 | @subgroupheader{Parameters} | ||
| 161 | |||
| 162 | - `f`: Binary callable function to apply | ||
| 163 | - `t`: Product type to operate on | ||
| 164 | - `init`: Optional initial value of the fold, last element is used otherwise | ||
| 165 | |||
| 166 | @subgroupheader{Return value} | ||
| 167 | |||
| 168 | - The resulting value of the application of the function `f(get<0>(t), f(... , f(get<N-1>(t), init))` | ||
| 169 | |||
| 170 | @groupheader{Helper type} | ||
| 171 | |||
| 172 | @snippet include/kumi/algorithm/fold.hpp fold_right_t | ||
| 173 | |||
| 174 | Computes the return type of a call to kumi::fold_right | ||
| 175 | |||
| 176 | @groupheader{Examples} | ||
| 177 | |||
| 178 | @tab_begin | ||
| 179 | |||
| 180 | @tab{Tuple} | ||
| 181 | @godbolt{doc/tuple/algo/fold_right.cpp} | ||
| 182 | |||
| 183 | @tab{Record} | ||
| 184 | @godbolt{doc/record/algo/fold_right.cpp} | ||
| 185 | |||
| 186 | @tab_end | ||
| 187 | **/ | ||
| 188 | //==================================================================================================================== | ||
| 189 | KUMI_VARIABLE_ABI constexpr fold_right_t fold_right{}; | ||
| 190 | |||
| 191 | namespace result | ||
| 192 | { | ||
| 193 | //! [fold_left_t] | ||
| 194 | template<typename Function, kumi::concepts::product_type T, typename... Value> | ||
| 195 | requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1)) | ||
| 196 | using fold_left_t = | ||
| 197 | decltype(kumi::fold_left(std::declval<Function>(), std::declval<T>(), std::declval<Value>()...)); | ||
| 198 | |||
| 199 | template<typename Function, kumi::concepts::product_type T, typename... Value> | ||
| 200 | requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1)) | ||
| 201 | struct fold_left | ||
| 202 | { | ||
| 203 | using type = kumi::result::fold_left_t<Function, T, Value...>; | ||
| 204 | }; | ||
| 205 | |||
| 206 | //! [fold_left_t] | ||
| 207 | |||
| 208 | //! [fold_right_t] | ||
| 209 | template<typename Function, kumi::concepts::product_type T, typename... Value> | ||
| 210 | requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1)) | ||
| 211 | using fold_right_t = | ||
| 212 | decltype(kumi::fold_right(std::declval<Function>(), std::declval<T>(), std::declval<Value>()...)); | ||
| 213 | |||
| 214 | template<typename Function, kumi::concepts::product_type T, typename... Value> | ||
| 215 | requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1)) | ||
| 216 | struct fold_right | ||
| 217 | { | ||
| 218 | using type = kumi::result::fold_right_t<Function, T, Value...>; | ||
| 219 | }; | ||
| 220 | |||
| 221 | //! [fold_right_t] | ||
| 222 | } | ||
| 223 | } | ||
| 224 |