TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
for_each.hpp
Go to the documentation of this file.
1// Copyright (c) 2018--present, The Simons Foundation
2// This file is part of TRIQS/nda and is licensed under the Apache License, Version 2.0.
3// SPDX-License-Identifier: Apache-2.0
4// See LICENSE in the root of this distribution for details.
5
10
11#pragma once
12
13#include "./permutation.hpp"
14#include "../stdutil/array.hpp"
15
16#include <array>
17#include <concepts>
18#include <cstdint>
19#include <utility>
20
21namespace nda {
22
27
28 namespace detail {
29
30 // Get the i-th slowest moving dimension from a given encoded stride order.
31 template <int R>
32 constexpr int index_from_stride_order(uint64_t stride_order, int i) {
33 if (stride_order == 0) return i; // default C-order
34 auto stride_order_arr = decode<R>(stride_order); // FIXME C++20
35 return stride_order_arr[i];
36 }
37
38 // Get the extent of an array along its i-th dimension.
39 template <int I, int R, uint64_t StaticExtents, std::integral Int = long>
40 constexpr long get_extent(std::array<Int, R> const &shape) {
41 if constexpr (StaticExtents == 0) {
42 // dynamic extents
43 return shape[I];
44 } else {
45 // full/partial static extents
46 constexpr auto static_extents = decode<R>(StaticExtents); // FIXME C++20
47 if constexpr (static_extents[I] == 0)
48 return shape[I];
49 else
50 return static_extents[I];
51 }
52 }
53
54 // Apply a callable object recursively to all possible index values of a given shape.
55 template <int I, uint64_t StaticExtents, uint64_t StrideOrder, typename F, size_t R, std::integral Int = long>
56 FORCEINLINE void for_each_static_impl(std::array<Int, R> const &shape, std::array<long, R> &idxs, F &f) {
57 if constexpr (I == R) {
58 // end of recursion
59 std::apply(f, idxs);
60 } else {
61 // get the dimension over which to iterate and its extent
62 static constexpr int J = index_from_stride_order<R>(StrideOrder, I);
63 const long imax = get_extent<J, R, StaticExtents>(shape);
64
65 // loop over all indices of the current dimension
66 for (long i = 0; i < imax; ++i) {
67 // recursive call for the next dimension
68 for_each_static_impl<I + 1, StaticExtents, StrideOrder>(shape, idxs, f);
69 ++idxs[J];
70 }
71 idxs[J] = 0;
72 }
73 }
74
75 } // namespace detail
76
94 template <uint64_t StaticExtents, uint64_t StrideOrder, typename F, auto R, std::integral Int = long>
95 FORCEINLINE void for_each_static(std::array<Int, R> const &shape, F &&f) { // NOLINT (we do not want to forward here)
97 detail::for_each_static_impl<0, StaticExtents, StrideOrder>(shape, idxs, f);
98 }
99
115 template <typename F, auto R, std::integral Int = long>
116 FORCEINLINE void for_each(std::array<Int, R> const &shape, F &&f) { // NOLINT (we do not want to forward here)
118 detail::for_each_static_impl<0, 0, 0>(shape, idxs, f);
119 }
120
122
123} // namespace nda
Provides utility functions for std::array.
constexpr uint64_t static_extents(int i0, Is... is)
Encode the given shape into a single integer using the nda::encode function.
__inline__ void for_each(std::array< Int, R > const &shape, F &&f)
Loop over all possible index values of a given shape and apply a function to them.
Definition for_each.hpp:116
__inline__ void for_each_static(std::array< Int, R > const &shape, F &&f)
Loop over all possible index values of a given shape and apply a function to them.
Definition for_each.hpp:95
constexpr std::array< int, N > decode(uint64_t binary_representation)
Decode a uint64_t into a std::array<int, N>.
constexpr std::array< T, R > make_initialized_array(T v)
Create a new std::array object initialized with a specific value.
Definition array.hpp:155
Provides utilities to work with permutations and to compactly encode/decode std::array objects.