TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
layout_transforms.hpp
Go to the documentation of this file.
1// Copyright (c) 2019--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 "./concepts.hpp"
14#include "./declarations.hpp"
15#include "./group_indices.hpp"
16#include "./layout/idx_map.hpp"
18#include "./layout/policies.hpp"
19#include "./map.hpp"
20#include "./stdutil/array.hpp"
21#include "./traits.hpp"
22
23#include <array>
24#include <concepts>
25#include <type_traits>
26#include <utility>
27
28#ifndef NDEBUG
29#include <numeric>
30#endif // NDEBUG
31
32namespace nda {
33
38
58 template <MemoryArray A, typename NewLayoutType>
59 auto map_layout_transform([[maybe_unused]] A &&a, [[maybe_unused]] NewLayoutType const &new_layout) {
60 using A_t = std::remove_reference_t<A>;
61
62 // layout policy of transformed array/view
63 using layout_policy = typename detail::layout_to_policy<NewLayoutType>::type;
64
65 // algebra of transformed array/view
66 static constexpr auto algebra = (NewLayoutType::rank() == get_rank<A> ? get_algebra<A> : 'A');
67
68 if constexpr (is_regular_v<A> and !std::is_reference_v<A>) {
69 // return a transformed array if the given type is an rvalue array
70 using array_t = basic_array<typename A_t::value_type, NewLayoutType::rank(), layout_policy, algebra, typename A_t::container_policy_t>;
71 return array_t{new_layout, std::forward<A>(a).storage()};
72 } else {
73 // otherwise return a transformed view
74 using value_t = std::conditional_t<std::is_const_v<A_t>, const typename A_t::value_type, typename A_t::value_type>;
75 using accessor_policy = typename get_view_t<A>::accessor_policy_t;
76 using owning_policy = typename get_view_t<A>::owning_policy_t;
77 return basic_array_view<value_t, NewLayoutType::rank(), layout_policy, algebra, accessor_policy, owning_policy>{new_layout, a.storage()};
78 }
79 }
80
96 template <MemoryArray A, std::integral Int, auto R>
97 auto reshape(A &&a, std::array<Int, R> const &new_shape) {
98 // check size and contiguity of new shape
99 EXPECTS_WITH_MESSAGE(a.size() == (std::accumulate(new_shape.cbegin(), new_shape.cend(), Int{1}, std::multiplies<>{})),
100 "Error in nda::reshape: New shape has an incorrect number of elements");
101 EXPECTS_WITH_MESSAGE(a.is_contiguous(), "Error in nda::reshape: Only contiguous arrays/views are supported");
102 EXPECTS_WITH_MESSAGE(a.has_positive_strides(), "Error in nda::reshape: Only arrays/views with positive strides are supported")
103
104 // restrict supported layouts
105 using A_t = std::remove_cvref_t<A>;
106 static_assert(A_t::is_stride_order_C() or A_t::is_stride_order_Fortran() or R == 1,
107 "Error in nda::reshape: Only C or Fortran layouts are supported");
108
109 // prepare new idx_map
110 // 1D case --> resulting layout is always C
111 // multi-dimensional case (only C or Fortran layout allowed) --> resulting layout is the same as the input
112 using layout_t = std::conditional_t<(R == 1), C_layout::template mapping<1>, typename std::decay_t<A>::layout_policy_t::template mapping<R>>;
113 return map_layout_transform(std::forward<A>(a), layout_t{stdutil::make_std_array<long>(new_shape)});
114 }
115
127 template <MemoryArray A, std::integral... Ints>
128 auto reshape(A &&a, Ints... is) {
129 return reshape(std::forward<A>(a), std::array<long, sizeof...(Ints)>{static_cast<long>(is)...});
130 }
131
133 template <MemoryArray A, std::integral Int, auto newRank>
134 [[deprecated("Please use reshape(arr, shape) instead")]] auto reshaped_view(A &&a, std::array<Int, newRank> const &new_shape) {
135 return reshape(std::forward<A>(a), new_shape);
136 }
137
147 template <MemoryArray A>
148 auto flatten(A &&a) {
149 return reshape(std::forward<A>(a), std::array{a.size()});
150 }
151
163 template <uint64_t Permutation, MemoryArray A>
165 return map_layout_transform(std::forward<A>(a), a.indexmap().template transpose<Permutation>());
166 }
167
179 template <typename A>
180 auto transpose(A &&a)
182 {
183 if constexpr (MemoryArray<A>) {
185 } else { // expr_call
186 static_assert(std::tuple_size_v<decltype(a.a)> == 1, "Error in nda::transpose: Cannot transpose expr_call with more than one array argument");
187 return map(a.f)(transpose(std::get<0>(std::forward<A>(a).a)));
188 }
189 }
190
203 template <int I, int J, MemoryArray A>
204 auto transposed_view(A &&a)
206 {
207 return permuted_indices_view<encode(permutations::transposition<get_rank<A>>(I, J))>(std::forward<A>(a));
208 }
209
210 // FIXME : use "magnetic" placeholder
234 template <MemoryArray A, typename... IdxGrps>
235 auto group_indices_view(A &&a, IdxGrps...) {
236 return map_layout_transform(std::forward<A>(a), group_indices_layout(a.indexmap(), IdxGrps{}...));
237 }
238
239 namespace detail {
240
241 // Append N fast dimensions to a given stride order.s
242 template <int N, auto R>
243 constexpr std::array<int, R + N> complete_stride_order_with_fast(std::array<int, R> const &order) {
245 for (int i = 0; i < R; ++i) r[i] = order[i];
246 for (int i = 0; i < N; ++i) r[R + i] = R + i;
247 return r;
248 }
249
250 } // namespace detail
251
260 template <int N, typename A>
263 {
264 auto const &lay = a.indexmap();
265 using lay_t = std::decay_t<decltype(lay)>;
266
267 static constexpr uint64_t new_stride_order_encoded = encode(detail::complete_stride_order_with_fast<N>(lay_t::stride_order));
268 static constexpr uint64_t new_static_extents_encoded = encode(stdutil::join(lay_t::static_extents, stdutil::make_initialized_array<N>(0)));
269 using new_lay_t = idx_map<get_rank<A> + N, new_static_extents_encoded, new_stride_order_encoded, lay_t::layout_prop>;
270
271 auto ones_n = stdutil::make_initialized_array<N>(1l);
272 return map_layout_transform(std::forward<A>(a), new_lay_t{stdutil::join(lay.lengths(), ones_n), stdutil::join(lay.strides(), ones_n)});
273 }
274
276
277} // namespace nda
Provides utility functions for std::array.
A generic view of a multi-dimensional array.
A generic multi-dimensional array.
Layout that specifies how to map multi-dimensional indices to a linear/flat index.
Definition idx_map.hpp:90
Check if a given type satisfies the memory array concept.
Definition concepts.hpp:248
Provides concepts for the nda library.
Provides various convenient aliases and helper functions for nda::basic_array and nda::basic_array_vi...
auto transposed_view(A &&a)
Transpose two indices/dimensions of an nda::basic_array or nda::basic_array_view.
auto reinterpret_add_fast_dims_of_size_one(A &&a)
Add N fast varying dimensions of size 1 to a given nda::basic_array or nda::basic_array_view.
auto permuted_indices_view(A &&a)
Permute the indices/dimensions of an nda::basic_array or nda::basic_array_view.
auto map_layout_transform(A &&a, NewLayoutType const &new_layout)
Transform the memory layout of an nda::basic_array or nda::basic_array_view.
auto flatten(A &&a)
Flatten an nda::basic_array or nda::basic_array_view to a 1-dimensional array/view by reshaping it.
auto transpose(A &&a)
Transpose the memory layout of an nda::MemoryArray or an nda::expr_call.
auto reshape(A &&a, std::array< Int, R > const &new_shape)
Reshape an nda::basic_array or nda::basic_array_view.
auto group_indices_view(A &&a, IdxGrps...)
Create a new nda::basic_array or nda::basic_array_view by grouping indices together of a given array/...
auto reshaped_view(A &&a, std::array< Int, newRank > const &new_shape)
mapped< F > map(F f)
Create a lazy function call expression on arrays/views.
Definition map.hpp:202
constexpr bool is_regular_v
Constexpr variable that is true if type A is a regular array, i.e. an nda::basic_array.
Definition traits.hpp:134
constexpr char get_algebra
Constexpr variable that specifies the algebra of a type.
Definition traits.hpp:115
constexpr int get_rank
Constexpr variable that specifies the rank of an nda::Array or of a contiguous 1-dimensional range.
Definition traits.hpp:125
std::remove_reference_t< decltype(basic_array_view{std::declval< T >()})> get_view_t
Get the type of the nda::basic_array_view that would be obtained by constructing a view from a given ...
constexpr bool is_regular_or_view_v
Constexpr variable that is true if type A is either a regular array or a view.
Definition traits.hpp:152
Provides functions used in nda::group_indices_view.
auto group_indices_layout(idx_map< Rank, StaticExtents, StrideOrder, LayoutProp > const &idxm, IdxGrps...)
Given an nda::idx_map and a partition of its indices, return a new nda::idx_map with the grouped indi...
constexpr std::array< int, N > transposition(int i, int j)
Get the permutation representing a single given transposition.
constexpr uint64_t encode(std::array< int, N > const &a)
Encode a std::array<int, N> in a uint64_t.
constexpr std::array< int, N > reverse_identity()
Get the reverse identity permutation.
constexpr std::array< T, R1+R2 > join(std::array< T, R1 > const &a1, std::array< T, R2 > const &a2)
Make a new std::array by joining two existing std::array objects.
Definition array.hpp:299
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
constexpr std::array< T, R > make_std_array(std::array< U, R > const &a)
Convert a std::array with value type U to a std::array with value type T.
Definition array.hpp:171
constexpr bool is_instantiation_of_v
Constexpr variable that is true if type T is an instantiation of TMPLT (see nda::is_instantiation_of)...
Definition traits.hpp:48
Provides a class that maps multi-dimensional indices to a linear index and vice versa.
Provides definitions of various layout policies.
Provides lazy function calls on arrays/views.
Provides utilities to work with permutations and to compactly encode/decode std::array objects.
Provides type traits for the nda library.