Tatooine
for_loop.h
Go to the documentation of this file.
1#ifndef TATOOINE_FOR_LOOP_H
2#define TATOOINE_FOR_LOOP_H
3//==============================================================================
4#include <tatooine/available_libraries.h>
6#include <tatooine/concepts.h>
7#include <tatooine/tags.h>
9#include <tatooine/utility.h>
10
11#include <array>
12#include <boost/range/algorithm/transform.hpp>
13#include <vector>
14#if TATOOINE_OPENMP_AVAILABLE
15#include <omp.h>
16#define TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE 1
17#else
18#define TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE 0
19#endif
20//==============================================================================
21namespace tatooine {
22//==============================================================================
23#if TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE
24static constexpr bool parallel_for_loop_support = true;
25#else
26static constexpr bool parallel_for_loop_support = false;
27#endif
28
29#if TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE
31 auto n = std::size_t{};
32#pragma omp parallel
33 {
34 if (omp_get_thread_num()) {
35 n = static_cast<std::size_t>(omp_get_num_threads());
36 }
37 }
38 return n;
39}
40
41template <typename T>
43 return std::vector<aligned<T>>(for_loop_num_parallel_threads());
44}
45#endif
46
47//==============================================================================
48namespace detail::for_loop {
49//==============================================================================
56template <typename Int, std::size_t N, std::size_t I, std::size_t ParallelIndex>
58 //----------------------------------------------------------------------------
59 // members
60 //----------------------------------------------------------------------------
61 public:
62 std::array<Int, N>& m_status;
63 std::array<Int, N> const& m_begins;
64 std::array<Int, N> const& m_ends;
65
66 //----------------------------------------------------------------------------
67 // methods
68 //----------------------------------------------------------------------------
69 private:
71 template <std::size_t... IndexSequence,
72 invocable<decltype(((void)IndexSequence, Int{}))...> Iteration>
73 constexpr auto loop(Iteration&& iteration,
74 std::index_sequence<IndexSequence...> /*unused*/) const {
75 // check if Iteration either returns bool or nothing
76 using return_type =
77 std::invoke_result_t<Iteration,
78 decltype(((void)IndexSequence, Int{}))...>;
79 constexpr bool returns_void = is_same<return_type, void>;
80 constexpr bool returns_bool = is_same<return_type, bool>;
81 static_assert(returns_void || returns_bool);
82 m_status[I - 1] = m_begins[I - 1];
83 for (; m_status[I - 1] < m_ends[I - 1]; ++m_status[I - 1]) {
84 if constexpr (returns_void) {
85 // if returns nothing just create another nested loop
86 for_loop_impl<Int, N, I - 1, ParallelIndex>{
87 m_status, m_begins, m_ends}(std::forward<Iteration>(iteration));
88 } else {
89 // if iteration returns bool and the current nested iteration returns
90 // false stop the whole nested for loop by recursively returning false
93 m_ends}(std::forward<Iteration>(iteration))) {
94 return false;
95 }
96 }
97 // reset nested status
98 m_status[I - 2] = m_begins[I - 2];
99 }
100 if constexpr (returns_bool) {
101 // return true if iteration never returned false
102 return true;
103 }
104 }
105
106 public:
107 template <typename Iteration>
108 constexpr auto operator()(Iteration&& iteration) const {
109 return loop(std::forward<Iteration>(iteration),
110 std::make_index_sequence<N>{});
111 }
112};
113//------------------------------------------------------------------------------
117template <typename Int, std::size_t N, std::size_t ParallelIndex>
119 //----------------------------------------------------------------------------
120 // members
121 //----------------------------------------------------------------------------
122 public:
123 std::array<Int, N>& m_status;
124 std::array<Int, N> const& m_begins;
125 std::array<Int, N> const& m_ends;
126
127 //----------------------------------------------------------------------------
128 // methods
129 //----------------------------------------------------------------------------
130 private:
131 template <std::size_t... IndexSequence,
132 invocable<decltype(((void)IndexSequence, Int{}))...> Iteration>
133 constexpr auto loop(Iteration&& iteration,
134 std::index_sequence<IndexSequence...> /*unused*/) const {
135 // check if Iteration either returns bool or nothing
136 using return_type =
137 std::invoke_result_t<Iteration,
138 decltype(((void)IndexSequence, Int{}))...>;
139 constexpr auto returns_void = is_same<return_type, void>;
140 constexpr auto returns_bool = is_same<return_type, bool>;
141 static_assert(returns_void || returns_bool);
142
143 m_status[0] = m_begins[0];
144 for (; m_status[0] < m_ends[0]; ++m_status[0]) {
145 if constexpr (returns_void) {
146 // if returns nothing just call it
147 iteration(m_status[IndexSequence]...);
148 } else {
149 // if iteration returns bool and the current iteration returns false
150 // stop the whole nested for loop by recursively returning false
151 if (!iteration(m_status[IndexSequence]...)) {
152 return false;
153 }
154 }
155 }
156 if constexpr (returns_bool) {
157 // return true if iteration never returned false
158 return true;
159 }
160 }
161
162 public:
163 template <typename Iteration>
164 constexpr auto operator()(Iteration&& iteration) const {
165 return loop(std::forward<Iteration>(iteration),
166 std::make_index_sequence<N>{});
167 }
168};
169#if TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE
170//==============================================================================
175template <typename Int, std::size_t N, std::size_t I>
177 //----------------------------------------------------------------------------
178 // members
179 //----------------------------------------------------------------------------
180 public:
181 std::array<Int, N>& m_status;
182 std::array<Int, N> const& m_begins;
183 std::array<Int, N> const& m_ends;
184
185 //----------------------------------------------------------------------------
186 // methods
187 //----------------------------------------------------------------------------
188 private:
190 template <std::size_t... IndexSequence,
191 invocable<decltype(((void)IndexSequence, Int{}))...> Iteration>
192 auto loop(Iteration&& iteration,
193 std::index_sequence<IndexSequence...> /*unused*/) const {
194 // check if Iteration either returns bool or nothing
195 using return_type =
196 std::invoke_result_t<Iteration,
197 decltype(((void)IndexSequence, Int{}))...>;
198 static constexpr auto returns_void = is_same<return_type, void>;
199 static constexpr auto returns_bool = is_same<return_type, bool>;
200 static_assert(returns_void || returns_bool);
201
202#pragma omp parallel for
203 for (Int i = m_begins[I - 1]; i < m_ends[I - 1]; ++i) {
204 auto status_copy = m_status;
205 status_copy[I - 1] = i;
206 if constexpr (returns_void) {
207 // if if returns nothing just create another nested loop
208 for_loop_impl<Int, N, I - 1, I>{
209 status_copy, m_begins, m_ends}(std::forward<Iteration>(iteration));
210 } else {
211 // if iteration returns bool and the current nested iteration returns
212 // false stop the whole nested for loop by recursively returning false
213 auto const cont = for_loop_impl<Int, N, I - 1, I>{
214 status_copy, m_begins, m_ends}(std::forward<Iteration>(iteration));
215 assert(cont && "cannot break in parallel loop");
216 }
217 }
218 if constexpr (returns_bool) {
219 // return true if iteration never returned false
220 return true;
221 }
222 }
223
224 public:
225 template <typename Iteration>
226 auto operator()(Iteration&& iteration) const {
227 return loop(std::forward<Iteration>(iteration),
228 std::make_index_sequence<N>{});
229 }
230};
231//------------------------------------------------------------------------------
236template <typename Int, std::size_t N>
238 //----------------------------------------------------------------------------
239 // members
240 //----------------------------------------------------------------------------
241 public:
242 std::array<Int, N>& m_status;
243 std::array<Int, N> const& m_begins;
244 std::array<Int, N> const& m_ends;
245
246 //----------------------------------------------------------------------------
247 // methods
248 //----------------------------------------------------------------------------
249 private:
250 template <std::size_t... IndexSequence,
251 invocable<decltype(((void)IndexSequence, Int{}))...> Iteration>
252 auto loop(Iteration&& iteration,
253 std::index_sequence<IndexSequence...> /*seq*/) const {
254 // check if Iteration either returns bool or nothing
255 using return_type =
256 std::invoke_result_t<Iteration,
257 decltype(((void)IndexSequence, Int{}))...>;
258 constexpr bool returns_void = is_same<return_type, void>;
259 constexpr bool returns_bool = is_same<return_type, bool>;
260 static_assert(returns_void || returns_bool);
261
262#pragma omp parallel for
263 for (Int i = m_begins[0]; i < m_ends[0]; ++i) {
264 auto status_copy = m_status;
265 status_copy[0] = i;
266 if constexpr (returns_void) {
267 // if if returns nothing just call it
268 iteration(status_copy[IndexSequence]...);
269 } else {
270 // if iteration returns bool and the current iteration returns false
271 // stop the whole nested for loop by recursively returning false
272 auto const cont = iteration(status_copy[IndexSequence]...);
273 assert(cont && "cannot break in parallel loop");
274 }
275 }
276 if constexpr (returns_bool) {
277 // return true if iteration never returned false
278 return true;
279 }
280 }
281
282 public:
283 template <typename Iteration>
284 auto operator()(Iteration&& iteration) const {
285 return loop(std::forward<Iteration>(iteration),
286 std::make_index_sequence<N>{});
287 }
288};
289#endif // TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE
290//==============================================================================
291template <std::size_t ParallelIndex, typename Int, Int... IndexSequence,
292 integral... Ranges,
293 invocable<decltype(((void)IndexSequence, Int{}))...> Iteration>
294constexpr auto for_loop(Iteration&& iteration,
295 std::integer_sequence<Int, IndexSequence...>,
296 std::pair<Ranges, Ranges> const&... ranges) {
297 // check if Iteration either returns bool or nothing
298 using return_type =
299 std::invoke_result_t<Iteration,
300 decltype(((void)IndexSequence, Int{}))...>;
301 constexpr bool returns_void = is_same<return_type, void>;
302 constexpr bool returns_bool = is_same<return_type, bool>;
303 static_assert(returns_void || returns_bool);
304
305 auto status =
306 std::array{((void)IndexSequence, static_cast<Int>(ranges.first))...};
307 auto const begins =
308 std::array{((void)IndexSequence, static_cast<Int>(ranges.first))...};
309 auto const ends = std::array{static_cast<Int>(ranges.second)...};
310 return for_loop_impl<Int, sizeof...(ranges), sizeof...(ranges),
311 ParallelIndex + 1>{
312 status, begins, ends}(std::forward<Iteration>(iteration));
313}
314//==============================================================================
315} // namespace detail::for_loop
316//==============================================================================
317template <typename Iteration, typename Range>
319 std::invocable<Iteration, std::ranges::iterator_t<Range>> &&
321 void, bool>;
322//------------------------------------------------------------------------------
323template <typename Iteration, typename IntRange>
325 std::invocable<Iteration, IntRange> &&
327//------------------------------------------------------------------------------
335template <typename Int = std::size_t, typename Iteration, integral... Ranges>
336constexpr auto for_loop(Iteration&& iteration, execution_policy::sequential_t,
337 Ranges (&&... ranges)[2]) -> void {
338 detail::for_loop::for_loop<sizeof...(ranges) + 1, Int>(
339 std::forward<Iteration>(iteration),
340 std::make_integer_sequence<Int, sizeof...(ranges)>{},
341 std::pair{ranges[0], ranges[1]}...);
342}
343// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
351template <typename Int = std::size_t, typename Iteration, integral... Ranges>
352constexpr auto for_loop(Iteration&& iteration, execution_policy::sequential_t,
353 std::pair<Ranges, Ranges> const&... ranges) -> void {
354 detail::for_loop::for_loop<sizeof...(ranges) + 1, Int>(
355 std::forward<Iteration>(iteration),
356 std::make_integer_sequence<Int, sizeof...(ranges)>{}, ranges...);
357}
358// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
366template <typename Int = std::size_t, typename Iteration, integral... Ends>
367constexpr auto for_loop(Iteration&& iteration, execution_policy::sequential_t,
368 Ends const... ends) -> void {
369 detail::for_loop::for_loop<sizeof...(ends) + 1, Int>(
370 std::forward<Iteration>(iteration),
371 std::make_integer_sequence<Int, sizeof...(ends)>{},
372 std::pair{Ends(0), ends}...);
373}
374//------------------------------------------------------------------------------
382template <typename Int = std::size_t, typename Iteration, integral... Ranges>
383constexpr auto for_loop([[maybe_unused]] Iteration&& iteration,
385 [[maybe_unused]] Ranges (&&... ranges)[2]) -> void
387{
388#if TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE
389 return detail::for_loop::for_loop<sizeof...(ranges) - 1, Int>(
390 std::forward<Iteration>(iteration),
391 std::make_integer_sequence<Int, sizeof...(ranges)>{},
392 std::pair{ranges[0], ranges[1]}...);
393#endif
394}
395// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
403template <typename Int = std::size_t, typename Iteration, integral... Ranges>
404constexpr auto for_loop(
405 [[maybe_unused]] Iteration&& iteration,
407 [[maybe_unused]] std::pair<Ranges, Ranges> const&... ranges) -> void
409{
410#if TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE
411 return detail::for_loop::for_loop<sizeof...(ranges) - 1, Int>(
412 std::forward<Iteration>(iteration),
413 std::make_integer_sequence<Int, sizeof...(ranges)>{}, ranges...);
414#endif
415}
416// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
424template <typename Int = std::size_t, typename Iteration, integral... Ends>
425constexpr auto for_loop([[maybe_unused]] Iteration&& iteration,
427 [[maybe_unused]] Ends const... ends) -> void
429{
430#if TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE
431 return detail::for_loop::for_loop<sizeof...(ends) - 1, Int>(
432 std::forward<Iteration>(iteration),
433 std::make_integer_sequence<Int, sizeof...(ends)>{},
434 std::pair{Ends(0), ends}...);
435#endif
436}
437//==============================================================================
445template <typename Int = std::size_t, typename Iteration, integral... Ranges>
446constexpr auto for_loop(Iteration&& iteration, Ranges (&&... ranges)[2])
447 -> void {
448 for_loop(std::forward<Iteration>(iteration), execution_policy::sequential,
449 std::pair{ranges[0], ranges[1]}...);
450}
451// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
459template <typename Int = std::size_t, typename Iteration, integral... Ranges>
460constexpr auto for_loop(Iteration&& iteration,
461 std::pair<Ranges, Ranges> const&... ranges) -> void {
462 for_loop(std::forward<Iteration>(iteration), execution_policy::sequential,
463 ranges...);
464}
465// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
473template <typename Int = std::size_t, typename Iteration, integral... Ends>
474constexpr auto for_loop(Iteration&& iteration, Ends const... ends) -> void {
475 for_loop(std::forward<Iteration>(iteration), execution_policy::sequential,
476 ends...);
477}
478// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
479template <typename Iteration, integral Int, std::size_t N>
480auto for_loop_unpacked(Iteration&& iteration, execution_policy_tag auto policy,
481 std::array<Int, N> const& sizes) {
483 [&](auto const... is) {
484 for_loop(std::forward<Iteration>(iteration), policy, is...);
485 },
486 unpack(sizes));
487}
488// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
489template <typename Iteration, integral Int, std::size_t N>
490auto for_loop_unpacked(Iteration&& iteration, std::array<Int, N> const& sizes) {
491 for_loop_unpacked(std::forward<Iteration>(iteration),
493}
494//==============================================================================
495template <typename Int = std::size_t, integral... Ends>
496constexpr auto chunked_for_loop(
497 invocable<decltype(((void)std::declval<Ends>(),
498 std::declval<Int>()))...> auto&& iteration,
499 execution_policy_tag auto policy, integral auto const chunk_size,
500 Ends const... ends) -> void {
501 for_loop(
502 [&](auto const... chunk_is) {
503 for_loop(
504 [&](auto const... inner_is) {
505 iteration((chunk_is * chunk_size + inner_is)...);
506 },
507 policy, std::min<Int>(chunk_size, chunk_is * chunk_size - ends)...);
508 },
509 ends / chunk_size...);
510}
511//------------------------------------------------------------------------------
512template <typename Int = std::size_t, typename Iteration, integral... Ends>
513requires invocable<Iteration,
514 decltype((std::declval<Ends>(), std::declval<Int>()))...>
515constexpr auto chunked_for_loop(Iteration&& iteration,
516 integral auto const chunk_size,
517 Ends const... ends) -> void {
518 chunked_for_loop(std::forward<Iteration>(iteration),
519 execution_policy::sequential, chunk_size, ends...);
520}
521//==============================================================================
524template <integral_pair_range IntPairRange,
525 for_loop_nested_index_iteration<std::vector<common_type<
526 typename std::ranges::range_value_t<IntPairRange>::first_type,
527 typename std::ranges::range_value_t<IntPairRange>::second_type>>>
528 Iteration>
529auto for_loop(Iteration&& iteration, IntPairRange const& ranges,
531 using integral_pair_t = std::ranges::range_value_t<IntPairRange>;
532 using int_t = common_type<typename integral_pair_t::first_type,
533 typename integral_pair_t::second_type>;
534 using iteration_invoke_result_type =
535 std::invoke_result_t<Iteration, std::vector<int_t>>;
536 auto cur_indices = std::vector<int_t>(size(ranges));
537 std::transform(
538 begin(ranges), end(ranges), begin(cur_indices),
539 [](auto const& range) { return static_cast<int_t>(range.first); });
540 auto finished = false;
541 while (!finished) {
543 auto const can_continue = iteration(cur_indices);
544 if (!can_continue) {
545 finished = true;
546 }
547 } else {
548 iteration(cur_indices);
549 }
550 ++cur_indices.front();
551 for (std::size_t i = 0; i < size(ranges) - 1; ++i) {
552 if (cur_indices[i] == static_cast<int_t>(ranges[i].second)) {
553 cur_indices[i] = static_cast<int_t>(ranges[i].first);
554 ++cur_indices[i + 1];
555 if (i == size(ranges) - 2 &&
556 cur_indices[i + 1] == static_cast<int_t>(ranges[i + 1].second)) {
557 finished = true;
558 }
559 } else {
560 break;
561 }
562 }
563 }
564}
565// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
568template <integral_pair_range IntPairRange,
569 for_loop_nested_index_iteration<std::vector<common_type<
570 typename std::ranges::range_value_t<IntPairRange>::first_type,
571 typename std::ranges::range_value_t<IntPairRange>::second_type>>>
572 Iteration>
573auto for_loop(Iteration&& iteration, IntPairRange const& ranges,
574 execution_policy_tag auto policy) {
575 for_loop(std::forward<Iteration>(iteration), ranges, policy);
576}
577// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
580template <integral_pair_range IntPairRange,
581 for_loop_nested_index_iteration<std::vector<common_type<
582 typename std::ranges::range_value_t<IntPairRange>::first_type,
583 typename std::ranges::range_value_t<IntPairRange>::second_type>>>
584 Iteration>
585auto for_loop(Iteration&& iteration, IntPairRange const& ranges) {
586 for_loop(std::forward<Iteration>(iteration), ranges,
588}
589//------------------------------------------------------------------------------
592template <integral_range IntRange,
593 for_loop_nested_index_iteration<IntRange> Iteration>
594auto for_loop(Iteration&& iteration, IntRange const& begin,
595 IntRange const& ends, execution_policy::sequential_t)
596/*-> std::invoke_result_t<Iteration, decltype(status)>*/ {
597 assert(size(begin) == size(ends));
598 auto const nesting_depth = size(ends);
599 using int_t = std::ranges::range_value_t<IntRange>;
600 using iteration_invoke_result_type =
601 std::invoke_result_t<Iteration, std::vector<int_t>>;
602 auto cur_indices = begin;
603 auto finished = false;
604 while (!finished) {
606 auto const can_continue = iteration(cur_indices);
607 if (!can_continue) {
608 finished = true;
609 }
610 } else {
611 iteration(cur_indices);
612 }
613 ++cur_indices.front();
614 for (std::size_t i = 0; i < nesting_depth - 1; ++i) {
615 if (cur_indices[i] == ends[i]) {
616 cur_indices[i] = begin[i];
617 ++cur_indices[i + 1];
618 if (i == nesting_depth - 2 && cur_indices[i + 1] == ends[i + 1]) {
619 finished = true;
620 }
621 } else {
622 break;
623 }
624 }
625 }
626}
627//------------------------------------------------------------------------------
630template <integral_range IntRange,
631 for_loop_nested_index_iteration<IntRange> Iteration>
632auto for_loop(Iteration&& iteration, IntRange const& begin,
633 IntRange const& ends) {
634 return for_loop(std::forward<Iteration>(iteration), begin, ends,
636}
637//------------------------------------------------------------------------------
640template <integral_range IntRange,
641 for_loop_nested_index_iteration<IntRange> Iteration>
642auto for_loop(Iteration&& iteration, IntRange const& ends,
643 execution_policy_tag auto policy) {
644 using int_t = std::ranges::range_value_t<IntRange>;
645 for_loop<int_t>(std::forward<Iteration>(iteration),
646 std::vector<int_t>(size(ends), 0), ends, policy);
647}
648//------------------------------------------------------------------------------
651template <integral_range IntRange,
652 for_loop_nested_index_iteration<IntRange> Iteration>
653auto for_loop(Iteration&& iteration, IntRange const& ends) {
654 using int_t = std::ranges::range_value_t<IntRange>;
655 for_loop(std::forward<Iteration>(iteration),
656 std::vector<int_t>(size(ends), 0), ends,
658}
659//------------------------------------------------------------------------------
661template <range Range, for_loop_range_iteration<Range> Iteration>
662requires(!integral<std::ranges::range_value_t<Range>>) &&
663 (!integral_pair<std::ranges::range_value_t<Range>>)
664 auto for_loop([[maybe_unused]] Iteration&& iteration,
665 [[maybe_unused]] Range&& r,
668{
669#if TATOOINE_PARALLEL_FOR_LOOPS_AVAILABLE
670#pragma omp parallel for
671 for (auto it = std::ranges::begin(r); it != std::ranges::end(r); ++it) {
672 iteration(it);
673 }
674#endif
675}
676//------------------------------------------------------------------------------
678template <range Range, for_loop_range_iteration<Range> Iteration>
679requires(!integral<std::ranges::range_value_t<Range>>) &&
680 (!integral_pair<std::ranges::range_value_t<Range>>)
681auto for_loop(Iteration&& iteration, Range&& r,
683 using iteration_invoke_result_type =
684 std::invoke_result_t<Iteration, std::ranges::iterator_t<Range>>;
685 for (auto it = std::ranges::begin(r); it != std::ranges::end(r); ++it) {
687 auto const can_continue = iteration(it);
688 if (!can_continue) {
689 break;
690 }
691 } else {
692 iteration(it);
693 }
694 }
695}
696//------------------------------------------------------------------------------
698template <range Range, for_loop_range_iteration<Range> Iteration>
699requires(!integral<std::ranges::range_value_t<Range>>) &&
700 (!integral_pair<std::ranges::range_value_t<Range>>)
701auto for_loop(Iteration&& iteration, Range const& r) {
702 for_loop(std::forward<Iteration>(iteration), r, execution_policy::sequential);
703}
704//==============================================================================
705} // namespace tatooine
706//==============================================================================
707#endif
Definition: concepts.h:18
Definition: tags.h:72
Definition: for_loop.h:318
Definition: concepts.h:21
Definition: concepts.h:121
Definition: concepts.h:84
Definition: concepts.h:15
constexpr auto for_loop(Iteration &&iteration, std::integer_sequence< Int, IndexSequence... >, std::pair< Ranges, Ranges > const &... ranges)
Definition: for_loop.h:294
static constexpr sequential_t sequential
Definition: tags.h:63
Definition: algorithm.h:6
typename common_type_impl< Ts... >::type common_type
Definition: common_type.h:23
auto begin(Range &&range)
Definition: iterator_facade.h:318
static constexpr bool parallel_for_loop_support
Definition: for_loop.h:24
auto end(Range &&range)
Definition: iterator_facade.h:322
constexpr auto chunked_for_loop(invocable< decltype(((void) std::declval< Ends >(), std::declval< Int >()))... > auto &&iteration, execution_policy_tag auto policy, integral auto const chunk_size, Ends const ... ends) -> void
Definition: for_loop.h:496
auto for_loop_unpacked(Iteration &&iteration, execution_policy_tag auto policy, std::array< Int, N > const &sizes)
Definition: for_loop.h:480
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
constexpr decltype(auto) invoke_unpacked(F &&f)
All arguments are bound -> just call f.
Definition: invoke_unpacked.h:15
auto for_loop_num_parallel_threads()
Definition: for_loop.h:30
constexpr auto for_loop(Iteration &&iteration, execution_policy::sequential_t, Ranges(&&... ranges)[2]) -> void
Use this function for creating a sequential nested loop.
Definition: for_loop.h:336
auto create_aligned_data_for_parallel()
Definition: for_loop.h:42
std::array< Int, N > & m_status
Definition: for_loop.h:242
std::array< Int, N > const & m_begins
Definition: for_loop.h:243
auto loop(Iteration &&iteration, std::index_sequence< IndexSequence... >) const
Definition: for_loop.h:252
std::array< Int, N > const & m_ends
Definition: for_loop.h:244
auto operator()(Iteration &&iteration) const
Definition: for_loop.h:284
constexpr auto loop(Iteration &&iteration, std::index_sequence< IndexSequence... >) const
Definition: for_loop.h:133
std::array< Int, N > & m_status
Definition: for_loop.h:123
std::array< Int, N > const & m_ends
Definition: for_loop.h:125
constexpr auto operator()(Iteration &&iteration) const
Definition: for_loop.h:164
std::array< Int, N > const & m_begins
Definition: for_loop.h:124
std::array< Int, N > const & m_ends
Definition: for_loop.h:183
std::array< Int, N > & m_status
Definition: for_loop.h:181
auto operator()(Iteration &&iteration) const
Definition: for_loop.h:226
std::array< Int, N > const & m_begins
Definition: for_loop.h:182
auto loop(Iteration &&iteration, std::index_sequence< IndexSequence... >) const
recursively creates loops
Definition: for_loop.h:192
std::array< Int, N > const & m_begins
Definition: for_loop.h:63
constexpr auto operator()(Iteration &&iteration) const
Definition: for_loop.h:108
constexpr auto loop(Iteration &&iteration, std::index_sequence< IndexSequence... >) const
recursively creates loops
Definition: for_loop.h:73
std::array< Int, N > const & m_ends
Definition: for_loop.h:64
std::array< Int, N > & m_status
Definition: for_loop.h:62
Definition: invoke_unpacked.h:11