TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
allocators.hpp
Go to the documentation of this file.
1// Copyright (c) 2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2022 Simons Foundation
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0.txt
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
17// Authors: Miguel Morales, Olivier Parcollet, Nils Wentzell
18
19/**
20 * @file
21 * @brief Provides custom allocators for the nda library.
22 */
23
24#pragma once
25
26#include "./address_space.hpp"
27#include "./malloc.hpp"
28#include "./memset.hpp"
29#include "../macros.hpp"
30
31#include <algorithm>
32#include <cstddef>
33#include <cstdint>
34#include <cstdlib>
35#include <memory>
36#include <vector>
37#include <utility>
38
39#ifndef NDEBUG
40#include <iostream>
41#endif
42
43#if defined(__has_feature)
44#if __has_feature(address_sanitizer)
45#include <sanitizer/asan_interface.h>
46#define NDA_USE_ASAN
47#endif
48#endif
49
50namespace nda::mem {
51
52 /**
53 * @addtogroup mem_allocators
54 * @{
55 */
56
57 /// Memory block consisting of a pointer and its size.
58 struct blk_t {
59 /// Pointer to the memory block.
60 char *ptr = nullptr;
61
62 /// Size of the memory block in bytes.
63 size_t s = 0;
64 };
65
66 /**
67 * @brief Custom allocator that uses nda::mem::malloc to allocate memory.
68 * @tparam AdrSp nda::mem::AddressSpace in which the memory is allocated.
69 */
70 template <AddressSpace AdrSp = Host>
71 class mallocator {
72 public:
73 /// Default constructor.
74 mallocator() = default;
75
76 /// Deleted copy constructor.
77 mallocator(mallocator const &) = delete;
78
79 /// Default move constructor.
80 mallocator(mallocator &&) = default;
81
82 /// Deleted copy assignment operator.
83 mallocator &operator=(mallocator const &) = delete;
84
85 /// Default move assignment operator.
87
88 /// nda::mem::AddressSpace in which the memory is allocated.
89 static constexpr auto address_space = AdrSp;
90
91 /**
92 * @brief Allocate memory using nda::mem::malloc.
93 *
94 * @param s Size in bytes of the memory to allocate.
95 * @return nda::mem::blk_t memory block.
96 */
97 static blk_t allocate(size_t s) noexcept { return {(char *)malloc<AdrSp>(s), s}; }
98
99 /**
100 * @brief Allocate memory and set it to zero.
101 *
102 * @details The behavior depends on the address space:
103 * - It uses std::calloc for `Host` nda::mem::AddressSpace.
104 * - Otherwise it uses nda::mem::malloc and nda::mem::memset.
105 *
106 * @param s Size in bytes of the memory to allocate.
107 * @return nda::mem::blk_t memory block.
108 */
109 static blk_t allocate_zero(size_t s) noexcept {
110 if constexpr (AdrSp == mem::Host) {
111 return {(char *)std::calloc(s, 1 /* byte */), s}; // NOLINT (C-style cast is fine here)
112 } else {
113 char *ptr = (char *)malloc<AdrSp>(s);
114 memset<AdrSp>(ptr, 0, s);
115 return {ptr, s};
116 }
117 }
118
119 /**
120 * @brief Deallocate memory using nda::mem::free.
121 * @param b nda::mem::blk_t memory block to deallocate.
122 */
123 static void deallocate(blk_t b) noexcept { free<AdrSp>((void *)b.ptr); }
124 };
125
126 /**
127 * @brief Custom allocator that allocates a bucket of memory on the heap consisting of 64 chunks.
128 *
129 * @details The allocator keeps track of which chunks are free using a bitmask. Once all chunks have been allocated,
130 * it will call std::abort on any further allocation requests.
131 *
132 * @note Only works with `Host` nda::mem::AddressSpace.
133 *
134 * @tparam ChunkSize Size of the chunks in bytes.
135 */
136 template <int ChunkSize>
137 class bucket {
138 // Unique pointer to handle memory allocation for the bucket.
139 std::unique_ptr<char[]> _start = std::make_unique<char[]>(TotalChunkSize); // NOLINT (C-style array is fine here)
140
141 // Pointer to the start of the bucket.
142 char *p = _start.get();
143
144 // Bitmask to keep track of which chunks are free.
145 uint64_t flags = uint64_t(-1);
146
147 public:
148 /// Total size of the bucket in bytes.
149 static constexpr int TotalChunkSize = 64 * ChunkSize;
150
151 /// Only `Host` nda::mem::AddressSpace is supported for this allocator.
152 static constexpr auto address_space = Host;
153
154#ifdef NDA_USE_ASAN
157#else
158 /// Default constructor.
159 bucket() = default;
160#endif
161 /// Deleted copy constructor.
162 bucket(bucket const &) = delete;
163
164 /// Default move constructor.
165 bucket(bucket &&) = default;
166
167 /// Deleted copy assignment operator.
168 bucket &operator=(bucket const &) = delete;
169
170 /// Default move assignment operator.
171 bucket &operator=(bucket &&) = default;
172
173 /**
174 * @brief Allocate a chunk of memory in the bucket and update the bitmask.
175 *
176 * @param s Size in bytes of the returned memory block (has to be < `ChunkSize`).
177 * @return nda::mem::blk_t memory block.
178 */
179 blk_t allocate(size_t s) noexcept {
180 // check the size and if there is a free chunk, otherwise abort
181 if (s > ChunkSize) std::abort();
182 if (flags == 0) std::abort();
183
184 // find the first free chunk
185 int pos = __builtin_ctzll(flags);
186
187 // update the bitmask and return the memory block
188 flags &= ~(1ull << pos);
189 blk_t b{p + static_cast<ptrdiff_t>(pos * ChunkSize), s};
190#ifdef NDA_USE_ASAN
191 __asan_unpoison_memory_region(b.ptr, ChunkSize);
192#endif
193 return b;
194 }
195
196 /**
197 * @brief Allocate a chunk of memory in the bucket, set it to zero and update the bitmask.
198 *
199 * @param s Size in bytes of the returned memory block (has to be < `ChunkSize`).
200 * @return nda::mem::blk_t memory block.
201 */
202 blk_t allocate_zero(size_t s) noexcept {
203 auto blk = allocate(s);
204 std::memset(blk.ptr, 0, s);
205 return blk;
206 }
207
208 /**
209 * @brief Deallocate a chunk of memory from the bucket by simply resetting the bitmask.
210 * @param b nda::mem::blk_t memory block to deallocate.
211 */
212 void deallocate(blk_t b) noexcept {
213#ifdef NDA_USE_ASAN
214 __asan_poison_memory_region(b.ptr, ChunkSize);
215#endif
216 int pos = (b.ptr - p) / ChunkSize;
217 flags |= (1ull << pos);
218 }
219
220 /**
221 * @brief Check if the bucket is full.
222 * @return True if there are no free chunks left, i.e. the bitmask is all zeros.
223 */
224 [[nodiscard]] bool is_full() const noexcept { return flags == 0; }
225
226 /**
227 * @brief Check if the bucket is empty.
228 * @return True if all chunks are free, i.e. the bitmask is all ones.
229 */
230 [[nodiscard]] bool empty() const noexcept { return flags == uint64_t(-1); }
231
232 /**
233 * @brief Get a pointer to the start of the bucket.
234 * @return Pointer to the chunk with the lowest memory address.
235 */
236 [[nodiscard]] const char *data() const noexcept { return p; }
237
238 /**
239 * @brief Get the bitmask of the bucket.
240 * @return Bitmask in the form of a `uint64_t`.
241 */
242 [[nodiscard]] auto mask() const noexcept { return flags; }
243
244 /**
245 * @brief Check if a given nda::mem::blk_t memory block is owned by the bucket.
246 *
247 * @param b nda::mem::blk_t memory block.
248 * @return True if the memory block is owned by the bucket.
249 */
250 [[nodiscard]] bool owns(blk_t b) const noexcept { return b.ptr >= p and b.ptr < p + TotalChunkSize; }
251 };
252
253 /**
254 * @brief Custom allocator that uses multiple nda::mem::bucket allocators.
255 *
256 * @details It uses a std::vector of bucket allocators. When all buckets in the vector are full, it simply adds a new
257 * one at the end.
258 *
259 * @note Only works with `Host` nda::mem::AddressSpace.
260 *
261 * @tparam ChunkSize Size of the chunks in bytes.
262 */
263 template <int ChunkSize>
265 // Alias for the bucket allocator type.
266 using b_t = bucket<ChunkSize>;
267
268 // Vector of nda::mem::bucket allocators (ordered in memory).
269 std::vector<b_t> bu_vec;
270
271 // Iterator to the current bucket in use.
272 typename std::vector<b_t>::iterator bu;
273
274 // Find a bucket with a free chunk, otherwise create a new one and insert it at the correct position.
275 [[gnu::noinline]] void find_non_full_bucket() {
276 bu = std::find_if(bu_vec.begin(), bu_vec.end(), [](auto const &b) { return !b.is_full(); });
277 if (bu != bu_vec.end()) return;
278 b_t b;
279 auto pos = std::upper_bound(bu_vec.begin(), bu_vec.end(), b, [](auto const &b1, auto const &b2) { return b1.data() < b2.data(); });
280 bu = bu_vec.insert(pos, std::move(b));
281 }
282
283 public:
284 /// Only `Host` nda::mem::AddressSpace is supported for this allocator.
285 static constexpr auto address_space = Host;
286
287 /// Default constructor.
288 multi_bucket() : bu_vec(1), bu(bu_vec.begin()) {}
289
290 /// Deleted copy constructor.
291 multi_bucket(multi_bucket const &) = delete;
292
293 /// Default move constructor.
295
296 /// Deleted copy assignment operator.
297 multi_bucket &operator=(multi_bucket const &) = delete;
298
299 /// Default move assignment operator.
301
302 /**
303 * @brief Allocate a chunk of memory in the current bucket or find a new one if the current one is full.
304 *
305 * @param s Size in bytes of the returned memory block (has to be < `ChunkSize`).
306 * @return nda::mem::blk_t memory block.
307 */
308 blk_t allocate(size_t s) noexcept {
309 if ((bu == bu_vec.end()) or (bu->is_full())) find_non_full_bucket();
310 return bu->allocate(s);
311 }
312
313 /**
314 * @brief Allocate a chunk of memory in the current bucket or find a new one if the current one is full and set it
315 * to zero.
316 *
317 * @param s Size in bytes of the returned memory block (has to be < `ChunkSize`).
318 * @return nda::mem::blk_t memory block.
319 */
320 blk_t allocate_zero(size_t s) noexcept {
321 auto blk = allocate(s);
322 std::memset(blk.ptr, 0, s);
323 return blk;
324 }
325
326 /**
327 * @brief Deallocate a chunk of memory from the bucket to which it belongs.
328 *
329 * @details If the bucket is empty after deallocation and it is not the only one, it is removed from the vector of
330 * buckets.
331 *
332 * @param b nda::mem::blk_t memory block to deallocate.
333 */
334 void deallocate(blk_t b) noexcept {
335 // try the current bucket first
336 if (bu != bu_vec.end() and bu->owns(b)) {
337 bu->deallocate(b);
338 return;
339 }
340
341 // otherwise, find the owning bucket in the vector and deallocate
342 bu = std::lower_bound(bu_vec.begin(), bu_vec.end(), b.ptr, [](auto const &b1, auto p) { return b1.data() <= p; });
343 --bu;
344 EXPECTS_WITH_MESSAGE((bu != bu_vec.end()), "Error in nda::mem::multi_bucket::deallocate: Owning bucket not found");
345 EXPECTS_WITH_MESSAGE((bu->owns(b)), "Error in nda::mem::multi_bucket::deallocate: Owning bucket not found");
346 bu->deallocate(b);
347
348 // remove bucket the current bucket if it is empty and not the only one
349 if (!bu->empty()) return;
350 if (bu_vec.size() <= 1) return;
351 bu_vec.erase(bu);
352 bu = bu_vec.end();
353 }
354
355 /**
356 * @brief Check if the current allocator is empty.
357 * @return True if there is only one bucket in the vector and it is empty.
358 */
359 [[nodiscard]] bool empty() const noexcept { return bu_vec.size() == 1 && bu_vec[0].empty(); }
360
361 /**
362 * @brief Get the bucket vector.
363 * @return std::vector with all the bucket allocators currently in use.
364 */
365 [[nodiscard]] auto const &buckets() const noexcept { return bu_vec; }
366
367 /**
368 * @brief Check if a given nda::mem::blk_t memory block is owned by allocator.
369 *
370 * @param b nda::mem::blk_t memory block.
371 * @return True if the memory block is owned by one of the buckets.
372 */
373 [[nodiscard]] bool owns(blk_t b) const noexcept {
374 bool res = false;
375 for (const auto &mb : bu_vec) { res = res || mb.owns(b); }
376 return res;
377 }
378 };
379
380 /**
381 * @brief Custom allocator that dispatches memory allocation to one of two allocators based on the size of the memory
382 * block to be allocated.
383 *
384 * @note Only works if both allocators have the same nda::mem::AddressSpace.
385 *
386 * @tparam Threshold Size in bytes that determines which allocator to use.
387 * @tparam A nda::mem::Allocator for small memory blocks.
388 * @tparam B nda::mem::Allocator for big memory blocks.
389 */
390 template <size_t Threshold, Allocator A, Allocator B>
392 // Allocator for small memory blocks.
393 A small;
394
395 // Allocator for big memory blocks.
396 B big;
397
398 public:
399 static_assert(A::address_space == B::address_space);
400
401 /// nda::mem::AddressSpace in which the memory is allocated.
402 static constexpr auto address_space = A::address_space;
403
404 /// Default constructor.
405 segregator() = default;
406
407 /// Deleted copy constructor.
408 segregator(segregator const &) = delete;
409
410 /// Default move constructor.
411 segregator(segregator &&) = default;
412
413 /// Deleted copy assignment operator.
414 segregator &operator=(segregator const &) = delete;
415
416 /// Default move assignment operator.
418
419 /**
420 * @brief Allocate memory using the small allocator if the size is less than or equal to the `Threshold`, otherwise
421 * use the big allocator.
422 *
423 * @param s Size in bytes of the memory to allocate.
424 * @return nda::mem::blk_t memory block.
425 */
426 blk_t allocate(size_t s) noexcept { return s <= Threshold ? small.allocate(s) : big.allocate(s); }
427
428 /**
429 * @brief Allocate memory and set the memory to zero using the small allocator if the size is less than or equal to
430 * the `Threshold`, otherwise use the big allocator.
431 *
432 * @param s Size in bytes of the memory to allocate.
433 * @return nda::mem::blk_t memory block.
434 */
435 blk_t allocate_zero(size_t s) noexcept { return s <= Threshold ? small.allocate_zero(s) : big.allocate_zero(s); }
436
437 /**
438 * @brief Deallocate memory using the small allocator if the size is less than or equal to the `Threshold`,
439 * otherwise use the big allocator.
440 *
441 * @param b nda::mem::blk_t memory block to deallocate.
442 */
443 void deallocate(blk_t b) noexcept { return b.s <= Threshold ? small.deallocate(b) : big.deallocate(b); }
444
445 /**
446 * @brief Check if a given nda::mem::blk_t memory block is owned by the allocator.
447 *
448 * @param b nda::mem::blk_t memory block.
449 * @return True if one of the two allocators owns the memory block.
450 */
451 [[nodiscard]] bool owns(blk_t b) const noexcept { return small.owns(b) or big.owns(b); }
452 };
453
454 /**
455 * @brief Wrap an allocator to check for memory leaks.
456 *
457 * @details It simply keeps track of the memory currently being used by the allocator, i.e. the total memory allocated
458 * minus the total memory deallocated, which should never be smaller than zero and should be exactly zero when the
459 * allocator is destroyed.
460 *
461 * @tparam A nda::mem::Allocator type to wrap.
462 */
463 template <Allocator A>
464 class leak_check : A {
465 // Total memory used by the allocator.
466 long memory_used = 0;
467
468 public:
469 /// nda::mem::AddressSpace in which the memory is allocated.
470 static constexpr auto address_space = A::address_space;
471
472 /// Default constructor.
473 leak_check() = default;
474
475 /// Deleted copy constructor.
476 leak_check(leak_check const &) = delete;
477
478 /// Default move constructor.
479 leak_check(leak_check &&) = default;
480
481 /// Deleted copy assignment operator.
482 leak_check &operator=(leak_check const &) = delete;
483
484 /// Default move assignment operator.
486
487 /**
488 * @brief Destructor that checks for memory leaks.
489 * @details In debug mode, it aborts the program if there is a memory leak.
490 */
492 if (!empty()) {
493#ifndef NDEBUG
494 std::cerr << "Memory leak in allocator: " << memory_used << " bytes leaked\n";
495 std::abort();
496#endif
497 }
498 }
499
500 /**
501 * @brief Allocate memory and update the total memory used.
502 *
503 * @param s Size in bytes of the memory to allocate.
504 * @return nda::mem::blk_t memory block.
505 */
506 blk_t allocate(size_t s) {
507 blk_t b = A::allocate(s);
508 memory_used += b.s;
509 return b;
510 }
511
512 /**
513 * @brief Allocate memory, set it to zero and update the total memory used.
514 *
515 * @param s Size in bytes of the memory to allocate.
516 * @return nda::mem::blk_t memory block.
517 */
519 blk_t b = A::allocate_zero(s);
520 memory_used += b.s;
521 return b;
522 }
523
524 /**
525 * @brief Deallocate memory and update the total memory used.
526 * @details In debug mode, it aborts the program if the total memory used is smaller than zero.
527 * @param b nda::mem::blk_t memory block to deallocate.
528 */
529 void deallocate(blk_t b) noexcept {
530 memory_used -= b.s;
531 if (memory_used < 0) {
532#ifndef NDEBUG
533 std::cerr << "Memory used by allocator < 0: Memory block to be deleted: b.s = " << b.s << ", b.ptr = " << (void *)b.ptr << "\n";
534 std::abort();
535#endif
536 }
537 A::deallocate(b);
538 }
539
540 /**
541 * @brief Check if the base allocator is empty.
542 * @return True if no memory is currently being used.
543 */
544 [[nodiscard]] bool empty() const { return (memory_used == 0); }
545
546 /**
547 * @brief Check if a given nda::mem::blk_t memory block is owned by the base allocator.
548 *
549 * @param b nda::mem::blk_t memory block.
550 * @return True if the base allocator owns the memory block.
551 */
552 [[nodiscard]] bool owns(blk_t b) const noexcept { return A::owns(b); }
553
554 /**
555 * @brief Get the total memory used by the base allocator.
556 * @return The size of the memory which has been allocated and not yet deallocated.
557 */
558 [[nodiscard]] long get_memory_used() const noexcept { return memory_used; }
559 };
560
561 /**
562 * @brief Wrap an allocator to gather statistics about memory allocation.
563 *
564 * @details It gathers a histogram of the different allocation sizes. The histogram is a std::vector of size 65, where
565 * element \f$ i \in \{0,...,63\} \f$ contains the number of allocations with a size in the range
566 * \f$ [2^{64-i-1}, 2^{64-i}) \f$ and the last element contains the number of allocations of size zero.
567 *
568 * @tparam A nda::mem::Allocator type to wrap.
569 */
570 template <Allocator A>
571 class stats : A {
572 // Histogram of the allocation sizes.
573 std::vector<uint64_t> hist = std::vector<uint64_t>(65, 0);
574
575 public:
576 /// nda::mem::AddressSpace in which the memory is allocated.
577 static constexpr auto address_space = A::address_space;
578
579 /// Default constructor.
580 stats() = default;
581
582 /// Deleted copy constructor.
583 stats(stats const &) = delete;
584
585 /// Default move constructor.
586 stats(stats &&) = default;
587
588 /// Deleted copy assignment operator.
589 stats &operator=(stats const &) = delete;
590
591 /// Default move assignment operator.
592 stats &operator=(stats &&) = default;
593
594 /// Destructor that outputs the statistics about the memory allocation in debug mode.
595 ~stats() {
596#ifndef NDEBUG
597 print_histogram(std::cerr);
598#endif
599 }
600
601 /**
602 * @brief Allocate memory and update the histogram.
603 *
604 * @param s Size in bytes of the memory to allocate.
605 * @return nda::mem::blk_t memory block.
606 */
607 blk_t allocate(uint64_t s) {
608 // __builtin_clzl returns the number of leading zeros
609 ++hist[__builtin_clzl(s)];
610 return A::allocate(s);
611 }
612
613 /**
614 * @brief Allocate memory, set it to zero and update the histogram.
615 *
616 * @param s Size in bytes of the memory to allocate.
617 * @return nda::mem::blk_t memory block.
618 */
619 blk_t allocate_zero(uint64_t s) {
620 // __builtin_clzl returns the number of leading zeros
621 ++hist[__builtin_clzl(s)];
622 return A::allocate_zero(s);
623 }
624
625 /**
626 * @brief Deallocate memory.
627 * @param b nda::mem::blk_t memory block to deallocate.
628 */
629 void deallocate(blk_t b) noexcept { A::deallocate(b); }
630
631 /**
632 * @brief Check if a given nda::mem::blk_t memory block is owned by the base allocator.
633 *
634 * @param b nda::mem::blk_t memory block.
635 * @return True if the base allocator owns the memory block.
636 */
637 [[nodiscard]] bool owns(blk_t b) const noexcept { return A::owns(b); }
638
639 /**
640 * @brief Get the histogram of the allocation sizes.
641 * @return std::vector of size 65 with the number of allocations in each size range.
642 */
643 [[nodiscard]] auto const &histogram() const noexcept { return hist; }
644
645 /**
646 * @brief Print the histogram to a std::ostream.
647 * @param os std::ostream object to print to.
648 */
649 void print_histogram(std::ostream &os) const {
650 os << "Allocation size histogram :\n";
651 os << "[0, 2^0): " << hist.back() << "\n";
652 for (int i = 0; i < 64; ++i) { os << "[2^" << i << ", 2^" << i + 1 << "): " << hist[63 - i] << "\n"; }
653 }
654 };
655
656 /** @} */
657
658} // namespace nda::mem
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.
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
static constexpr std::array< int, Rank > stride_order
Decoded stride order.
Definition idx_map.hpp:121
idx_map(idx_map< Rank, StaticExtents, StrideOrder, LP > const &idxm) noexcept
Construct a new map from an existing map with different layout properties.
Definition idx_map.hpp:327
static bool is_stride_order_valid(Int *lenptr, Int *strptr)
Check if a given shape and strides are compatible with the stride order.
Definition idx_map.hpp:244
static constexpr layout_info_t layout_info
Compile-time information about the layout (stride order and layout properties).
Definition idx_map.hpp:130
idx_map(idx_map &&)=default
Default move constructor.
long size() const noexcept
Get the total number of elements.
Definition idx_map.hpp:160
long min_stride() const noexcept
Get the value of the smallest stride.
Definition idx_map.hpp:190
idx_map(std::array< long, n_dynamic_extents > const &shape) noexcept
Construct a new map from an array with its dynamic extents.
Definition idx_map.hpp:404
auto transpose() const
Create a new map by permuting the indices/dimensions of the current map with a given permutation.
Definition idx_map.hpp:604
std::array< long, Rank > to_idx(long lin_idx) const
Calculate the multi-dimensional index from a given linear index.
Definition idx_map.hpp:543
bool is_stride_order_valid() const
Check if the shape and strides of the current map are compatible with its stride order.
Definition idx_map.hpp:259
idx_map(idx_map< Rank, SE, SO, LP > const &)
Construct a new map from an existing map with a different stride order.
Definition idx_map.hpp:418
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 bool is_stride_order_C()
Is the stride order equal to C-order?
Definition idx_map.hpp:227
static constexpr int n_dynamic_extents
Number of dynamic dimensions/extents.
Definition idx_map.hpp:143
static constexpr uint64_t stride_order_encoded
Encoded stride order.
Definition idx_map.hpp:124
static constexpr int rank() noexcept
Get the rank of the map.
Definition idx_map.hpp:154
static constexpr std::array< int, Rank > static_extents
Decoded static extents.
Definition idx_map.hpp:118
bool is_strided_1d() const noexcept
Is the data strided in memory with a constant stride?
Definition idx_map.hpp:216
static constexpr int argument_is_allowed_for_call_or_slice
Alias template to check if type T can be used to either access a single element or a slice of element...
Definition idx_map.hpp:138
idx_map(std::array< Int, Rank > const &shape) noexcept
Construct a new map from a given shape and with contiguous strides.
Definition idx_map.hpp:390
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
static constexpr bool is_stride_order_Fortran()
Is the stride order equal to Fortran-order?
Definition idx_map.hpp:233
idx_map(idx_map const &)=default
Default copy constructor.
static constexpr int argument_is_allowed_for_call
Alias template to check if type T can be used to access a single element.
Definition idx_map.hpp:134
static constexpr long ce_size() noexcept
Get the size known at compile-time.
Definition idx_map.hpp:166
bool is_contiguous() const noexcept
Is the data contiguous in memory?
Definition idx_map.hpp:200
idx_map(idx_map< Rank, SE, StrideOrder, LP > const &idxm) noexcept(false)
Construct a new map from an existing map with different layout properties and different static extent...
Definition idx_map.hpp:350
idx_map(std::array< long, Rank > const &shape, std::array< long, Rank > const &strides) noexcept(!check_stride_order)
Construct a new map from a given shape and strides.
Definition idx_map.hpp:374
idx_map()
Default constructor.
Definition idx_map.hpp:310
std::array< long, Rank > const & strides() const noexcept
Get the strides of all dimensions.
Definition idx_map.hpp:184
idx_map & operator=(idx_map const &)=default
Default copy assignment operator.
static constexpr layout_prop_e layout_prop
Compile-time memory layout properties.
Definition idx_map.hpp:127
static constexpr uint64_t static_extents_encoded
Encoded static extents.
Definition idx_map.hpp:115
idx_map & operator=(idx_map &&)=default
Default move assignment operator.
idx_map(std::array< long, R > const &)
Construct a new map with a shape of a different rank.
Definition idx_map.hpp:430
Custom allocator that allocates a bucket of memory on the heap consisting of 64 chunks.
bucket(bucket &&)=default
Default move constructor.
bool empty() const noexcept
Check if the bucket is empty.
bucket()=default
Default constructor.
bool owns(blk_t b) const noexcept
Check if a given nda::mem::blk_t memory block is owned by the bucket.
void deallocate(blk_t b) noexcept
Deallocate a chunk of memory from the bucket by simply resetting the bitmask.
bool is_full() const noexcept
Check if the bucket is full.
auto mask() const noexcept
Get the bitmask of the bucket.
const char * data() const noexcept
Get a pointer to the start of the bucket.
static constexpr auto address_space
Only Host nda::mem::AddressSpace is supported for this allocator.
bucket(bucket const &)=delete
Deleted copy constructor.
bucket & operator=(bucket const &)=delete
Deleted copy assignment operator.
bucket & operator=(bucket &&)=default
Default move assignment operator.
blk_t allocate(size_t s) noexcept
Allocate a chunk of memory in the bucket and update the bitmask.
static constexpr int TotalChunkSize
Total size of the bucket in bytes.
blk_t allocate_zero(size_t s) noexcept
Allocate a chunk of memory in the bucket, set it to zero and update the bitmask.
Wrap an allocator to check for memory leaks.
bool empty() const
Check if the base allocator is empty.
long get_memory_used() const noexcept
Get the total memory used by the base allocator.
bool owns(blk_t b) const noexcept
Check if a given nda::mem::blk_t memory block is owned by the base allocator.
leak_check & operator=(leak_check &&)=default
Default move assignment operator.
static constexpr auto address_space
nda::mem::AddressSpace in which the memory is allocated.
leak_check(leak_check const &)=delete
Deleted copy constructor.
~leak_check()
Destructor that checks for memory leaks.
blk_t allocate_zero(size_t s)
Allocate memory, set it to zero and update the total memory used.
leak_check()=default
Default constructor.
blk_t allocate(size_t s)
Allocate memory and update the total memory used.
leak_check & operator=(leak_check const &)=delete
Deleted copy assignment operator.
void deallocate(blk_t b) noexcept
Deallocate memory and update the total memory used.
leak_check(leak_check &&)=default
Default move constructor.
Custom allocator that uses nda::mem::malloc to allocate memory.
mallocator & operator=(mallocator const &)=delete
Deleted copy assignment operator.
static void deallocate(blk_t b) noexcept
Deallocate memory using nda::mem::free.
mallocator & operator=(mallocator &&)=default
Default move assignment operator.
mallocator()=default
Default constructor.
mallocator(mallocator const &)=delete
Deleted copy constructor.
static blk_t allocate_zero(size_t s) noexcept
Allocate memory and set it to zero.
static blk_t allocate(size_t s) noexcept
Allocate memory using nda::mem::malloc.
static constexpr auto address_space
nda::mem::AddressSpace in which the memory is allocated.
mallocator(mallocator &&)=default
Default move constructor.
Custom allocator that uses multiple nda::mem::bucket allocators.
multi_bucket(multi_bucket &&)=default
Default move constructor.
bool owns(blk_t b) const noexcept
Check if a given nda::mem::blk_t memory block is owned by allocator.
blk_t allocate_zero(size_t s) noexcept
Allocate a chunk of memory in the current bucket or find a new one if the current one is full and set...
void deallocate(blk_t b) noexcept
Deallocate a chunk of memory from the bucket to which it belongs.
multi_bucket()
Default constructor.
bool empty() const noexcept
Check if the current allocator is empty.
static constexpr auto address_space
Only Host nda::mem::AddressSpace is supported for this allocator.
multi_bucket & operator=(multi_bucket &&)=default
Default move assignment operator.
auto const & buckets() const noexcept
Get the bucket vector.
blk_t allocate(size_t s) noexcept
Allocate a chunk of memory in the current bucket or find a new one if the current one is full.
multi_bucket(multi_bucket const &)=delete
Deleted copy constructor.
multi_bucket & operator=(multi_bucket const &)=delete
Deleted copy assignment operator.
Custom allocator that dispatches memory allocation to one of two allocators based on the size of the ...
blk_t allocate_zero(size_t s) noexcept
Allocate memory and set the memory to zero using the small allocator if the size is less than or equa...
segregator()=default
Default constructor.
segregator(segregator const &)=delete
Deleted copy constructor.
void deallocate(blk_t b) noexcept
Deallocate memory using the small allocator if the size is less than or equal to the Threshold,...
bool owns(blk_t b) const noexcept
Check if a given nda::mem::blk_t memory block is owned by the allocator.
segregator & operator=(segregator &&)=default
Default move assignment operator.
segregator(segregator &&)=default
Default move constructor.
static constexpr auto address_space
nda::mem::AddressSpace in which the memory is allocated.
segregator & operator=(segregator const &)=delete
Deleted copy assignment operator.
blk_t allocate(size_t s) noexcept
Allocate memory using the small allocator if the size is less than or equal to the Threshold,...
Wrap an allocator to gather statistics about memory allocation.
stats & operator=(stats &&)=default
Default move assignment operator.
static constexpr auto address_space
nda::mem::AddressSpace in which the memory is allocated.
blk_t allocate(uint64_t s)
Allocate memory and update the histogram.
auto const & histogram() const noexcept
Get the histogram of the allocation sizes.
void print_histogram(std::ostream &os) const
Print the histogram to a std::ostream.
blk_t allocate_zero(uint64_t s)
Allocate memory, set it to zero and update the histogram.
~stats()
Destructor that outputs the statistics about the memory allocation in debug mode.
stats & operator=(stats const &)=delete
Deleted copy assignment operator.
bool owns(blk_t b) const noexcept
Check if a given nda::mem::blk_t memory block is owned by the base allocator.
stats(stats const &)=delete
Deleted copy constructor.
void deallocate(blk_t b) noexcept
Deallocate memory.
stats(stats &&)=default
Default move constructor.
stats()=default
Default constructor.
#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 bool is_view_v< basic_array_view< ValueType, Rank, Layout, Algebra, AccessorPolicy, OwningPolicy > >
Specialization of nda::is_view_v for nda::basic_array_view.
constexpr bool is_regular_v< basic_array< ValueType, Rank, Layout, Algebra, ContainerPolicy > >
Specialization of nda::is_regular_v for nda::basic_array.
constexpr char get_algebra< basic_array_view< ValueType, Rank, Layout, Algebra, AccessorPolicy, OwningPolicy > >
Specialization of nda::get_algebra for nda::basic_array_view types.
constexpr char get_algebra< basic_array< ValueType, Rank, Layout, Algebra, ContainerPolicy > >
Specialization of nda::get_algebra for nda::basic_array types.
constexpr uint64_t static_extents(int i0, Is... is)
Encode the given shape into a single integer using the nda::encode function.
constexpr char get_algebra< expr_unary< OP, A > >
Specialization of nda::get_algebra for nda::expr_unary types.
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.
constexpr char get_algebra< expr< OP, L, R > >
Specialization of nda::get_algebra for nda::expr types.
__inline__ void clef_auto_assign(expr< tags::terminal, T > const &ex, RHS &&rhs)
Overload of clef_auto_assign function for terminal expressions.
__inline__ void clef_auto_assign(std::reference_wrapper< T > wrapper, RHS &&rhs)
Overload of clef_auto_assign function for std::reference_wrapper objects.
__inline__ void operator<<(expr< tags::function, F, placeholder< Is >... > const &ex, RHS &&rhs)
Assign values to the underlying object of a lazy function call expression.
__inline__ void clef_auto_assign_subscript(std::reference_wrapper< T > wrapper, RHS &&rhs)
Overload of clef_auto_assign_subscript function for std::reference_wrapper objects.
__inline__ void clef_auto_assign_subscript(expr< Tag, Childs... > const &ex, RHS const &rhs)
Overload of clef_auto_assign_subscript function for generic expressions.
__inline__ void clef_auto_assign_subscript(expr< tags::terminal, T > const &ex, RHS &&rhs)
Overload of clef_auto_assign_subscript function for terminal expressions.
__inline__ void clef_auto_assign(expr< Tag, Childs... > const &ex, RHS const &rhs)
Overload of clef_auto_assign function for generic expressions.
void clef_auto_assign(A &&a, F &&f)
Overload of nda::clef::clef_auto_assign function for nda::Array objects.
__inline__ void operator<<(expr< tags::subscript, T, placeholder< Is >... > const &ex, RHS &&rhs)
Assign values to the underlying object of a lazy subscript expression.
__inline__ decltype(auto) eval(T const &obj, Pairs &&...pairs)
Generic function to evaluate expressions and other types.
Definition eval.hpp:197
__inline__ auto make_function(T &&obj, Phs...)
Factory function for nda::clef::make_fun_impl objects.
Definition function.hpp:100
__inline__ auto if_else(C &&c, A &&a, B &&b)
Create a lazy ternary (if-else) expression.
#define CLEF_OPERATION(TAG, OP)
auto make_expr(T &&t)
Create a terminal expression node of an object.
Definition make_lazy.hpp:45
__inline__ auto op_dispatch(std::true_type, Args &&...args)
Dispatch operations containing at least one lazy operand.
__inline__ decltype(auto) op_dispatch(std::false_type, Args &&...args)
Dispatch operations containing only non-lazy operands.
auto make_expr_subscript(T &&t, Args &&...args)
Create a subscript expression from an object and a list of arguments.
Definition make_lazy.hpp:93
auto make_expr_call(F &&f, Args &&...args)
Create a function call expression from a callable object and a list of arguments.
Definition make_lazy.hpp:74
auto make_expr_from_clone(T &&t)
Create a terminal expression node of an object.
Definition make_lazy.hpp:57
constexpr bool is_clef_expression
Alias template for nda::clef::is_any_lazy.
Definition utils.hpp:161
constexpr bool is_lazy
Constexpr variable that is true if the type T is a lazy type.
Definition utils.hpp:153
constexpr bool force_copy_in_expr
Constexpr variable that is true if objects of type T should be forced to be copied into an expression...
Definition utils.hpp:137
constexpr bool is_function
Constexpr variable that is true if the type T is an nda::clef::make_fun_impl type.
Definition utils.hpp:165
constexpr bool is_any_lazy
Constexpr variable that is true if any of the given types is lazy.
Definition utils.hpp:157
constexpr uint64_t C_stride_order
C/Row-major stride order.
Definition idx_map.hpp:65
constexpr uint64_t Fortran_stride_order
Fortran/Column-major stride order.
Definition idx_map.hpp:57
__inline__ decltype(auto) slice_idx_map(idx_map< R, SE, SO, LP > const &idxm, Args const &...args)
Determine the resulting nda::idx_map when taking a slice of a given nda::idx_map.
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_strided_1d(layout_prop_e lp)
Checks if a layout property has the strided_1d property.
Definition traits.hpp:266
auto get_block_layout(A const &a)
Check if a given nda::MemoryArray has a block-strided layout.
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
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 bool have_host_compatible_addr_space
Constexpr variable that is true if all given types have an address space compatible with Host.
static constexpr bool have_compatible_addr_space
Constexpr variable that is true if all given types have compatible address spaces.
constexpr AddressSpace combine
Promotion rules for nda::mem::AddressSpace values.
static constexpr bool have_device_compatible_addr_space
Constexpr variable that is true if all given types have an address space compatible with Device.
static constexpr bool on_device
Constexpr variable that is true if all given types have a Device address space.
static constexpr bool on_unified
Constexpr variable that is true if all given types have a Unified address space.
static constexpr AddressSpace get_addr_space
Variable template providing the address space for different types.
static constexpr bool on_host
Constexpr variable that is true if all given types have a Host address space.
constexpr AddressSpace common_addr_space
Get common address space for a number of given nda::MemoryArray types.
static const auto check_adr_sp_valid
Check validity of a set of nda::mem::AddressSpace values.
static constexpr bool have_same_addr_space
Constexpr variable that is true if all given types have the same address space.
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 std::array< int, N > transposition(int i, int j)
Get the permutation representing a single given transposition.
constexpr std::array< Int, N > inverse(std::array< Int, N > const &p)
Inverse of a permutation.
constexpr std::array< int, N > decode(uint64_t binary_representation)
Decode a uint64_t into a std::array<int, N>.
constexpr bool is_valid(std::array< Int, N > const &p)
Check if a given array is a valid permutation.
constexpr std::array< T, N > apply_inverse(std::array< Int, N > const &p, std::array< T, N > const &a)
Apply the inverse of a permutation to a std::array.
constexpr std::array< int, N > identity()
Get the identity permutation.
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< int, N > cycle(int p, int pos=N)
Perform a forward (partial) cyclic permutation of the identity p times.
constexpr std::array< Int, N > compose(std::array< Int, N > const &p1, std::array< Int, N > const &p2)
Composition of two permutations.
constexpr std::array< T, N > apply(std::array< Int, N > const &p, std::array< T, N > const &a)
Apply a permutation to a std::array.
constexpr std::array< T, R > operator*(std::array< T, R > const &lhs, std::array< T, R > const &rhs)
Multiply two std::array objects element-wise.
Definition array.hpp:115
constexpr std::array< T, R - N > front_mpop(std::array< T, R > const &a)
Make a new std::array by popping the first N elements of an existing std::array.
Definition array.hpp:278
constexpr std::array< T, R+1 > append(std::array< T, R > const &a, U const &x)
Make a new std::array by appending one element at the end to an existing std::array.
Definition array.hpp:214
constexpr std::array< T, R+1 > front_append(std::array< T, R > const &a, U const &x)
Make a new std::array by prepending one element at the front to an existing std::array.
Definition array.hpp:232
constexpr std::array< T, R - 1 > pop(std::array< T, R > const &a)
Make a new std::array by popping the last element of an existing std::array.
Definition array.hpp:264
constexpr std::array< T, R > operator+(std::array< T, R > const &lhs, std::array< T, R > const &rhs)
Add two std::array objects element-wise.
Definition array.hpp:83
constexpr std::array< T, R > operator-(std::array< T, R > const &a)
Negate a std::array element-wise (unary minus).
Definition array.hpp:130
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:309
constexpr std::array< T, R > operator*(T s, std::array< T, R > const &a)
Multiply a scalar and a std::array element-wise.
Definition array.hpp:146
constexpr std::vector< T > to_vector(std::array< T, R > const &a)
Convert a std::array to a std::vector.
Definition array.hpp:197
constexpr std::array< T, R > make_initialized_array(T v)
Create a new std::array object initialized with a specific value.
Definition array.hpp:165
constexpr auto sum(std::array< T, R > const &a)
Calculate the sum of all elements in a std::array.
Definition array.hpp:326
std::string to_string(std::array< T, R > const &a)
Get a string representation of a std::array.
Definition array.hpp:65
constexpr std::array< T, R > operator-(std::array< T, R > const &lhs, std::array< T, R > const &rhs)
Subtract two std::array objects element-wise.
Definition array.hpp:99
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:181
constexpr std::array< T, R - 1 > front_pop(std::array< T, R > const &a)
Make a new std::array by popping the first element of an existing std::array.
Definition array.hpp:293
constexpr auto product(std::array< T, R > const &a)
Calculate the product of all elements in a std::array.
Definition array.hpp:345
constexpr auto dot_product(std::array< T, R > const &a1, std::array< U, R > const &a2)
Calculate the dot product of two std::array objects.
Definition array.hpp:366
constexpr std::array< T, R - N > mpop(std::array< T, R > const &a)
Make a new std::array by popping the last N elements of an existing std::array.
Definition array.hpp:249
#define EXPECTS(X)
Definition macros.hpp:59
#define FORCEINLINE
Definition macros.hpp:41
#define EXPECTS_WITH_MESSAGE(X,...)
Definition macros.hpp:75
#define ENSURES(X)
Definition macros.hpp:69
#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
Strided (non-contiguous) layout policy with C-order (row-major order).
Definition policies.hpp:79
Contiguous layout policy with Fortran-order (column-major order).
Definition policies.hpp:63
Strided (non-contiguous) layout policy with Fortran-order (column-major order).
Definition policies.hpp:95
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
static constexpr bool is_lazy
Constexpr variable that is true if any of the evaluators of the child nodes is lazy.
Definition eval.hpp:150
__inline__ decltype(auto) operator()(expr< Tag, Childs... > const &ex, Pairs &...pairs) const
Evaluate the given expression by applying the given nda::clef::pair objects.
Definition eval.hpp:170
__inline__ decltype(auto) operator()(make_fun_impl< T, Is... > const &f, Pairs &...pairs) const
Evaluate the nda::clef::make_fun_impl object.
Definition function.hpp:133
static constexpr bool is_lazy
Constexpr variable that is true if all the placeholders are assigned a value.
Definition function.hpp:120
static constexpr bool is_lazy
Constexpr variable that is true if the there is no nda::clef::pair containing an nda::clef::placehold...
Definition eval.hpp:92
__inline__ decltype(auto) operator()(placeholder< N >, pair< Is, Ts > &...pairs) const
Evaluate the placeholder.
Definition eval.hpp:101
static constexpr bool is_lazy
Constexpr variable that is always false.
Definition eval.hpp:126
__inline__ decltype(auto) operator()(std::reference_wrapper< T > const &wrapper, Pairs const &...pairs) const
Evaluate the std::reference_wrapper by redirecting the evaluation to the object contained in the wrap...
Definition eval.hpp:135
Generic evaluator for types which do not have a specialized evaluator.
Definition eval.hpp:55
__inline__ T const & operator()(T const &t, Pairs &...) const
Evaluate the object and ignore all given nda::clef::pair objects.
Definition eval.hpp:65
static constexpr bool is_lazy
Constexpr variable that is true if the type T is lazy.
Definition eval.hpp:57
Single node of the expression tree.
expr & operator=(expr const &)=delete
Copy assignment operator is deleted.
expr(expr &&ex) noexcept
Move constructor simply moves the child nodes from the source expression.
auto operator[](Args &&...args) const
Subscript operator.
expr & operator=(expr &&)=default
Default move assignment operator.
expr(expr const &)=default
Default copy constructor.
expr(Tag, Us &&...us)
Construct an expression node with a given tag and child nodes.
childs_t childs
Child nodes of the current expression node.
auto operator()(Args &&...args) const
Function call operator.
Helper struct to simplify calls to nda::clef::eval.
Definition function.hpp:52
T obj
Object to be evaluated.
Definition function.hpp:54
__inline__ decltype(auto) operator()(Args &&...args) const
Function call operator.
Definition function.hpp:68
__inline__ decltype(auto) operator()(F &&f, Args &&...args) const
Perform a function call operation.
Definition operation.hpp:95
__inline__ A operator()(C const &c, A const &a, B const &b) const
Perform a ternary (if-else) operation.
__inline__ decltype(auto) operator()(F &&f, Args &&...args) const
Perform a subscript operation.
__inline__ L operator()(L &&l) const
Perform a terminal operation.
Definition operation.hpp:77
A pair consisting of a placeholder and its assigned value.
T rhs
Value assigned to the placeholder (can be an lvalue reference).
static constexpr int p
Integer label of the placeholder.
A placeholder is an empty struct, labelled by an int.
static constexpr int index
Integer label.
auto operator[](T &&t) const
Subscript operator.
pair< N, RHS > operator=(RHS &&rhs) const
Assign a value to the placeholder.
auto operator()(Args &&...args) const
Function call operator.
Tag for binary operator expressions.
Tag for function call expressions.
Tag for conditional expressions.
Tag for subscript expressions.
Tag to indicate a terminal node in the expression tree.
Tag for unary operator expressions.
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
Mimics Python's ... syntax.
Definition range.hpp:49
A lazy function call expression on arrays/views.
Definition map.hpp:90
Lazy unary expression for nda::Array types.
Lazy binary expression for nda::ArrayOrScalar types.
Memory policy using an nda::mem::handle_heap.
Definition policies.hpp:44
Stores information about the memory layout and the stride order of an array/view.
Definition traits.hpp:295
Memory block consisting of a pointer and its size.
char * ptr
Pointer to the memory block.
size_t s
Size of the memory block in bytes.
A non-owning handle for a memory block on the heap.
Definition handle.hpp:858
A handle for a memory block on the heap.
Definition handle.hpp:99
A handle for a memory block on the heap with shared ownership.
Definition handle.hpp:754
A handle for a memory block on the heap or stack depending on the size of the data.
Definition handle.hpp:492
A handle for a memory block on the stack.
Definition handle.hpp:359
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
Memory policy using an nda::mem::handle_shared.
Definition policies.hpp:94
Memory policy using an nda::mem::handle_sso.
Definition policies.hpp:70
Memory policy using an nda::mem::handle_stack.
Definition policies.hpp:84