TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
basic_functions.hpp
Go to the documentation of this file.
1// Copyright (c) 2019-2024 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: Dominik Kiese, Miguel Morales, Olivier Parcollet, Nils Wentzell
16
17/**
18 * @file
19 * @brief Provides basic functions to create and manipulate arrays and views.
20 */
21
22#pragma once
23
24#include "./clef/clef.hpp"
25#include "./declarations.hpp"
26#include "./exceptions.hpp"
27#include "./layout/for_each.hpp"
28#include "./mem/address_space.hpp"
29#include "./traits.hpp"
30
31#include <itertools/itertools.hpp>
32
33#include <array>
34#include <concepts>
35#include <optional>
36#include <random>
37#include <tuple>
38#include <type_traits>
39#include <utility>
40
41namespace nda {
42
43 /**
44 * @addtogroup av_factories
45 * @{
46 */
47
48 /**
49 * @brief Make an array of the given shape on the given address space and zero-initialize it.
50 *
51 * @details For a more specific array type consider using nda::basic_array::zeros.
52 *
53 * @tparam T Value type of the array.
54 * @tparam AdrSp Address space of the array.
55 * @tparam Int Integer type.
56 * @tparam Rank Rank of the array.
57 * @param shape Shape of the array.
58 * @return Zero-initialized nda::array or nda::cuarray or scalar if `Rank == 0`.
59 */
60 template <typename T, mem::AddressSpace AdrSp = mem::Host, std::integral Int, auto Rank>
61 auto zeros(std::array<Int, Rank> const &shape) {
62 static_assert(AdrSp != mem::None);
63 if constexpr (Rank == 0)
64 return T{};
65 else if constexpr (AdrSp == mem::Host)
66 return array<T, Rank>::zeros(shape);
67 else
68 return cuarray<T, Rank>::zeros(shape);
69 }
70
71 /**
72 * @brief Make an array of the given shape on the given address space and zero-initialize it.
73 *
74 * @details For a more specific array type consider using nda::basic_array::zeros.
75 *
76 * @tparam T Value type of the array.
77 * @tparam AdrSp Address space of the array.
78 * @tparam Ints Integer types.
79 * @param is Extent (number of elements) along each dimension.
80 * @return Zero-initialized nda::array or nda::cuarray or scalar if no arguments are given.
81 */
82 template <typename T, mem::AddressSpace AdrSp = mem::Host, std::integral... Ints>
83 auto zeros(Ints... is) {
84 return zeros<T, AdrSp>(std::array<long, sizeof...(Ints)>{static_cast<long>(is)...});
85 }
86
87 /**
88 * @brief Make an array of the given shape and one-initialize it.
89 *
90 * @details For a more specific array type consider using nda::basic_array::ones.
91 *
92 * @tparam T Value type of the array.
93 * @tparam Int Integer type.
94 * @tparam Rank Rank of the array.
95 * @param shape Shape of the array.
96 * @return One-initialized nda::array or scalar if `Rank == 0`.
97 */
98 template <typename T, std::integral Int, auto Rank>
99 auto ones(std::array<Int, Rank> const &shape)
100 requires(nda::is_scalar_v<T>)
101 {
102 if constexpr (Rank == 0)
103 return T{1};
104 else { return array<T, Rank>::ones(shape); }
105 }
106
107 /**
108 * @brief Make an array with the given dimensions and one-initialize it.
109 *
110 * @details For a more specific array type consider using nda::basic_array::ones.
111 *
112 * @tparam T Value type of the array.
113 * @tparam Ints Integer types.
114 * @param is Extent (number of elements) along each dimension.
115 * @return One-initialized nda::array or scalar if no arguments are given.
116 */
117 template <typename T, std::integral... Ints>
118 auto ones(Ints... is) {
119 return ones<T>(std::array<long, sizeof...(Ints)>{is...});
120 }
121
122 /**
123 * @brief Make a 1-dimensional integer array and initialize it with values of a given `nda::range`.
124 *
125 * @tparam Int Integer type/Value type of the created array.
126 * @param first First value of the range.
127 * @param last Last value of the range (excluded).
128 * @param step Step size of the range.
129 * @return 1-dimensional integer nda::array.
130 */
131 template <std::integral Int = long>
132 auto arange(long first, long last, long step = 1) {
133 auto r = range(first, last, step);
134 auto a = array<Int, 1>(r.size());
135 for (auto [x, v] : itertools::zip(a, r)) x = v;
136 return a;
137 }
138
139 /**
140 * @brief Make a 1-dimensional integer array and initialize it with values of a given `nda::range` with a step size
141 * of 1 and a starting value of 0.
142 *
143 * @tparam Int Integer type/Value type of the created array.
144 * @param last Last value of the range (excluded).
145 * @return 1-dimensional integer nda::array.
146 */
147 template <std::integral Int = long>
148 auto arange(long last) {
149 return arange<Int>(0, last);
150 }
151
152 /**
153 * @brief Make an array of the given shape and initialize it with random values from the uniform distribution over
154 * [0, 1).
155 *
156 * @details For a more specific array type consider using nda::basic_array::rand.
157 *
158 * @tparam RealType Value type of the array.
159 * @tparam Int Integer type.
160 * @tparam Rank Rank of the array.
161 * @param shape Shape of the array.
162 * @return Random-initialized nda::array or scalar if `Rank == 0`.
163 */
164 template <typename RealType = double, std::integral Int, auto Rank>
165 auto rand(std::array<Int, Rank> const &shape)
166 requires(std::is_floating_point_v<RealType>)
167 {
168 if constexpr (Rank == 0) {
169 auto static gen = std::mt19937{};
170 auto static dist = std::uniform_real_distribution<>{0.0, 1.0};
171 return dist(gen);
172 } else {
173 return array<RealType, Rank>::rand(shape);
174 }
175 }
176
177 /**
178 * @brief Make an array of the given dimensions and initialize it with random values from the uniform distribution
179 * over [0, 1).
180 *
181 * @details For a more specific array type consider using nda::basic_array::rand.
182 *
183 * @tparam RealType Value type of the array.
184 * @tparam Ints Integer types.
185 * @param is Extent (number of elements) along each dimension.
186 * @return Random-initialized nda::array or scalar if no arguments are given.
187 */
188 template <typename RealType = double, std::integral... Ints>
189 auto rand(Ints... is) {
190 return rand<RealType>(std::array<long, sizeof...(Ints)>{is...});
191 }
192
193 /**
194 * @ingroup av_utils
195 * @brief Get the extent of the first dimension of the array.
196 *
197 * @details Equivalent to `a.extent(0)` and `a.shape()[0]`.
198 *
199 * @tparam A nda::Array type.
200 * @param a nda::Array object.
201 * @return Extent of the first dimension.
202 */
203 template <Array A>
204 long first_dim(A const &a) {
205 return a.extent(0);
206 }
207
208 /**
209 * @ingroup av_utils
210 * @brief Get the extent of the second dimension of the array.
211 *
212 * @details Equivalent to `a.extent(1)` and `a.shape()[1]`.
213 *
214 * @tparam A nda::Array type.
215 * @param a nda::Array object.
216 * @return Extent of the second dimension.
217 */
218 template <Array A>
219 long second_dim(A const &a) {
220 return a.extent(1);
221 }
222
223 /**
224 * @brief Make a given object regular.
225 *
226 * @details The return type of this function depends on the input type `A`:
227 * - If `A` is an nda::Array and not regular, then the return type is nda::basic_array.
228 * - If `A` has a nested type `regular_t` which is not the same as `A`, then the return type is `A::regular_t`.
229 * - Otherwise, the input type is simply forwarded.
230 *
231 * @note Rvalue references will be moved, while lvalue references will be copied.
232 *
233 * @tparam A Input type.
234 * @param a Input object to make regular.
235 * @return Regular object.
236 */
237 template <typename A, typename A_t = std::decay_t<A>>
238 decltype(auto) make_regular(A &&a) {
239 if constexpr (Array<A> and not is_regular_v<A>) {
240 return basic_array{std::forward<A>(a)};
241 } else if constexpr (requires { typename A_t::regular_t; }) {
242 if constexpr (not std::is_same_v<A_t, typename A_t::regular_t>)
243 return typename A_t::regular_t{std::forward<A>(a)};
244 else
245 return std::forward<A>(a);
246 } else {
247 return std::forward<A>(a);
248 }
249 }
250
251 /**
252 * @brief Convert an nda::MemoryArray to its regular type on host memory.
253 *
254 * @details If the input object is already on host memory, simply forward the argument (independent of its type).
255 *
256 * @tparam A nda::MemoryArray type.
257 * @param a nda::MemoryArray object.
258 * @return (Regular) object on host memory.
259 */
260 template <MemoryArray A>
261 decltype(auto) to_host(A &&a) {
262 if constexpr (not mem::on_host<A>) {
263 return get_regular_host_t<A>{std::forward<A>(a)};
264 } else {
265 return std::forward<A>(a);
266 }
267 }
268
269 /**
270 * @brief Convert an nda::MemoryArray to its regular type on device memory.
271 *
272 * @details If the input object is already on device memory, simply forward the argument (independent of its type).
273 *
274 * @tparam A nda::MemoryArray type.
275 * @param a nda::MemoryArray object.
276 * @return (Regular) object on device memory.
277 */
278 template <MemoryArray A>
279 decltype(auto) to_device(A &&a) {
280 if constexpr (not mem::on_device<A>) {
281 return get_regular_device_t<A>{std::forward<A>(a)};
282 } else {
283 return std::forward<A>(a);
284 }
285 }
286
287 /**
288 * @brief Convert an nda::MemoryArray to its regular type on unified memory.
289 *
290 * @details If the input object is already on unified memory, simply forward the argument (independent of its type).
291 *
292 * @tparam A nda::MemoryArray type.
293 * @param a nda::MemoryArray object.
294 * @return (Regular) object on unified memory.
295 */
296 template <MemoryArray A>
297 decltype(auto) to_unified(A &&a) {
298 if constexpr (not mem::on_unified<A>) {
299 return get_regular_unified_t<A>{std::forward<A>(a)};
300 } else {
301 return std::forward<A>(a);
302 }
303 }
304
305 /**
306 * @brief Resize a given regular array to the given shape or check if a given view as the correct shape.
307 *
308 * @details Regular types are resized (if necessary) by calling nda::basic_array::resize while views are checked for
309 * the correct shape.
310 *
311 * Throws an exception if the shape of the view does not match the given shape.
312 *
313 * @tparam A Type of the object.
314 * @param a Object to resize or check.
315 * @param sha New shape.
316 */
317 template <typename A>
318 void resize_or_check_if_view(A &a, std::array<long, A::rank> const &sha)
319 requires(is_regular_or_view_v<A>)
320 {
321 if (a.shape() == sha) return;
322 if constexpr (is_regular_v<A>) {
323 a.resize(sha);
324 } else {
325 NDA_RUNTIME_ERROR << "Error in nda::resize_or_check_if_view: Size mismatch: " << a.shape() << " != " << sha;
326 }
327 }
328
329 /**
330 * @brief Make an nda::basic_array_view with a const value type from a given nda::basic_array.
331 *
332 * @tparam T Value type of the array.
333 * @tparam R Rank of the array.
334 * @tparam LP Layout policy of the array.
335 * @tparam A Algebra of the array.
336 * @tparam CP Container policy of the array.
337 *
338 * @param a nda::basic_array object.
339 * @return nda::basic_array_view object with a const value type.
340 */
341 template <typename T, int R, typename LP, char A, typename CP>
342 auto make_const_view(basic_array<T, R, LP, A, CP> const &a) {
343 return basic_array_view<T const, R, LP, A>{a};
344 }
345
346 /**
347 * @brief Make an nda::basic_array_view with a const value type from a given nda::basic_array_view.
348 *
349 * @tparam T Value type of the view.
350 * @tparam R Rank of the view.
351 * @tparam LP Layout policy of the view.
352 * @tparam Algebra Algebra of the view.
353 * @tparam AP Accessor policy of the view.
354 * @tparam OP Owning policy of the view.
355 *
356 * @param a nda::basic_array_view object.
357 * @return nda::basic_array_view object with a const value type.
358 */
359 template <typename T, int R, typename LP, char A, typename AP, typename OP>
360 auto make_const_view(basic_array_view<T, R, LP, A, AP, OP> const &a) {
361 return basic_array_view<T const, R, LP, A, AP, OP>{a};
362 }
363
364 /**
365 * @brief Make an nda::array_view of a given nda::basic_array.
366 *
367 * @tparam T Value type of the array.
368 * @tparam R Rank of the array.
369 * @tparam LP Layout policy of the array.
370 * @tparam A Algebra of the array.
371 * @tparam CP Container policy of the array.
372 *
373 * @param a nda::basic_array object.
374 * @return nda::array_view object.
375 */
376 template <typename T, int R, typename LP, char A, typename CP>
377 auto make_array_view(basic_array<T, R, LP, A, CP> const &a) {
378 return array_view<T, R>{a};
379 }
380
381 /**
382 * @brief Make an nda::array_view of a given nda::basic_array_view.
383 *
384 * @tparam T Value type of the view.
385 * @tparam R Rank of the view.
386 * @tparam LP Layout policy of the view.
387 * @tparam A Algebra of the view.
388 * @tparam AP Accessor policy of the view.
389 * @tparam OP Owning policy of the view.
390 *
391 * @param a nda::basic_array_view object.
392 * @return nda::array_view object.
393 */
394 template <typename T, int R, typename LP, char A, typename AP, typename OP>
395 auto make_array_view(basic_array_view<T, R, LP, A, AP, OP> const &a) {
396 return array_view<T, R>{a};
397 }
398
399 /**
400 * @brief Make an nda::array_const_view of a given nda::basic_array.
401 *
402 * @tparam T Value type of the array.
403 * @tparam R Rank of the array.
404 * @tparam LP Layout policy of the array.
405 * @tparam A Algebra of the array.
406 * @tparam CP Container policy of the array.
407 *
408 * @param a nda::basic_array object.
409 * @return nda::array_const_view object.
410 */
411 template <typename T, int R, typename LP, char A, typename CP>
412 auto make_array_const_view(basic_array<T, R, LP, A, CP> const &a) {
413 return array_const_view<T, R>{a};
414 }
415
416 /**
417 * @brief Make an nda::array_const_view of a given nda::basic_array_view.
418 *
419 * @tparam T Value type of the view.
420 * @tparam R Rank of the view.
421 * @tparam LP Layout policy of the view.
422 * @tparam A Algebra of the view.
423 * @tparam AP Accessor policy of the view.
424 * @tparam OP Owning policy of the view.
425 *
426 * @param a nda::basic_array_view object.
427 * @return nda::array_const_view object.
428 */
429 template <typename T, int R, typename LP, char A, typename AP, typename OP>
430 auto make_array_const_view(basic_array_view<T, R, LP, A, AP, OP> const &a) {
431 return array_const_view<T, R>{a};
432 }
433
434 /**
435 * @brief Make an nda::matrix_view of a given nda::basic_array.
436 *
437 * @tparam T Value type of the array.
438 * @tparam R Rank of the array.
439 * @tparam LP Layout policy of the array.
440 * @tparam A Algebra of the array.
441 * @tparam CP Container policy of the array.
442 *
443 * @param a nda::basic_array object.
444 * @return nda::matrix_view object.
445 */
446 template <typename T, int R, typename LP, char A, typename CP>
447 auto make_matrix_view(basic_array<T, R, LP, A, CP> const &a) {
448 return matrix_view<T, LP>{a};
449 }
450
451 /**
452 * @brief Make an nda::matrix_view of a given nda::basic_array_view.
453 *
454 * @tparam T Value type of the view.
455 * @tparam R Rank of the view.
456 * @tparam LP Layout policy of the view.
457 * @tparam A Algebra of the view.
458 * @tparam AP Accessor policy of the view.
459 * @tparam OP Owning policy of the view.
460 *P
461 * @param a nda::basic_array_view object.
462 * @return nda::matrix_view object.
463 */
464 template <typename T, int R, typename LP, char A, typename AP, typename OP>
465 auto make_matrix_view(basic_array_view<T, R, LP, A, AP, OP> const &a) {
466 return matrix_view<T, LP>{a};
467 }
468
469 /**
470 * @ingroup av_utils
471 * @brief Equal-to comparison operator for two nda::Array objects.
472 *
473 * @tparam LHS nda::Array type of left hand side.
474 * @tparam RHS nda::Array type of right hand side.
475 * @param lhs Left hand side array operand.
476 * @param rhs Right hand side array operand.
477 * @return True if all elements are equal, false otherwise.
478 */
479 template <Array LHS, Array RHS>
480 bool operator==(LHS const &lhs, RHS const &rhs) {
481 // FIXME not implemented in clang
482#ifndef __clang__
483 static_assert(std::equality_comparable_with<get_value_t<LHS>, get_value_t<RHS>>,
484 "Error in nda::operator==: Only defined when elements are comparable");
485#endif
486 if (lhs.shape() != rhs.shape()) return false;
487 bool r = true;
488 nda::for_each(lhs.shape(), [&](auto &&...x) { r &= (lhs(x...) == rhs(x...)); });
489 return r;
490 }
491
492 /**
493 * @ingroup av_utils
494 * @brief Equal-to comparison operator for a 1-dimensional nda::Array and a `std::ranges::contiguous_range`.
495 *
496 * @tparam A nda::Array type of left hand side.
497 * @tparam R `std::ranges::contiguous_range` type of right hand side.
498 * @param a Left hand side array operand.
499 * @param rg Right hand side range operand.
500 * @return True if all elements are equal, false otherwise.
501 */
502 template <ArrayOfRank<1> A, std::ranges::contiguous_range R>
503 bool operator==(A const &a, R const &rg) {
504 return a == basic_array_view{rg};
505 }
506
507 /**
508 * @ingroup av_utils
509 * @brief Equal-to comparison operator for a `std::ranges::contiguous_range` and a 1-dimensional nda::Array.
510 *
511 * @tparam R `std::ranges::contiguous_range` type of left hand side.
512 * @tparam A nda::Array type of right hand side.
513 * @param rg Left hand side range operand.
514 * @param a Right hand side array operand.
515 * @return True if all elements are equal, false otherwise.
516 */
517 template <std::ranges::contiguous_range R, ArrayOfRank<1> A>
518 bool operator==(R const &rg, A const &a) {
519 return a == rg;
520 }
521
522 /**
523 * @ingroup clef_autoassign
524 * @brief Overload of nda::clef::clef_auto_assign function for nda::Array objects.
525 *
526 * @tparam A nda::Array type.
527 * @tparam F Callable type.
528 * @param a nda::Array object.
529 * @param f Callable object.
530 */
531 template <Array A, typename F>
532 void clef_auto_assign(A &&a, F &&f) { // NOLINT (Should we forward the references?)
533 nda::for_each(a.shape(), [&a, &f](auto &&...x) {
534 if constexpr (clef::is_function<std::decay_t<decltype(f(x...))>>) {
535 clef_auto_assign(a(x...), f(x...));
536 } else {
537 a(x...) = f(x...);
538 }
539 });
540 }
541
542 /**
543 * @ingroup layout_utils
544 * @brief Check if a given nda::MemoryArray has a block-strided layout.
545 *
546 * @details If the array is block-strided, return the number of blocks, their size and the stride.
547 *
548 * An array is considered to be block-strided if its data in memory is laid out as contiguous blocks of the same size
549 * (> 1) repeated with a single stride in memory.
550 *
551 * A block-strided array has at most 1 non-contiguous index `m`, i.e. `strides[order[m]] != strides[order[m+1]] *
552 * shape[order[m+1]]`.
553 *
554 * @tparam A nda::MemoryArray type.
555 * @param a Array object.
556 * @return An optional tuple (if block-strided) containing the number of blocks, their size and the stride between
557 * blocks.
558 */
559 template <MemoryArray A>
560 auto get_block_layout(A const &a) {
561 EXPECTS(!a.empty());
562 using opt_t = std::optional<std::tuple<int, int, int>>;
563
564 auto const &shape = a.indexmap().lengths();
565 auto const &strides = a.indexmap().strides();
566 auto const &order = a.indexmap().stride_order;
567
568 int data_size = shape[order[0]] * strides[order[0]];
569 int block_size = data_size;
570 int block_str = data_size;
571 int n_blocks = 1;
572
573 for (auto n : range(A::rank)) {
574 auto inner_size = (n == A::rank - 1) ? 1 : strides[order[n + 1]] * shape[order[n + 1]];
575 if (strides[order[n]] != inner_size) {
576 if (block_size < data_size) // second strided dimension
577 return opt_t{};
578 // found a strided dimension with (assumed) contiguous inner blocks
579 n_blocks = a.size() / inner_size;
580 block_size = inner_size;
581 block_str = strides[order[n]];
582 }
583 }
584 ASSERT(n_blocks * block_size == a.size());
585 ASSERT(n_blocks * block_str == shape[order[0]] * strides[order[0]]);
586 return opt_t{std::make_tuple(n_blocks, block_size, block_str)};
587 }
588
589 /**
590 * @brief Join a sequence of nda::Array types along an existing axis.
591 *
592 * @details The arrays must have the same value type and also shape, except in the dimension corresponding to the
593 * given axis (the first, by default).
594 *
595 * @tparam Axis The axis (dimension) along which to concatenate (default: 0).
596 * @tparam A0 nda::Array type.
597 * @tparam As nda::Array types.
598 * @param a0 First array object.
599 * @param as Remaining array objects.
600 * @return New nda::array with the concatenated data.
601 */
602 template <size_t Axis = 0, Array A0, Array... As>
603 auto concatenate(A0 const &a0, As const &...as) {
604 // sanity checks
605 auto constexpr rank = A0::rank;
606 static_assert(Axis < rank);
607 static_assert(have_same_rank_v<A0, As...>);
608 static_assert(have_same_value_type_v<A0, As...>);
609 for (auto ax [[maybe_unused]] : range(rank)) { EXPECTS(ax == Axis or ((a0.extent(ax) == as.extent(ax)) and ... and true)); }
610
611 // construct concatenated array
612 auto new_shape = a0.shape();
613 new_shape[Axis] = (as.extent(Axis) + ... + new_shape[Axis]);
614 auto new_array = array<get_value_t<A0>, rank>(new_shape);
615
616 // slicing helper function
617 auto slice_Axis = [](Array auto &a, range r) {
618 auto all_or_range = std::make_tuple(range::all, r);
619 return [&]<auto... Is>(std::index_sequence<Is...>) { return a(std::get<Is == Axis>(all_or_range)...); }(std::make_index_sequence<rank>{});
620 };
621
622 // initialize concatenated array
623 long offset = 0;
624 for (auto const &a_view : {basic_array_view(a0), basic_array_view(as)...}) {
625 slice_Axis(new_array, range(offset, offset + a_view.extent(Axis))) = a_view;
626 offset += a_view.extent(Axis);
627 }
628
629 return new_array;
630 };
631
632 /** @} */
633
634} // namespace nda
void swap(nda::basic_array_view< V1, R1, LP1, A1, AP1, OP1 > &a, nda::basic_array_view< V2, R2, LP2, A2, AP2, OP2 > &b)=delete
std::swap is deleted for nda::basic_array_view.
Iterator for nda::basic_array and nda::basic_array_view types.
A generic view of a multi-dimensional array.
basic_array_view(A &&a) noexcept
Generic constructor from any nda::MemoryArray type.
const_iterator end() const noexcept
Get a const iterator to the end of the view/array.
ValueType const * data() const noexcept
Get a pointer to the actual data (in general this is not the beginning of the memory block for a view...
static constexpr bool is_stride_order_C() noexcept
Is the stride order of the view/array in C-order?
iterator begin() noexcept
Get an iterator to the beginning of the view/array.
ValueType * data() noexcept
Get a pointer to the actual data (in general this is not the beginning of thr memory block for a view...
basic_array_view & operator=(RHS const &rhs) noexcept
Assignment operator makes a deep copy of the contents of an nda::ArrayOfRank object.
auto & operator/=(RHS const &rhs) noexcept
Division assignment operator.
static constexpr int rank
Number of dimensions of the view.
decltype(auto) operator[](T const &idx) const &noexcept(has_no_boundcheck)
Subscript operator to access the 1-dimensional view/array.
auto const & shape() const noexcept
Get the shape of the view/array.
static __inline__ decltype(auto) call(Self &&self, Ts const &...idxs) noexcept(has_no_boundcheck)
Implementation of the function call operator.
basic_array_view(layout_t const &idxm, ValueType *p) noexcept
Construct a view from a bare pointer to some contiguous data and a memory layout.
__inline__ decltype(auto) operator()(Ts const &...idxs) &noexcept(has_no_boundcheck)
Non-const overload of nda::basic_array_view::operator()(Ts const &...) const &.
decltype(auto) operator[](T const &x) &&noexcept(has_no_boundcheck)
Rvalue overload of nda::basic_array_view::operator[](T const &) const &.
basic_array_view(R &rg) noexcept
Construct a 1-dimensional view of a general contiguous range.
basic_array_view & operator=(basic_array_view const &rhs) noexcept
Copy assignment operator makes a deep copy of the contents of the view.
basic_array_view(std::array< ValueType, N > &a) noexcept
Construct a 1-dimensional view of a std::array.
auto const & strides() const noexcept
Get the strides of the view/array (see nda::idx_map for more details on how we define strides).
long shape(int i) const noexcept
storage_t storage() &&noexcept
Get the data storage of the view/array.
decltype(auto) operator[](T const &x) &noexcept(has_no_boundcheck)
Non-const overload of nda::basic_array_view::operator[](T const &) const &.
decltype(auto) operator()(_linear_index_t idx) noexcept
Non-const overload of nda::basic_array_view::operator()(_linear_index_t) const.
auto & operator+=(RHS const &rhs) noexcept
Addition assignment operator.
auto indices() const noexcept
Get a range that generates all valid index tuples.
basic_array_view()=default
Default constructor constructs an empty view with a default constructed memory handle and layout.
long is_contiguous() const noexcept
Is the memory layout of the view/array contiguous?
auto & operator=(R const &rhs) noexcept
Assignment operator makes a deep copy of a general contiguous range and assigns it to the 1-dimension...
storage_t & storage() &noexcept
Get the data storage of the view/array.
static constexpr bool is_stride_order_Fortran() noexcept
Is the stride order of the view/array in Fortran-order?
decltype(auto) operator()(_linear_index_t idx) const noexcept
Access the element of the view/array at the given nda::_linear_index_t.
__inline__ decltype(auto) operator()(Ts const &...idxs) const &noexcept(has_no_boundcheck)
Function call operator to access the view/array.
auto & operator*=(RHS const &rhs) noexcept
Multiplication assignment operator.
basic_array_view(std::array< std::remove_const_t< ValueType >, N > const &a) noexcept
Construct a 1-dimensional view of a std::array.
friend void deep_swap(basic_array_view a, basic_array_view b) noexcept
Swap two views by swapping their data.
iterator end() noexcept
Get an iterator to the end of the view/array.
long size() const noexcept
Get the total size of the view/array.
auto & operator-=(RHS const &rhs) noexcept
Subtraction assignment operator.
bool empty() const
Is the view/array empty?
basic_array_view(std::array< long, Rank > const &shape, ValueType *p) noexcept
Construct a view from a bare pointer to some contiguous data and a shape.
bool is_empty() const noexcept
friend void swap(basic_array_view &a, basic_array_view &b) noexcept
Swap two views by swapping their memory handles and layouts.
constexpr auto stride_order() const noexcept
Get the stride order of the memory layout of the view/array (see nda::idx_map for more details on how...
const_iterator cbegin() const noexcept
Get a const iterator to the beginning of the view/array.
basic_array_view(layout_t const &idxm, storage_t st)
Construct a view from a given layout and memory handle.
static constexpr int iterator_rank
Rank of the nda::array_iterator for the view/array.
basic_array_view(basic_array_view &&)=default
Default move constructor moves the memory handle and layout.
void rebind(basic_array_view< T, R, LP, A, AP, OP > v) noexcept
Rebind the current view to another view.
basic_array_view(basic_array_view const &)=default
Default copy constructor copies the memory handle and layout.
__inline__ decltype(auto) operator()(Ts const &...idxs) &&noexcept(has_no_boundcheck)
Rvalue overload of nda::basic_array_view::operator()(Ts const &...) const &.
long extent(int i) const noexcept
Get the extent of the ith dimension.
constexpr auto const & indexmap() const noexcept
Get the memory layout of the view/array.
const_iterator begin() const noexcept
Get a const iterator to the beginning of the view/array.
const_iterator cend() const noexcept
Get a const iterator to the end of the view/array.
storage_t const & storage() const &noexcept
Get the data storage of the view/array.
A generic multi-dimensional array.
auto & operator+=(RHS const &rhs) noexcept
Addition assignment operator.
decltype(auto) operator[](T const &idx) const &noexcept(has_no_boundcheck)
Subscript operator to access the 1-dimensional view/array.
basic_array(basic_array< ValueType, 2, LayoutPolicy, A2, ContainerPolicy > &&a) noexcept
Construct a 2-dimensional array from another 2-dimensional array with a different algebra.
basic_array & operator=(RHS const &rhs)
Assignment operator makes a deep copy of an nda::ArrayOfRank object.
static constexpr bool is_stride_order_Fortran() noexcept
Is the stride order of the view/array in Fortran-order?
ValueType const * data() const noexcept
Get a pointer to the actual data (in general this is not the beginning of the memory block for a view...
ValueType * data() noexcept
Get a pointer to the actual data (in general this is not the beginning of thr memory block for a view...
long shape(int i) const noexcept
const_iterator cbegin() const noexcept
Get a const iterator to the beginning of the view/array.
static constexpr int rank
Number of dimensions of the array.
static constexpr bool is_stride_order_C() noexcept
Is the stride order of the view/array in C-order?
storage_t & storage() &noexcept
Get the data storage of the view/array.
basic_array(basic_array< ValueType, Rank, LayoutPolicy, A, CP > a) noexcept
Construct an array from another array with a different algebra and/or container policy.
auto const & strides() const noexcept
Get the strides of the view/array (see nda::idx_map for more details on how we define strides).
basic_array(Ints... is)
Construct an array with the given dimensions.
static basic_array ones(Ints... is)
Make a one-initialized array with the given dimensions.
const_iterator begin() const noexcept
Get a const iterator to the beginning of the view/array.
auto as_array_view() const
Convert the current array to a view with an 'A' (array) algebra.
long extent(int i) const noexcept
Get the extent of the ith dimension.
basic_array(std::initializer_list< ValueType > const &l)
Construct a 1-dimensional array from an initializer list.
decltype(auto) operator[](T const &x) &&noexcept(has_no_boundcheck)
Rvalue overload of nda::basic_array_view::operator[](T const &) const &.
long is_contiguous() const noexcept
Is the memory layout of the view/array contiguous?
basic_array(std::initializer_list< std::initializer_list< ValueType > > const &l2)
Construct a 2-dimensional array from a double nested initializer list.
decltype(auto) operator()(_linear_index_t idx) noexcept
Non-const overload of nda::basic_array_view::operator()(_linear_index_t) const.
__inline__ decltype(auto) operator()(Ts const &...idxs) &noexcept(has_no_boundcheck)
Non-const overload of nda::basic_array_view::operator()(Ts const &...) const &.
bool empty() const
Is the view/array empty?
void resize(std::array< long, Rank > const &shape)
Resize the array to a new shape.
basic_array(Int sz, RHS const &val)
Construct a 1-dimensional array with the given size and initialize each element to the given scalar v...
static basic_array ones(std::array< Int, Rank > const &shape)
Make a one-initialized array with the given shape.
constexpr auto stride_order() const noexcept
Get the stride order of the memory layout of the view/array (see nda::idx_map for more details on how...
auto & operator/=(RHS const &rhs) noexcept
Division assignment operator.
auto as_array_view()
Convert the current array to a view with an 'A' (array) algebra.
basic_array(A const &a)
Construct an array from an nda::ArrayOfRank object with the same rank by copying each element.
static basic_array zeros(Ints... is)
Make a zero-initialized array with the given dimensions.
auto indices() const noexcept
Get a range that generates all valid index tuples.
static __inline__ decltype(auto) call(Self &&self, Ts const &...idxs) noexcept(has_no_boundcheck)
Implementation of the function call operator.
void resize(Ints const &...is)
Resize the array to a new shape.
storage_t storage() &&noexcept
Get the data storage of the view/array.
basic_array()
Default constructor constructs an empty array with a default constructed memory handle and layout.
bool is_empty() const noexcept
auto & operator=(R const &rhs) noexcept
Assignment operator makes a deep copy of a general contiguous range and assigns it to the 1-dimension...
storage_t const & storage() const &noexcept
Get the data storage of the view/array.
basic_array & operator=(basic_array const &)=default
Default copy assignment copies the memory handle and layout from the right hand side array.
basic_array & operator=(basic_array< ValueType, Rank, LayoutPolicy, A, CP > const &rhs)
Assignment operator makes a deep copy of another array with a different algebra and/or container poli...
basic_array(basic_array const &a)=default
Default copy constructor copies the memory handle and layout.
basic_array(std::initializer_list< std::initializer_list< std::initializer_list< ValueType > > > const &l3)
Construct a 3-dimensional array from a triple nested initializer list.
iterator begin() noexcept
Get an iterator to the beginning of the view/array.
basic_array(layout_t const &layout)
Construct an array with the given memory layout.
static basic_array rand(Ints... is)
Make a random-initialized array with the given dimensions.
basic_array(layout_t const &layout, storage_t &&storage) noexcept
Construct an array with the given memory layout and with an existing memory handle/storage.
static constexpr int iterator_rank
Rank of the nda::array_iterator for the view/array.
auto & operator-=(RHS const &rhs) noexcept
Subtraction assignment operator.
const_iterator end() const noexcept
Get a const iterator to the end of the view/array.
basic_array(basic_array &&)=default
Default move constructor moves the memory handle and layout.
__inline__ decltype(auto) operator()(Ts const &...idxs) &&noexcept(has_no_boundcheck)
Rvalue overload of nda::basic_array_view::operator()(Ts const &...) const &.
basic_array(std::array< Int, Rank > const &shape)
Construct an array with the given shape.
const_iterator cend() const noexcept
Get a const iterator to the end of the view/array.
auto const & shape() const noexcept
Get the shape of the view/array.
long size() const noexcept
Get the total size of the view/array.
decltype(auto) operator[](T const &x) &noexcept(has_no_boundcheck)
Non-const overload of nda::basic_array_view::operator[](T const &) const &.
auto & operator*=(RHS const &rhs) noexcept
Multiplication assignment operator.
basic_array & operator=(basic_array &&)=default
Default move assignment moves the memory handle and layout from the right hand side array.
static basic_array zeros(std::array< Int, Rank > const &shape)
Make a zero-initialized array with the given shape.
__inline__ decltype(auto) operator()(Ts const &...idxs) const &noexcept(has_no_boundcheck)
Function call operator to access the view/array.
constexpr auto const & indexmap() const noexcept
Get the memory layout of the view/array.
iterator end() noexcept
Get an iterator to the end of the view/array.
decltype(auto) operator()(_linear_index_t idx) const noexcept
Access the element of the view/array at the given nda::_linear_index_t.
static basic_array rand(std::array< Int, Rank > const &shape)
Make a random-initialized array with the given shape.
#define CUSOLVER_CHECK(X, info,...)
#define NDA_RUNTIME_ERROR
auto rand(std::array< Int, Rank > const &shape)
Make an array of the given shape and initialize it with random values from the uniform distribution o...
decltype(auto) make_regular(A &&a)
Make a given object regular.
void resize_or_check_if_view(A &a, std::array< long, A::rank > const &sha)
Resize a given regular array to the given shape or check if a given view as the correct shape.
decltype(auto) to_unified(A &&a)
Convert an nda::MemoryArray to its regular type on unified memory.
auto make_const_view(basic_array< T, R, LP, A, CP > const &a)
Make an nda::basic_array_view with a const value type from a given nda::basic_array.
auto zeros(Ints... is)
Make an array of the given shape on the given address space and zero-initialize it.
auto zeros(std::array< Int, Rank > const &shape)
Make an array of the given shape on the given address space and zero-initialize it.
auto rand(Ints... is)
Make an array of the given dimensions and initialize it with random values from the uniform distribut...
auto arange(long first, long last, long step=1)
Make a 1-dimensional integer array and initialize it with values of a given nda::range.
decltype(auto) to_host(A &&a)
Convert an nda::MemoryArray to its regular type on host memory.
auto make_matrix_view(basic_array_view< T, R, LP, A, AP, OP > const &a)
Make an nda::matrix_view of a given nda::basic_array_view.
auto arange(long last)
Make a 1-dimensional integer array and initialize it with values of a given nda::range with a step si...
auto make_matrix_view(basic_array< T, R, LP, A, CP > const &a)
Make an nda::matrix_view of a given nda::basic_array.
auto ones(Ints... is)
Make an array with the given dimensions and one-initialize it.
auto make_const_view(basic_array_view< T, R, LP, A, AP, OP > const &a)
Make an nda::basic_array_view with a const value type from a given nda::basic_array_view.
decltype(auto) to_device(A &&a)
Convert an nda::MemoryArray to its regular type on device memory.
auto make_array_view(basic_array< T, R, LP, A, CP > const &a)
Make an nda::array_view of a given nda::basic_array.
auto make_array_const_view(basic_array< T, R, LP, A, CP > const &a)
Make an nda::array_const_view of a given nda::basic_array.
auto ones(std::array< Int, Rank > const &shape)
Make an array of the given shape and one-initialize it.
auto make_array_const_view(basic_array_view< T, R, LP, A, AP, OP > const &a)
Make an nda::array_const_view of a given nda::basic_array_view.
auto make_array_view(basic_array_view< T, R, LP, A, AP, OP > const &a)
Make an nda::array_view of a given nda::basic_array_view.
auto concatenate(A0 const &a0, As const &...as)
Join a sequence of nda::Array types along an existing axis.
long first_dim(A const &a)
Get the extent of the first dimension of the array.
constexpr uint64_t static_extents(int i0, Is... is)
Encode the given shape into a single integer using the nda::encode function.
bool operator==(LHS const &lhs, RHS const &rhs)
Equal-to comparison operator for two nda::Array objects.
long second_dim(A const &a)
Get the extent of the second dimension of the array.
void clef_auto_assign(A &&a, F &&f)
Overload of nda::clef::clef_auto_assign function for nda::Array objects.
auto get_block_layout(A const &a)
Check if a given nda::MemoryArray has a block-strided layout.
layout_prop_e
Compile-time guarantees of the memory layout of an array/view.
Definition traits.hpp:222
AddressSpace
Enum providing identifiers for the different memory address spaces.
static constexpr do_not_initialize_t do_not_initialize
Instance of nda::mem::do_not_initialize_t.
Definition handle.hpp:69
static constexpr init_zero_t init_zero
Instance of nda::mem::init_zero_t.
Definition handle.hpp:75
constexpr uint64_t encode(std::array< int, N > const &a)
Encode a std::array<int, N> in a uint64_t.
#define EXPECTS(X)
Definition macros.hpp:59
#define FORCEINLINE
Definition macros.hpp:41
#define EXPECTS_WITH_MESSAGE(X,...)
Definition macros.hpp:75
#define AS_STRING(...)
Definition macros.hpp:31
#define ASSERT(X)
Definition macros.hpp:64
Contiguous layout policy with C-order (row-major order).
Definition policies.hpp:47
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
Generic layout policy with arbitrary order.
Definition policies.hpp:115
Memory policy using an nda::mem::handle_borrowed.
Definition policies.hpp:108
Accessor type of the nda::default_accessor.
Definition accessors.hpp:42
static __inline__ T * offset(pointer p, std::ptrdiff_t i) noexcept
Offset the pointer by a certain number of elements.
Definition accessors.hpp:71
static __inline__ reference access(pointer p, std::ptrdiff_t i) noexcept
Access a specific element of the data.
Definition accessors.hpp:59
Default accessor for various array and view types.
Definition accessors.hpp:36
Tag used in constructors to indicate that the memory should be initialized to zero.
Definition handle.hpp:72
Accessor type of the nda::no_alias_accessor.
Definition accessors.hpp:82
static __inline__ reference access(pointer p, std::ptrdiff_t i) noexcept
Access a specific element of the data.
Definition accessors.hpp:99
static __inline__ T * offset(pointer p, std::ptrdiff_t i) noexcept
Offset the pointer by a certain number of elements.
Accessor for array and view types with no aliasing.
Definition accessors.hpp:76