TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
traits.hpp
Go to the documentation of this file.
1// Copyright (c) 2019-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: Thomas Hahn, Olivier Parcollet, Nils Wentzell
16
17/**
18 * @file
19 * @brief Provides type traits for the nda library.
20 */
21
22#pragma once
23
24#include <complex>
25#include <cstdint>
26#include <ranges>
27#include <type_traits>
28#include <utility>
29
30namespace nda {
31
32 /**
33 * @addtogroup utils_type_traits
34 * @{
35 */
36
37 /**
38 * @brief Check if type `T` is of type `TMPLT<...>`.
39 *
40 * @details For example, the following code will compile:
41 *
42 * @code{.cpp}
43 * static_assert(nda::is_instantiation_of<std::complex, std::complex<double>>::value);
44 * static_assert(not nda::is_instantiation_of<std::complex, double>::value);
45 * @endcode
46 *
47 * @tparam TMPLT Template type to check against.
48 * @tparam T Type to check.
49 */
50 template <template <typename...> class TMPLT, typename T>
51 struct is_instantiation_of : std::false_type {};
52
53 // Specialization of nda::is_instantiation_of for when it evaluates to true.
54 template <template <typename...> class TMPLT, typename... U>
55 struct is_instantiation_of<TMPLT, TMPLT<U...>> : std::true_type {};
56
57 /// Constexpr variable that is true if type `T` is an instantiation of `TMPLT` (see nda::is_instantiation_of).
58 template <template <typename...> class TMPLT, typename T>
60
61 /// Constexpr variable that is true if type `T` is contained in the parameter pack `Ts`.
62 template <typename T, typename... Ts>
63 static constexpr bool is_any_of = (std::is_same_v<Ts, T> or ... or false);
64
65 /// Constexpr variable that is always true regardless of the types in `Ts`.
66 template <typename... Ts>
67 static constexpr bool always_true = true;
68
69 /// Constexpr variable that is always false regardless of the types in `Ts` (used to trigger `static_assert`).
70 template <typename... Ts>
71 static constexpr bool always_false = false;
72
73 /// Constexpr variable that is true if type `T` is a std::complex type.
74 template <typename T>
75 inline constexpr bool is_complex_v = is_instantiation_of_v<std::complex, T>;
76
77 /// Constexpr variable that is true if type `S` is a scalar type, i.e. arithmetic or complex.
78 template <typename S>
80
81 /**
82 * @brief Constexpr variable that is true if type `S` is a scalar type (see nda::is_scalar_v) or if a
83 * `std::complex<double>` can be constructed from it.
84 */
85 template <typename S>
86 inline constexpr bool is_scalar_or_convertible_v = is_scalar_v<S> or std::is_constructible_v<std::complex<double>, S>;
87
88 /**
89 * @brief Constexpr variable used to check requirements when initializing an nda::basic_array or nda::basic_array_view
90 * of type `A` with some object/value of type `S`.
91 */
92 template <typename S, typename A>
93 inline constexpr bool is_scalar_for_v =
95
96 /// Constexpr variable that is true if type `T` is a std::complex type or a double type.
97 template <typename T>
98 inline constexpr bool is_double_or_complex_v = is_complex_v<T> or std::is_same_v<double, std::remove_cvref_t<T>>;
99
100 /// Alias for nda::is_double_or_complex_v.
101 template <typename T>
102 inline constexpr bool is_blas_lapack_v = is_double_or_complex_v<T>;
103
104 /** @} */
105
106 /**
107 * @addtogroup av_utils
108 * @{
109 */
110
111 /**
112 * @brief Constexpr variable that specifies the algebra of a type.
113 *
114 * @details The possible values are:
115 * - 'N' = none
116 * - 'A' = array
117 * - 'M' = matrix
118 * - 'V' = vector
119 *
120 * The algebra defines the behavior of objects in certain situations, e.g. matrix multiplication of two matrices
121 * ('M' algebra) vs. element-wise multiplication of two arrays ('A' algebra).
122 *
123 * @tparam A Type to get the algebra of.
124 */
125 template <typename A>
126 inline constexpr char get_algebra = 'N';
127
128 // Specialization of nda::get_algebra for cvref types.
129 template <typename A>
130 requires(!std::is_same_v<A, std::remove_cvref_t<A>>)
131 inline constexpr char get_algebra<A> = get_algebra<std::remove_cvref_t<A>>;
132
133 /// Constexpr variable that specifies the rank of an nda::Array or of a contiguous 1-dimensional range.
134 template <typename A>
135 requires(std::ranges::contiguous_range<A> or requires { std::declval<A const>().shape(); })
136 constexpr int get_rank = []() {
137 if constexpr (std::ranges::contiguous_range<A>)
138 return 1;
139 else
140 return std::tuple_size_v<std::remove_cvref_t<decltype(std::declval<A const>().shape())>>;
141 }();
142
143 /// Constexpr variable that is true if type `A` is a regular array, i.e. an nda::basic_array.
144 template <typename A>
145 inline constexpr bool is_regular_v = false;
146
147 // Specialization of nda::is_regular_v for cvref types.
148 template <typename A>
149 requires(!std::is_same_v<A, std::remove_cvref_t<A>>)
150 inline constexpr bool is_regular_v<A> = is_regular_v<std::remove_cvref_t<A>>;
151
152 /// Constexpr variable that is true if type `A` is a view, i.e. an nda::basic_array_view.
153 template <typename A>
154 inline constexpr bool is_view_v = false;
155
156 // Specialization of nda::is_view_v for cvref types.
157 template <typename A>
158 requires(!std::is_same_v<A, std::remove_cvref_t<A>>)
159 inline constexpr bool is_view_v<A> = is_view_v<std::remove_cvref_t<A>>;
160
161 /// Constexpr variable that is true if type `A` is either a regular array or a view.
162 template <typename A>
163 inline constexpr bool is_regular_or_view_v = is_regular_v<A> or is_view_v<A>;
164
165 /// Constexpr variable that is true if type `A` is a regular matrix or a view of a matrix.
166 template <typename A>
167 inline constexpr bool is_matrix_or_view_v = is_regular_or_view_v<A> and (get_algebra<A> == 'M') and (get_rank<A> == 2);
168
169 /**
170 * @brief Get the first element of an array/view or simply return the scalar if a scalar is given.
171 *
172 * @tparam A Array/View/Scalar type.
173 * @param a Input array/view/scalar.
174 * @return If an array/view is given, return its first element. Otherwise, return the given scalar.
175 */
176 template <typename A>
177 decltype(auto) get_first_element(A const &a) {
178 if constexpr (is_scalar_v<A>) {
179 return a;
180 } else {
181 return [&a]<auto... Is>(std::index_sequence<Is...>) -> decltype(auto) {
182 return a((0 * Is)...); // repeat 0 sizeof...(Is) times
183 }(std::make_index_sequence<get_rank<A>>{});
184 }
185 }
186
187 /**
188 * @brief Get the value type of an array/view or a scalar type.
189 * @tparam A Array/View/Scalar type.
190 */
191 template <typename A>
192 using get_value_t = std::decay_t<decltype(get_first_element(std::declval<A const>()))>;
193
194 /// Constexpr variable that is true if all types in `As` have the same value type as `A0`.
195 template <typename A0, typename... As>
196 inline constexpr bool have_same_value_type_v = (std::is_same_v<get_value_t<A0>, get_value_t<As>> and ... and true);
197
198 /// Constexpr variable that is true if all types in `As` have the same rank as `A0`.
199 template <typename A0, typename... As>
200 inline constexpr bool have_same_rank_v = ((get_rank<A0> == get_rank<As>)and... and true);
201
202 /** @} */
203
204 /**
205 * @addtogroup layout_utils
206 * @{
207 */
208
209 /**
210 * @brief Compile-time guarantees of the memory layout of an array/view.
211 *
212 * @details The possible values are:
213 * - `none`: No guarantees.
214 * - `strided_1d`: There is a constant overall stride in memory.
215 * - `smallest_stride_is_one`: The stride in the fastest dimension is 1.
216 * - `contiguous`: The array/view is contiguous in memory, i.e. it is `strided_1d` and `smallest_stride_is_one`.
217 *
218 * Furthermore, the set of values has a partial order:
219 * - `contiguous` > `strided_1d` > `none`
220 * - `contiguous` > `smallest_stride_is_one` > `none`
221 */
222 enum class layout_prop_e : uint64_t {
223 none = 0x0,
224 strided_1d = 0x1,
225 smallest_stride_is_one = 0x2,
226 contiguous = strided_1d | smallest_stride_is_one
227 };
228
229 /**
230 * @brief Checks if two layout properties are compatible with each other.
231 *
232 * @param from Source nda::layout_prop_e.
233 * @param to Target nda::layout_prop_e.
234 * @return True if the source layout property is greater or equal to the target layout property,
235 * otherwise false (see nda::layout_prop_e).
236 */
238 if (from == layout_prop_e::contiguous) return true;
239 return ((to == layout_prop_e::none) or (to == from));
240 }
241
242 /**
243 * @brief Bitwise OR operator for two layout properties.
244 *
245 * @param lhs Left hand side nda::layout_prop_e operand.
246 * @param rhs Right hand side nda::layout_prop_e operand.
247 * @return The bitwise OR of their numerical binary representation.
248 */
249 constexpr layout_prop_e operator|(layout_prop_e lhs, layout_prop_e rhs) { return layout_prop_e(uint64_t(lhs) | uint64_t(rhs)); }
250
251 /**
252 * @brief Bitwise AND operator for two layout properties.
253 *
254 * @param lhs Left hand side nda::layout_prop_e operand.
255 * @param rhs Right hand side nda::layout_prop_e operand.
256 * @return The bitwise AND of their numerical binary representation.
257 */
258 constexpr layout_prop_e operator&(layout_prop_e lhs, layout_prop_e rhs) { return layout_prop_e{uint64_t(lhs) & uint64_t(rhs)}; }
259
260 /**
261 * @brief Checks if a layout property has the `strided_1d` property.
262 *
263 * @param lp nda::layout_prop_e to check.
264 * @return True if it has the `strided_1d` property, false otherwise.
265 */
266 inline constexpr bool has_strided_1d(layout_prop_e lp) { return uint64_t(lp) & uint64_t(layout_prop_e::strided_1d); }
267
268 /**
269 * @brief Checks if a layout property has the `smallest_stride_is_one` property.
270 *
271 * @param lp nda::layout_prop_e to check.
272 * @return True if it has the `smallest_stride_is_one` property, false otherwise.
273 */
274 inline constexpr bool has_smallest_stride_is_one(layout_prop_e lp) { return uint64_t(lp) & uint64_t(layout_prop_e::smallest_stride_is_one); }
275
276 /**
277 * @brief Checks if a layout property has the `contiguous` property.
278 *
279 * @param lp nda::layout_prop_e to check.
280 * @return True if it has the `contiguous` property, false otherwise.
281 */
282 inline constexpr bool has_contiguous(layout_prop_e lp) { return has_strided_1d(lp) and has_smallest_stride_is_one(lp); }
283
284 // FIXME : I need a NONE for stride_order. For the scalars ...
285 /**
286 * @brief Stores information about the memory layout and the stride order of an array/view.
287 *
288 * @details The stride order of an N-dimensional array/view is a specific permutation of the integers from 0 to N-1,
289 * i.e. `(i1, i2, ..., iN)`, which is encoded in a `uint64_t` (note that this limits the max. number of dimensions to
290 * 16). It specifies the order in which the dimensions are traversed with `i1` being the slowest and `iN` the fastest.
291 *
292 * For example, a 3D array/view with C-order has a stride order of `(0, 1, 2)`, while the Fortran-order would be
293 * `(2, 1, 0)`.
294 */
296 /// Stride order of the array/view.
297 uint64_t stride_order = 0;
298
299 /// Memory layout properties of the array/view.
301 };
302
303 /**
304 * @brief Bitwise AND operator for layout infos.
305 *
306 * @param lhs Left hand side nda::layout_info_t operand.
307 * @param rhs Right hand side nda::layout_info_t operand.
308 * @return A new nda::layout_info_t with the same stride order as the two arguments and their compatible
309 * nda::layout_prop_e. If the stride orders are different, the stride order is set to -1 (undefined, no
310 * permutation) and no memory layout guarantee can be made.
311 */
313 if (lhs.stride_order == rhs.stride_order)
314 return layout_info_t{lhs.stride_order, layout_prop_e(uint64_t(lhs.prop) & uint64_t(rhs.prop))};
315 else
316 return layout_info_t{uint64_t(-1), layout_prop_e::none};
317 }
318
319 /// Constexpr variable that specifies the nda::layout_info_t of type `A`.
320 template <typename A>
322
323 // Specialization of nda::get_layout_info for cvref types.
324 template <typename A>
325 requires(!std::is_same_v<A, std::remove_cvref_t<A>>)
326 inline constexpr layout_info_t get_layout_info<A> = get_layout_info<std::remove_cvref_t<A>>;
327
328 /// Constexpr variable that is true if type `A` has the `contiguous` nda::layout_prop_e guarantee.
329 template <typename A>
331
332 /// Constexpr variable that is true if type `A` has the `strided_1d` nda::layout_prop_e guarantee.
333 template <typename A>
335
336 /// Constexpr variable that is true if type `A` has the `smallest_stride_is_one` nda::layout_prop_e guarantee.
337 template <typename A>
339
340 /**
341 * @brief A small wrapper around a single long integer to be used as a linear index.
342 */
344 /// Linear index.
345 long value;
346 };
347
348 /** @} */
349
350} // namespace nda
#define CUBLAS_CHECK(X,...)
#define NDA_RUNTIME_ERROR
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:145
constexpr char get_algebra
Constexpr variable that specifies the algebra of a type.
Definition traits.hpp:126
constexpr bool is_matrix_or_view_v
Constexpr variable that is true if type A is a regular matrix or a view of a matrix.
Definition traits.hpp:167
constexpr bool have_same_value_type_v
Constexpr variable that is true if all types in As have the same value type as A0.
Definition traits.hpp:196
constexpr int get_rank
Constexpr variable that specifies the rank of an nda::Array or of a contiguous 1-dimensional range.
Definition traits.hpp:136
constexpr bool have_same_rank_v
Constexpr variable that is true if all types in As have the same rank as A0.
Definition traits.hpp:200
constexpr bool is_view_v
Constexpr variable that is true if type A is a view, i.e. an nda::basic_array_view.
Definition traits.hpp:154
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:163
decltype(auto) get_first_element(A const &a)
Get the first element of an array/view or simply return the scalar if a scalar is given.
Definition traits.hpp:177
constexpr bool layout_property_compatible(layout_prop_e from, layout_prop_e to)
Checks if two layout properties are compatible with each other.
Definition traits.hpp:237
constexpr bool has_contiguous(layout_prop_e lp)
Checks if a layout property has the contiguous property.
Definition traits.hpp:282
constexpr bool has_layout_smallest_stride_is_one
Constexpr variable that is true if type A has the smallest_stride_is_one nda::layout_prop_e guarantee...
Definition traits.hpp:338
constexpr bool has_strided_1d(layout_prop_e lp)
Checks if a layout property has the strided_1d property.
Definition traits.hpp:266
constexpr bool has_layout_strided_1d
Constexpr variable that is true if type A has the strided_1d nda::layout_prop_e guarantee.
Definition traits.hpp:334
constexpr layout_prop_e operator&(layout_prop_e lhs, layout_prop_e rhs)
Bitwise AND operator for two layout properties.
Definition traits.hpp:258
constexpr layout_info_t operator&(layout_info_t lhs, layout_info_t rhs)
Bitwise AND operator for layout infos.
Definition traits.hpp:312
constexpr layout_prop_e operator|(layout_prop_e lhs, layout_prop_e rhs)
Bitwise OR operator for two layout properties.
Definition traits.hpp:249
constexpr layout_info_t get_layout_info
Constexpr variable that specifies the nda::layout_info_t of type A.
Definition traits.hpp:321
constexpr bool has_smallest_stride_is_one(layout_prop_e lp)
Checks if a layout property has the smallest_stride_is_one property.
Definition traits.hpp:274
constexpr bool has_contiguous_layout
Constexpr variable that is true if type A has the contiguous nda::layout_prop_e guarantee.
Definition traits.hpp:330
layout_prop_e
Compile-time guarantees of the memory layout of an array/view.
Definition traits.hpp:222
int get_ld(A const &a)
Get the leading dimension in LAPACK jargon of an nda::MemoryMatrix.
Definition tools.hpp:109
static constexpr bool has_C_layout
Constexpr variable that is true if the given nda::Array type has a C memory layout.
Definition tools.hpp:76
static constexpr bool is_conj_array_expr
Constexpr variable that is true if the given type is a conjugate lazy expression.
Definition tools.hpp:52
int get_ncols(A const &a)
Get the number of columns in LAPACK jargon of an nda::MemoryMatrix.
Definition tools.hpp:121
static constexpr bool is_conj_array_expr< expr_call< conj_f, A > >
Specialization of nda::blas::is_conj_array_expr for the conjugate lazy expressions.
Definition tools.hpp:56
static constexpr bool has_F_layout
Constexpr variable that is true if the given nda::Array type has a Fortran memory layout.
Definition tools.hpp:66
const char get_op
Variable template that determines the BLAS matrix operation tag ('N','T','C') based on the given bool...
Definition tools.hpp:91
AddressSpace
Enum providing identifiers for the different memory address spaces.
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:59
constexpr bool is_complex_v
Constexpr variable that is true if type T is a std::complex type.
Definition traits.hpp:75
constexpr bool is_blas_lapack_v
Alias for nda::is_double_or_complex_v.
Definition traits.hpp:102
static constexpr bool always_false
Constexpr variable that is always false regardless of the types in Ts (used to trigger static_assert)...
Definition traits.hpp:71
constexpr bool is_scalar_for_v
Constexpr variable used to check requirements when initializing an nda::basic_array or nda::basic_arr...
Definition traits.hpp:93
static constexpr bool is_any_of
Constexpr variable that is true if type T is contained in the parameter pack Ts.
Definition traits.hpp:63
constexpr bool is_double_or_complex_v
Constexpr variable that is true if type T is a std::complex type or a double type.
Definition traits.hpp:98
static constexpr bool always_true
Constexpr variable that is always true regardless of the types in Ts.
Definition traits.hpp:67
constexpr bool is_scalar_v
Constexpr variable that is true if type S is a scalar type, i.e. arithmetic or complex.
Definition traits.hpp:79
constexpr bool is_scalar_or_convertible_v
Constexpr variable that is true if type S is a scalar type (see nda::is_scalar_v) or if a std::comple...
Definition traits.hpp:86
#define AS_STRING(...)
Definition macros.hpp:31
A small wrapper around a single long integer to be used as a linear index.
Definition traits.hpp:343
long value
Linear index.
Definition traits.hpp:345
Check if type T is of type TMPLT<...>.
Definition traits.hpp:51
Stores information about the memory layout and the stride order of an array/view.
Definition traits.hpp:295
uint64_t stride_order
Stride order of the array/view.
Definition traits.hpp:297
layout_prop_e prop
Memory layout properties of the array/view.
Definition traits.hpp:300
Memory block consisting of a pointer and its size.