TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
rect_str.hpp
Go to the documentation of this file.
1// Copyright (c) 2020-2023 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Olivier Parcollet, Nils Wentzell
16
22#pragma once
23
24#include "./idx_map.hpp"
25#include "./policies.hpp"
26#include "../basic_array.hpp"
28#include "../declarations.hpp"
29#include "../exceptions.hpp"
30#include "../traits.hpp"
31
32#include <array>
33#include <cstdint>
34#include <memory>
35#include <string>
36#include <type_traits>
37#include <utility>
38
39namespace nda {
40
47 // Forward declaration.
48 template <int Rank, uint64_t StaticExtents, uint64_t StrideOrder, layout_prop_e LayoutProp>
49 class rect_str;
51
52 namespace detail {
53
54 // Get the corresponding nda::rect_str type from a given nda::idx_map type.
55 template <typename T>
56 struct rect_str_from_base;
57
58 // Specialization of rect_str_from_base for nda::idx_map.
59 template <int Rank, uint64_t StaticExtents, uint64_t StrideOrder, layout_prop_e LayoutProp>
60 struct rect_str_from_base<idx_map<Rank, StaticExtents, StrideOrder, LayoutProp>> {
61 // nda::rect_str type.
62 using type = rect_str<Rank, StaticExtents, StrideOrder, LayoutProp>;
63 };
64
65 } // namespace detail
66
78 template <int Rank, uint64_t StaticExtents, uint64_t StrideOrder, layout_prop_e LayoutProp>
79 class rect_str : public idx_map<Rank, StaticExtents, StrideOrder, LayoutProp> {
80 // Type for storing the string indices.
82
83 // Type of the nda::idx_map base class.
85
86 // String indices for each dimension.
87 mutable std::shared_ptr<ind_t const> s_indices;
88
89 // Number of dynamic dimensions/extents.
91
92 // Get the shape of the nda::rect_str from given string indices.
93 static std::array<long, Rank> make_shape_from_string_indices(ind_t const &str_indices) {
94 if (str_indices.size() != Rank)
95 NDA_RUNTIME_ERROR << "Error in rect_str::make_shape_from_string_indices: String indices do not have the correct rank";
96 std::array<long, Rank> sha;
97 for (int i = 0; i < Rank; ++i) sha[i] = str_indices[i].size();
98 return sha;
99 }
100
101 public:
110 auto const &get_string_indices() const {
111 if (not s_indices) {
112 // string indices are not initialized
113 auto ind = ind_t(Rank);
114 for (int i = 0; i < Rank; ++i) {
115 auto a = nda::array<std::string, 1>(this->lengths()[i]);
116 for (int j = 0; j < a.size(); ++j) a(j) = std::to_string(j);
117 ind(i) = std::move(a);
118 }
119 s_indices = std::make_shared<ind_t>(std::move(ind));
120 }
121 return *s_indices;
122 }
123
125 template <typename T>
126 static constexpr int argument_is_allowed_for_call = base_t::template argument_is_allowed_for_call<T> or std::is_constructible_v<std::string, T>;
127
129 template <typename T>
131 base_t::template argument_is_allowed_for_call_or_slice<T> or std::is_constructible_v<std::string, T>;
132
137 rect_str() = default;
138
143 rect_str(base_t const &idxm) noexcept : base_t{idxm} {}
144
153 rect_str(base_t const &idxm, ind_t const &str_indices) noexcept : base_t{idxm}, s_indices{std::make_shared<ind_t>(std::move(str_indices))} {}
154
161 template <layout_prop_e LP>
163 : base_t{rstr}, s_indices{std::make_shared<ind_t>(rstr.get_string_indices())} {}
164
172 template <uint64_t SE, layout_prop_e LP>
174 : base_t{rstr}, s_indices{std::make_shared<ind_t>(rstr.get_string_indices())} {}
175
182 rect_str(std::array<long, Rank> const &shape, std::array<long, Rank> const &strides) noexcept : base_t{shape, strides} {}
183
188 rect_str(std::array<long, Rank> const &shape) noexcept : base_t{shape} {}
189
194 rect_str(nda::array<nda::array<std::string, 1>, 1> str_indices) noexcept(false)
195 : base_t{make_shape_from_string_indices(str_indices)}, s_indices{std::make_shared<ind_t>(std::move(str_indices))} {}
196
202 rect_str(std::array<long, base_t::n_dynamic_extents> const &shape) noexcept
203 requires((base_t::n_dynamic_extents != Rank) and (base_t::n_dynamic_extents != 0))
204 : base_t{shape} {}
205
207 rect_str(rect_str const &) = default;
208
210 rect_str(rect_str &&) = default;
211
213 rect_str &operator=(rect_str const &) = default;
214
217
218 private:
219 // Convert a given string argument into a corresponding index. If the argument isn't a string, it is returned as is.
220 template <typename T>
221 auto peel_string(int pos, T const &arg) const {
222 if constexpr (not std::is_constructible_v<std::string, T>)
223 // argument is not a string, simply return it
224 return arg;
225 else {
226 // argument is a string, find its position in the string indices of the given dimension
227 auto const &sind = get_string_indices();
228 auto const &idx = sind[pos];
229 auto it = std::find(idx.begin(), idx.end(), arg);
230 if (it == idx.end()) NDA_RUNTIME_ERROR << "Error in nda::rect_str: Key " << arg << " at position " << pos << " does not match an index";
231 return it - idx.begin();
232 }
233 }
234
235 // Actual implementation of the function call operator.
236 template <typename... Args, size_t... Is>
237 [[nodiscard]] FORCEINLINE long call_impl(std::index_sequence<Is...>, Args... args) const {
238 // calls the underlying nda::idx_map::operator() after converting all string arguments to long indices
239 return base_t::operator()(peel_string(Is, args)...);
240 }
241
242 public:
252 template <typename... Args>
253 FORCEINLINE long operator()(Args const &...args) const {
254 return call_impl(std::make_index_sequence<sizeof...(Args)>{}, args...);
255 }
256
257 private:
258 // Helper function to get a new nda::rect_str by taking a slice of the current one.
259 template <typename... Args, auto... Is>
260 FORCEINLINE decltype(auto) slice_impl(std::index_sequence<Is...>, Args const &...args) const {
261 // convert string arguments to long indices and slice the underlying nda::idx_map
262 auto const [offset, idxm2] = base_t::slice(peel_string(Is, args)...);
263
264 // type of sliced nda::rect_str
265 using new_rect_str_t = typename detail::rect_str_from_base<std::decay_t<decltype(idxm2)>>::type;
266
267 // if the string indices have not been initialized, simply return a new nda::rect_str with the sliced nda::idx_map
268 if (not s_indices) return std::make_pair(offset, new_rect_str_t{idxm2});
269
270 // otherwise slice the string indices as well (not optimized but simple)
271 auto const &current_ind = get_string_indices();
272 ind_t ind2((not argument_is_allowed_for_call<Args> + ...)); // will not work for ellipsis that cover more than one dimension
273 auto add_string_indices = [p = 0, &current_ind, &ind2](int n, auto const &y) mutable -> void {
274 using U = std::decay_t<decltype(y)>;
275 if constexpr (not argument_is_allowed_for_call<U>) { ind2[p++] = current_ind[n](y); }
276 };
277 (add_string_indices(Is, args), ...);
278
279 return std::make_pair(offset, new_rect_str_t{idxm2, ind2});
280 }
281
282 public:
294 template <typename... Args>
295 auto slice(Args const &...args) const {
296 return slice_impl(std::make_index_sequence<sizeof...(args)>{}, args...);
297 }
298
305 bool operator==(rect_str const &rhs) const {
306 return base_t::operator==(rhs) and (!s_indices or !rhs.s_indices or (*s_indices == *(rhs.s_indices)));
307 }
308
315 bool operator!=(rect_str const &rhs) { return !(operator==(rhs)); }
316
331 template <uint64_t Permutation>
332 auto transpose() const {
333 // transpose the underlying nda::idx_map
334 auto idxm2 = base_t::template transpose<Permutation>();
335
336 // type of transposed nda::rect_str
337 using new_rect_str_t = typename detail::rect_str_from_base<std::decay_t<decltype(idxm2)>>::type;
338
339 // if the string indices have not been initialized, simply return the transposed nda::rect_str
340 if (not s_indices) return new_rect_str_t{idxm2};
341
342 // otherwise transpose the string indices as well
343 ind_t ind2(s_indices->size());
344 static constexpr std::array<int, Rank> permu = decode<Rank>(Permutation);
345 for (int u = 0; u < Rank; ++u) { ind2[permu[u]] = (*s_indices)[u]; }
346 return new_rect_str_t{idxm2, ind2};
347 }
348 };
349
358 // Forward declarations.
359 struct C_stride_layout_str;
360 struct F_stride_layout_str;
362
369 template <int Rank>
370 using mapping = rect_str<Rank, 0, C_stride_order<Rank>, layout_prop_e::contiguous>;
371
374
377 };
378
385 template <int Rank>
386 using mapping = rect_str<Rank, 0, Fortran_stride_order<Rank>, layout_prop_e::contiguous>;
387
390
393 };
394
401 template <int Rank>
402 using mapping = rect_str<Rank, 0, C_stride_order<Rank>, layout_prop_e::none>;
403
406
409 };
410
417 template <int Rank>
419
422
425 };
426
434 template <uint64_t StaticExtents, uint64_t StrideOrder, layout_prop_e LayoutProp>
447
448 namespace detail {
449
450 // Get the correct layout policy given a general nda::rect_str.
451 template <int Rank, uint64_t StaticExtents, uint64_t StrideOrder, layout_prop_e LayoutProp>
452 struct layout_to_policy<rect_str<Rank, StaticExtents, StrideOrder, LayoutProp>> {
454 };
455
456 // Get the correct layout policy given a general nda::rect_str.
457 template <int Rank>
458 struct layout_to_policy<rect_str<Rank, 0, C_stride_order<Rank>, layout_prop_e::contiguous>> {
459 using type = C_layout_str;
460 };
461
462 // Get the correct layout policy given a strided nda::rect_str with C-order.
463 template <int Rank>
464 struct layout_to_policy<rect_str<Rank, 0, C_stride_order<Rank>, layout_prop_e::none>> {
465 using type = C_stride_layout_str;
466 };
467
468 } // namespace detail
469
472} // namespace nda
Provides the generic class for arrays.
Provides basic functions to create and manipulate arrays and views.
A generic multi-dimensional array.
long size() const noexcept
Get the total size of the view/array.
Layout that specifies how to map multi-dimensional indices to a linear/flat index.
Definition idx_map.hpp:103
__inline__ long operator()(Args const &...args) const noexcept(true)
Function call operator to map a given multi-dimensional index to a linear index.
Definition idx_map.hpp:512
long size() const noexcept
Get the total number of elements.
Definition idx_map.hpp:160
bool operator==(idx_map< R, SE, SO, LP > const &rhs) const
Equal-to operator for two nda::idx_map objects.
Definition idx_map.hpp:585
static constexpr int n_dynamic_extents
Number of dynamic dimensions/extents.
Definition idx_map.hpp:143
std::array< long, Rank > const & lengths() const noexcept
Get the extents of all dimensions.
Definition idx_map.hpp:178
auto slice(Args const &...args) const
Get a new nda::idx_map by taking a slice of the current one.
Definition idx_map.hpp:570
std::array< long, Rank > const & strides() const noexcept
Get the strides of all dimensions.
Definition idx_map.hpp:184
Layout that specifies how to map multi-dimensional indices including possible string indices to a lin...
Definition rect_str.hpp:79
__inline__ long operator()(Args const &...args) const
Function call operator to map a given multi-dimensional index to a linear index.
Definition rect_str.hpp:253
bool operator!=(rect_str const &rhs)
Not-equal-to operator for two nda::rect_str objects.
Definition rect_str.hpp:315
rect_str(std::array< long, Rank > const &shape) noexcept
Construct an nda::rect_str from a given shape and with contiguous strides.
Definition rect_str.hpp:188
rect_str(rect_str< Rank, StaticExtents, StrideOrder, LP > const &rstr) noexcept
Construct an nda::rect_str from another nda::rect_str with different layout properties.
Definition rect_str.hpp:162
rect_str & operator=(rect_str &&)=default
Default move assignment operator.
rect_str(nda::array< nda::array< std::string, 1 >, 1 > str_indices) noexcept(false)
Construct an nda::rect_str from given string indices and with contiguous strides.
Definition rect_str.hpp:194
rect_str(rect_str< Rank, SE, StrideOrder, LP > const &rstr) noexcept(false)
Construct an nda::rect_str from another nda::rect_str with different layout properties and static ext...
Definition rect_str.hpp:173
auto slice(Args const &...args) const
Get a new nda::rect_str by taking a slice of the current one.
Definition rect_str.hpp:295
rect_str & operator=(rect_str const &)=default
Default copy assignment operator.
static constexpr int argument_is_allowed_for_call_or_slice
Alias template to check if type T can be used to either access a specific element or a slice of eleme...
Definition rect_str.hpp:130
static constexpr int argument_is_allowed_for_call
Alias template to check if type T can be used to access a specific element.
Definition rect_str.hpp:126
rect_str(base_t const &idxm) noexcept
Construct an nda::rect_str from a given nda::idx_map.
Definition rect_str.hpp:143
bool operator==(rect_str const &rhs) const
Equal-to operator for two nda::rect_str objects.
Definition rect_str.hpp:305
rect_str(std::array< long, base_t::n_dynamic_extents > const &shape) noexcept
Construct an nda::rect_str from an array with its dynamic extents.
Definition rect_str.hpp:202
rect_str(rect_str const &)=default
Default copy constructor.
rect_str(rect_str &&)=default
Default move constructor.
rect_str(std::array< long, Rank > const &shape, std::array< long, Rank > const &strides) noexcept
Construct an nda::rect_str from a given shape and strides.
Definition rect_str.hpp:182
rect_str()=default
Default constructor.
auto const & get_string_indices() const
Get the string indices.
Definition rect_str.hpp:110
auto transpose() const
Create a new nda::rect_str by permuting the indices/dimensions with a given permutation.
Definition rect_str.hpp:332
rect_str(base_t const &idxm, ind_t const &str_indices) noexcept
Construct an nda::rect_str from a given nda::idx_map and string indices.
Definition rect_str.hpp:153
Provides various convenient aliases and helper functions for nda::basic_array and nda::basic_array_vi...
Provides a custom runtime error class and macros to assert conditions and throw exceptions.
basic_array< ValueType, Rank, Layout, 'A', ContainerPolicy > array
Alias template of an nda::basic_array with an 'A' algebra.
constexpr uint64_t C_stride_order
C/Row-major stride order.
Definition idx_map.hpp:65
layout_prop_e
Compile-time guarantees of the memory layout of an array/view.
Definition traits.hpp:222
constexpr std::array< int, N > decode(uint64_t binary_representation)
Decode a uint64_t into a std::array<int, N>.
std::string to_string(std::array< T, R > const &a)
Get a string representation of a std::array.
Definition array.hpp:65
Provides a class that maps multi-dimensional indices to a linear index and vice versa.
Provides definitions of various layout policies.
Contiguous layout policy with C-order (row-major order) and possible string indices.
Definition rect_str.hpp:367
Strided (non-contiguous) layout policy with C-order (row-major order) and possible string indices.
Definition rect_str.hpp:399
Contiguous layout policy with Fortran-order (column-major order) and possible string indices.
Definition rect_str.hpp:383
Strided (non-contiguous) layout policy with Fortran-order (column-major order) and possible string in...
Definition rect_str.hpp:415
Generic layout policy with arbitrary order and possible string indices.
Definition rect_str.hpp:435
Provides type traits for the nda library.