18
19
20
24#include "./stdutil/concepts.hpp"
25#include "./traits.hpp"
35
36
37
44
45
46
47
48
49
50
51
52 template <
typename A,
int R>
53 concept CallableWithLongs =
requires(A
const &a) {
55 []<
auto... Is>(std::index_sequence<Is...>,
auto const &aa) ->
decltype(aa(
long(Is)...)) {
return aa(
long(Is)...);}
56 (std::make_index_sequence<R>{}, a);
65 template <
auto... Is,
typename A>
66 auto call_on_R_longs(std::index_sequence<Is...>, A
const &a) ->
decltype(a((
long{Is})...));
71
72
73
74
75
76
77
78
79 template <
typename A,
int R>
80 concept CallableWithLongs =
requires(A
const &a) {
81 { detail::call_on_R_longs(std::make_index_sequence<R>{}, a) };
90 constexpr bool is_std_array_of_long_v =
false;
94 requires(!std::is_same_v<T, std::remove_cvref_t<T>>)
95 constexpr bool is_std_array_of_long_v<T> = is_std_array_of_long_v<std::remove_cvref_t<T>>;
99 constexpr bool is_std_array_of_long_v<std::array<
long, R>> =
true;
104
105
106
107
108
109
110
112 concept StdArrayOfLong = detail::is_std_array_of_long_v<T>;
115
116
117
118 template <
typename S>
119 concept Scalar = nda::is_scalar_v<S>;
122
123
124
125 template <
typename S>
126 concept DoubleOrComplex = nda::is_double_or_complex_v<S>;
129
130
131
132
133
134
135
136 template <
typename T,
template <
typename...>
class TMPLT>
137 concept InstantiationOf = nda::is_instantiation_of_v<TMPLT, T>;
144
145
146
155
156
157
158
159
160
161
162
163
164
165 template <
typename A>
166 concept Allocator =
requires(A &a) {
167 { a.allocate(size_t{}) }
noexcept -> std::same_as<
blk_t>;
168 { a.allocate_zero(size_t{}) }
noexcept -> std::same_as<
blk_t>;
169 { a.deallocate(std::declval<
blk_t>()) }
noexcept;
170 { A::address_space } -> std::same_as<
AddressSpace const &>;
174
175
176
177
178
179
180
181
182
183 template <
typename H,
typename T =
typename std::remove_cvref_t<H>::value_type>
184 concept Handle =
requires(H
const &h) {
185 requires std::is_same_v<
typename std::remove_cvref_t<H>::value_type, T>;
186 { h.is_null() }
noexcept -> std::same_as<
bool>;
187 { h.data() }
noexcept -> std::same_as<T *>;
188 { H::address_space } -> std::same_as<
AddressSpace const &>;
192
193
194
195
196
197
198
199
200 template <
typename H,
typename T =
typename std::remove_cvref_t<H>::value_type>
201 concept OwningHandle = Handle<H, T>
and requires(H
const &h) {
202 requires not std::is_const_v<
typename std::remove_cvref_t<H>::value_type>;
203 { h.size() }
noexcept -> std::same_as<
long>;
211
212
213
216
217
218
219
220
221
222
223
224
225
226
227
228
229 template <
typename A>
230 concept Array =
requires(A
const &a) {
231 { a.shape() } -> StdArrayOfLong;
232 { a.size() } -> std::same_as<
long>;
233 requires CallableWithLongs<A, get_rank<A>>;
237
238
239
240
241
242
243
244
245
246
247 template <
typename A,
typename A_t = std::remove_cvref_t<A>>
248 concept MemoryArray = Array<A> &&
requires(A &a) {
249 typename A_t::storage_t;
250 requires mem::Handle<
typename A_t::storage_t>;
251 typename A_t::value_type;
254 } -> std::same_as<std::conditional_t<std::is_const_v<std::remove_reference_t<A>> || std::is_const_v<
typename A_t::value_type>,
255 const get_value_t<A>, get_value_t<A>> *>;
256 { a.indexmap().strides() } -> StdArrayOfLong;
260
261
262
263
264
265 template <
typename A,
int R>
266 concept ArrayOfRank = Array<A>
and (get_rank<A> == R);
269
270
271
272
273
274 template <
typename A,
int R>
275 concept MemoryArrayOfRank = MemoryArray<A>
and (get_rank<A> == R);
278
279
280
281 template <
typename AS>
282 concept ArrayOrScalar = Array<AS>
or Scalar<AS>;
285
286
287
288
289 template <
typename M>
290 concept Matrix = ArrayOfRank<M, 2>;
293
294
295
296
297 template <
typename V>
298 concept Vector = ArrayOfRank<V, 1>;
301
302
303
304
305 template <
typename M>
306 concept MemoryMatrix = MemoryArrayOfRank<M, 2>;
309
310
311
312
313 template <
typename V>
314 concept MemoryVector = MemoryArrayOfRank<V, 1>;
317
318
319
320
321
322
323
324 template <
typename A,
typename B>
325 concept ArrayInitializer =
requires(A
const &a) {
326 { a.shape() } -> StdArrayOfLong;
327 typename std::remove_cvref_t<A>::value_type;
328 requires MemoryArray<B> &&
requires(B &b) { a.invoke(b); };
333
334
335
336
337
338 template <
typename A,
typename U>
339 concept HasValueTypeConstructibleFrom = Array<A>
and (std::is_constructible_v<U, get_value_t<A>>);
#define CUBLAS_CHECK(X,...)
#define NDA_RUNTIME_ERROR
int get_ld(A const &a)
Get the leading dimension in LAPACK jargon of an nda::MemoryMatrix.
static constexpr bool has_C_layout
Constexpr variable that is true if the given nda::Array type has a C memory layout.
static constexpr bool is_conj_array_expr
Constexpr variable that is true if the given type is a conjugate lazy expression.
int get_ncols(A const &a)
Get the number of columns in LAPACK jargon of an nda::MemoryMatrix.
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.
static constexpr bool has_F_layout
Constexpr variable that is true if the given nda::Array type has a Fortran memory layout.
const char get_op
Variable template that determines the BLAS matrix operation tag ('N','T','C') based on the given bool...
AddressSpace
Enum providing identifiers for the different memory address spaces.
Memory block consisting of a pointer and its size.