Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
block_tensor_storage.hpp
Go to the documentation of this file.
1
7#pragma once
8
11#include <uni20/core/types.hpp>
19
20#include <algorithm>
21#include <array>
22#include <concepts>
23#include <cstddef>
24#include <limits>
25#include <numeric>
26#include <span>
27#include <stdexcept>
28#include <type_traits>
29#include <utility>
30#include <vector>
31
32namespace uni20
33{
34
38
42
45template <class Storage>
46concept BlockTensorStorage = requires {
47 typename Storage::leaf_storage_policy;
48 typename Storage::backend_selector_type;
49 typename Storage::block_execution_policy;
50 { Storage::stores_all_legal_blocks } -> std::convertible_to<bool>;
51 { Storage::is_distributed } -> std::convertible_to<bool>;
52 { Storage::backend_selector() } -> std::same_as<typename Storage::backend_selector_type>;
53};
54
57template <class Storage>
58concept SparseBlockStorage = BlockTensorStorage<Storage> && !Storage::stores_all_legal_blocks;
59
62template <class Storage>
63concept CompleteBlockStorage = BlockTensorStorage<Storage> && Storage::stores_all_legal_blocks;
64
70template <class Storage>
72 { Storage::stores_diagonal_blocks } -> std::convertible_to<bool>;
73} && Storage::stores_diagonal_blocks;
74
80template <class Storage, typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
83 requires(typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>& storage,
84 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder> const& const_storage,
85 std::array<std::size_t, DenseBlockOrder> const& extents) {
86 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::mutable_block_type;
87 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::const_block_type;
88 { const_storage.size() } -> std::same_as<std::size_t>;
89 { const_storage.keys() } -> std::same_as<std::span<BlockKey<KeyCoordinateCount> const>>;
90 {
91 storage.block(std::size_t{}, extents)
92 }
93 -> std::same_as<typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::mutable_block_type>;
94 {
95 const_storage.block(std::size_t{}, extents)
96 } -> std::same_as<typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::const_block_type>;
97 } &&
99 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::mutable_block_type,
100 DenseBlockOrder> &&
102 DenseBlockOrder> &&
103 std::same_as<tensor_element_t<
104 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::mutable_block_type>,
105 T> &&
106 std::same_as<typename tensor_mdspec_t<typename Storage::template storage_t<
107 T, KeyCoordinateCount, DenseBlockOrder>::const_block_type>::element_type,
108 T const>;
109
117template <class Storage, typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
120
126template <class Storage, typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
130 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::mutable_block_type,
131 DenseBlockOrder> &&
133 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::const_block_type,
134 DenseBlockOrder>;
135
141template <class Storage, typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
144 requires(typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>& storage,
145 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder> const& const_storage) {
146 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::block_value_type;
147 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::async_block_type;
148 {
149 storage.async_block(std::size_t{})
150 }
151 -> std::same_as<typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::async_block_type&>;
152 {
153 const_storage.async_block(std::size_t{})
154 } -> std::same_as<
155 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::async_block_type const&>;
156 } &&
157 std::same_as<
158 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::async_block_type,
161 typename Storage::template storage_t<T, KeyCoordinateCount, DenseBlockOrder>::block_value_type,
162 DenseBlockOrder>;
163
167template <class Storage, typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
170
171namespace detail
172{
173
174template <std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder> struct BlockSpec
175{
176 BlockKey<KeyCoordinateCount> key;
177 std::array<std::size_t, DenseBlockOrder> extents;
178};
179
180template <class Tensor, std::size_t Order, std::size_t... I>
181auto make_block_tensor(std::array<std::size_t, Order> const& extents, StorageInitialization initialization,
182 std::index_sequence<I...>) -> Tensor
183{
184 if (initialization == StorageInitialization::Uninitialized)
185 return Tensor(uninitialized, static_cast<index_type>(extents[I])...);
186 return Tensor(static_cast<index_type>(extents[I])...);
187}
188
189template <class Tensor, std::size_t Order>
190auto make_block_tensor(std::array<std::size_t, Order> const& extents, StorageInitialization initialization) -> Tensor
191{
192 return make_block_tensor<Tensor>(extents, initialization, std::make_index_sequence<Order>{});
193}
194
195template <class Extents, std::size_t Order, std::size_t... I>
196auto make_extents(std::array<std::size_t, Order> const& extents, std::index_sequence<I...>) -> Extents
197{
198 return Extents(static_cast<typename Extents::index_type>(extents[I])...);
199}
200
201template <class Extents, std::size_t Order> auto make_extents(std::array<std::size_t, Order> const& extents) -> Extents
202{
203 return make_extents<Extents>(extents, std::make_index_sequence<Order>{});
204}
205
206inline auto checked_block_size(std::span<std::size_t const> extents) -> std::size_t
207{
208 std::size_t size = 1;
209 for (std::size_t const extent : extents)
210 {
211 if (extent != 0 && size > std::numeric_limits<std::size_t>::max() / extent)
212 {
213 throw std::length_error("BlockTensor block size overflows size_t");
214 }
215 size *= extent;
216 }
217 return size;
218}
219
220template <std::size_t Rank>
221constexpr auto diagonal_extent(std::array<std::size_t, Rank> const& extents) noexcept -> std::size_t
222{
223 if constexpr (Rank == 0)
224 {
225 return 1;
226 }
227 else
228 {
229 return *std::ranges::min_element(extents);
230 }
231}
232
233template <class Storage, class T>
234auto make_storage(std::size_t size, StorageInitialization initialization) -> typename Storage::template storage_t<T>
235{
236 using storage_type = typename Storage::template storage_t<T>;
237 if constexpr (requires { Storage::template make_storage<T>(size, initialization); })
238 {
239 return Storage::template make_storage<T>(size, initialization);
240 }
241 else
242 {
243 // Legacy contiguous host containers can initialize through their live elements.
244 // Descriptor-backed or opaque storage must provide an initialization-aware factory.
245 auto storage = [&] {
246 if constexpr (std::default_initializable<storage_type> && requires(storage_type& value) { value.resize(size); })
247 {
248 storage_type result;
249 result.resize(size);
250 return result;
251 }
252 else
253 {
254 return storage_type(size);
255 }
256 }();
257 initialize_host_elements(storage.data(), size, initialization);
258 return storage;
259 }
260}
261
262template <class Storage, class T>
263auto make_storage_like(typename Storage::template storage_t<T> const& prototype, std::size_t size,
264 StorageInitialization initialization) -> typename Storage::template storage_t<T>
265{
266 if constexpr (requires {
267 {
268 Storage::template make_storage_like<T>(prototype, size, initialization)
269 } -> std::same_as<typename Storage::template storage_t<T>>;
270 })
271 {
272 return Storage::template make_storage_like<T>(prototype, size, initialization);
273 }
274 else
275 {
276 return make_storage<Storage, T>(size, initialization);
277 }
278}
279
280template <class Storage, class T, class = void> struct PackedStorageType
281{
282 using type = typename Storage::template storage_t<T>;
283};
284
285template <class Storage, class T>
286struct PackedStorageType<Storage, T, std::void_t<typename Storage::template packed_storage_t<T>>>
287{
288 using type = typename Storage::template packed_storage_t<T>;
289};
290
291template <class Storage, class T> using packed_storage_t = typename PackedStorageType<Storage, T>::type;
292
293template <class Storage, class T>
294auto make_packed_storage(std::size_t size, std::span<std::size_t const> offsets,
295 StorageInitialization initialization) -> packed_storage_t<Storage, T>
296{
297 if constexpr (requires {
298 {
299 Storage::template make_packed_storage<T>(size, offsets, initialization)
300 } -> std::same_as<packed_storage_t<Storage, T>>;
301 })
302 {
303 return Storage::template make_packed_storage<T>(size, offsets, initialization);
304 }
305 else
306 {
307 return make_storage<Storage, T>(size, initialization);
308 }
309}
310
311template <class Storage, class T>
312auto make_packed_storage_like(packed_storage_t<Storage, T> const& prototype, std::size_t size,
313 std::span<std::size_t const> offsets,
314 StorageInitialization initialization) -> packed_storage_t<Storage, T>
315{
316 if constexpr (requires {
317 {
318 Storage::template make_packed_storage_like<T>(prototype, size, offsets, initialization)
319 } -> std::same_as<packed_storage_t<Storage, T>>;
320 })
321 {
322 return Storage::template make_packed_storage_like<T>(prototype, size, offsets, initialization);
323 }
324 else
325 {
326 return make_storage_like<Storage, T>(prototype, size, initialization);
327 }
328}
329
330template <class Storage, class Buffer>
331decltype(auto) make_packed_data_descriptor(Buffer& buffer, std::size_t ordinal, std::size_t offset)
332{
333 if constexpr (requires { Storage::make_packed_data_descriptor(buffer, ordinal); })
334 return Storage::make_packed_data_descriptor(buffer, ordinal);
335 else
336 return Storage::make_data_descriptor(buffer).offset_by(offset);
337}
338
339template <class Storage, class T, class Buffer>
340void initialize_packed_padding(Buffer& buffer, std::span<std::size_t const> offsets,
341 std::span<std::size_t const> block_ends)
342{
343 if constexpr (requires { Storage::initialize_packed_padding(buffer, offsets, block_ends); })
344 {
345 Storage::initialize_packed_padding(buffer, offsets, block_ends);
346 }
347 else
348 {
349 static_assert(
350 requires { Storage::make_handle(buffer); },
351 "aligned packed storage must provide immediate access or initialize_packed_padding");
352 auto* data = Storage::make_handle(buffer);
353 for (std::size_t ordinal = 0; ordinal < block_ends.size(); ++ordinal)
354 std::fill(data + block_ends[ordinal], data + offsets[ordinal + 1], zero_value<T>());
355 }
356}
357
358template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder, class LeafStorage>
359class SeparateSparseBlockStorageData {
360 public:
361 using key_type = BlockKey<KeyCoordinateCount>;
362 using block_type = ColumnMajorTensor<T, DenseBlockOrder, LeafStorage>;
363 using mutable_mdspan_type = typename block_type::mdspan_type;
364 using const_mdspan_type = typename block_type::const_mdspan_type;
365 using mutable_block_type = MdspecTensorView<mutable_mdspan_type, const_mdspan_type, LeafStorage>;
366 using const_block_type = MdspecTensorView<const_mdspan_type, const_mdspan_type, LeafStorage>;
367
369 "separate sparse block storage currently requires immediate leaf access");
370
371 explicit SeparateSparseBlockStorageData(std::vector<BlockSpec<KeyCoordinateCount, DenseBlockOrder>> const& specs,
373 {
374 keys_.reserve(specs.size());
375 blocks_.reserve(specs.size());
376 for (auto const& spec : specs)
377 {
378 keys_.push_back(spec.key);
379 blocks_.push_back(make_block_tensor<block_type>(spec.extents, initialization));
380 }
381 }
382
383 auto size() const noexcept -> std::size_t { return keys_.size(); }
384 auto keys() const noexcept -> std::span<key_type const> { return keys_; }
385
386 auto block(std::size_t ordinal, std::array<std::size_t, DenseBlockOrder> const&) -> mutable_block_type
387 {
388 return mutable_block_type{blocks_[ordinal].mdspan(), std::as_const(blocks_[ordinal]).mdspan()};
389 }
390
391 auto block(std::size_t ordinal, std::array<std::size_t, DenseBlockOrder> const&) const -> const_block_type
392 {
393 auto span = blocks_[ordinal].mdspan();
394 return const_block_type{span, span};
395 }
396
397 private:
398 std::vector<key_type> keys_;
399 std::vector<block_type> blocks_;
400};
401
402template <class LeafStorage, typename T>
403concept ImmediatePackedLeafStorage =
404 std::default_initializable<tensor_accessor_factory_t<LeafStorage>> &&
405 requires(typename LeafStorage::template storage_t<T>& buffer,
406 typename LeafStorage::template storage_t<T> const& const_buffer,
407 tensor_accessor_factory_t<LeafStorage> const& accessor_factory) {
408 {
409 LeafStorage::make_handle(buffer)
410 }
411 -> std::convertible_to<typename tensor_accessor_factory_t<LeafStorage>::template accessor_t<T>::data_handle_type>;
412 {
413 LeafStorage::make_handle(const_buffer)
414 } -> std::convertible_to<
415 typename tensor_accessor_factory_t<LeafStorage>::template accessor_t<T const>::data_handle_type>;
416 {
417 accessor_factory.template make_accessor<T>(buffer)
418 } -> std::same_as<typename tensor_accessor_factory_t<LeafStorage>::template accessor_t<T>>;
419 {
420 accessor_factory.template make_accessor<T const>(const_buffer)
421 } -> std::same_as<typename tensor_accessor_factory_t<LeafStorage>::template accessor_t<T const>>;
422 };
423
424template <typename T, std::size_t DenseBlockOrder, class LeafStorage,
425 bool Immediate = ImmediatePackedLeafStorage<LeafStorage, T>>
426struct PackedBlockViewTraits;
427
428template <typename T, std::size_t DenseBlockOrder, class LeafStorage>
429struct PackedBlockViewTraits<T, DenseBlockOrder, LeafStorage, true>
430{
431 using buffer_type = packed_storage_t<LeafStorage, T>;
432 using extents_type = stdex::dextents<index_type, DenseBlockOrder>;
433 using mapping_type = typename ColumnMajor::template mapping<extents_type>;
434 using accessor_factory_type = tensor_accessor_factory_t<LeafStorage>;
435 using accessor_type = typename accessor_factory_type::template accessor_t<T>;
436 using const_accessor_type = typename accessor_factory_type::template accessor_t<T const>;
437 using mutable_mdspec_type = stdex::mdspan<T, extents_type, ColumnMajor, accessor_type>;
438 using const_mdspec_type = stdex::mdspan<T const, extents_type, ColumnMajor, const_accessor_type>;
439 using mutable_block_type = MdspecTensorView<mutable_mdspec_type, const_mdspec_type, LeafStorage>;
440 using const_block_type = MdspecTensorView<const_mdspec_type, const_mdspec_type, LeafStorage>;
441
442 static auto mutable_block(buffer_type& buffer, std::size_t offset,
443 extents_type const& extents) -> mutable_block_type
444 {
445 accessor_factory_type accessor_factory;
446 auto accessor = accessor_factory.template make_accessor<T>(buffer);
447 auto const_accessor = accessor_factory.template make_accessor<T const>(std::as_const(buffer));
448 auto mutable_handle = accessor.offset(LeafStorage::make_handle(buffer), offset);
449 auto const_handle = const_accessor.offset(LeafStorage::make_handle(std::as_const(buffer)), offset);
450 return mutable_block_type{mutable_mdspec_type{mutable_handle, mapping_type(extents), accessor},
451 const_mdspec_type{const_handle, mapping_type(extents), const_accessor}};
452 }
453
454 static auto const_block(buffer_type const& buffer, std::size_t offset,
455 extents_type const& extents) -> const_block_type
456 {
457 accessor_factory_type accessor_factory;
458 auto accessor = accessor_factory.template make_accessor<T const>(buffer);
459 auto handle = accessor.offset(LeafStorage::make_handle(buffer), offset);
460 auto span = const_mdspec_type{handle, mapping_type(extents), accessor};
461 return const_block_type{span, span};
462 }
463};
464
465template <typename T, std::size_t DenseBlockOrder, class LeafStorage>
466struct PackedBlockViewTraits<T, DenseBlockOrder, LeafStorage, false>
467{
468 using buffer_type = packed_storage_t<LeafStorage, T>;
469 using extents_type = stdex::dextents<index_type, DenseBlockOrder>;
470 using mapping_type = typename ColumnMajor::template mapping<extents_type>;
471 using accessor_factory_type = tensor_accessor_factory_t<LeafStorage>;
472 using accessor_type = tensor_device_accessor_t<accessor_factory_type, T>;
473 using const_accessor_type = tensor_device_accessor_t<accessor_factory_type, T const>;
474 using descriptor_type =
475 decltype(make_packed_data_descriptor<LeafStorage>(std::declval<buffer_type&>(), std::size_t{}, std::size_t{}));
476 using const_descriptor_type = decltype(make_packed_data_descriptor<LeafStorage>(std::declval<buffer_type const&>(),
477 std::size_t{}, std::size_t{}));
478 using mutable_mdspec_type = mdspec<T, extents_type, ColumnMajor, accessor_type, descriptor_type>;
479 using const_mdspec_type = mdspec<T const, extents_type, ColumnMajor, const_accessor_type, const_descriptor_type>;
480 using mutable_block_type = MdspecTensorView<mutable_mdspec_type, const_mdspec_type, LeafStorage>;
481 using const_block_type = MdspecTensorView<const_mdspec_type, const_mdspec_type, LeafStorage>;
482
483 static_assert(std::default_initializable<accessor_factory_type>,
484 "packed descriptor-backed storage requires a default-constructible accessor factory");
485 template <class ElementType>
486 static auto
487 device_accessor(buffer_type const& buffer) -> tensor_device_accessor_t<accessor_factory_type, ElementType>
488 {
489 accessor_factory_type accessor_factory;
490 if constexpr (requires { accessor_factory.template make_device_accessor<ElementType>(buffer); })
491 return accessor_factory.template make_device_accessor<ElementType>(buffer);
492 else
493 return accessor_factory.template make_accessor<ElementType>(buffer);
494 }
495
496 static auto mutable_block(buffer_type& buffer, std::size_t offset, extents_type const& extents,
497 std::size_t ordinal) -> mutable_block_type
498 {
499 auto descriptor = make_packed_data_descriptor<LeafStorage>(buffer, ordinal, offset);
500 auto const_descriptor = make_packed_data_descriptor<LeafStorage>(std::as_const(buffer), ordinal, offset);
501 return mutable_block_type{
502 mutable_mdspec_type{std::move(descriptor), mapping_type(extents), device_accessor<T>(buffer)},
503 const_mdspec_type{std::move(const_descriptor), mapping_type(extents), device_accessor<T const>(buffer)}};
504 }
505
506 static auto const_block(buffer_type const& buffer, std::size_t offset, extents_type const& extents,
507 std::size_t ordinal) -> const_block_type
508 {
509 auto descriptor = make_packed_data_descriptor<LeafStorage>(buffer, ordinal, offset);
510 auto span = const_mdspec_type{std::move(descriptor), mapping_type(extents), device_accessor<T const>(buffer)};
511 return const_block_type{span, span};
512 }
513};
514
515template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder, class LeafStorage,
516 std::size_t BlockAlignment>
517class PackedBlockStorageData {
518 public:
519 using key_type = BlockKey<KeyCoordinateCount>;
520 using buffer_type = packed_storage_t<LeafStorage, T>;
521 using view_traits = PackedBlockViewTraits<T, DenseBlockOrder, LeafStorage>;
522 using extents_type = typename view_traits::extents_type;
523 using mutable_block_type = typename view_traits::mutable_block_type;
524 using const_block_type = typename view_traits::const_block_type;
525
526 static_assert(BlockAlignment > 0, "packed block alignment must be positive");
527 static_assert(
528 [] {
529 if constexpr (BlockAlignment == 1)
530 return true;
531 else if constexpr (requires { LeafStorage::allocation_alignment; })
532 return LeafStorage::allocation_alignment % BlockAlignment == 0;
533 else
534 return false;
535 }(),
536 "nontrivial packed block alignment must divide the leaf allocation alignment");
537 explicit PackedBlockStorageData(std::vector<BlockSpec<KeyCoordinateCount, DenseBlockOrder>> const& specs,
539 : PackedBlockStorageData(make_layout(specs), initialization)
540 {}
541
543 template <class Context>
544 requires requires(Context& context, std::size_t size, std::span<std::size_t const> offsets,
545 StorageInitialization initialization) {
546 {
547 LeafStorage::template make_packed_storage<T>(context, size, offsets, initialization)
548 } -> std::same_as<buffer_type>;
549 }
550 explicit PackedBlockStorageData(std::vector<BlockSpec<KeyCoordinateCount, DenseBlockOrder>> const& specs,
551 Context& context,
553 : PackedBlockStorageData(make_layout(specs), context, initialization)
554 {}
555
556 auto size() const noexcept -> std::size_t { return keys_.size(); }
557 auto keys() const noexcept -> std::span<key_type const> { return keys_; }
558
559 auto block(std::size_t ordinal, std::array<std::size_t, DenseBlockOrder> const& extents) -> mutable_block_type
560 {
561 if constexpr (ImmediatePackedLeafStorage<LeafStorage, T>)
562 return view_traits::mutable_block(buffer_, offsets_[ordinal], make_extents<extents_type>(extents));
563 else
564 return view_traits::mutable_block(buffer_, offsets_[ordinal], make_extents<extents_type>(extents), ordinal);
565 }
566
567 auto block(std::size_t ordinal, std::array<std::size_t, DenseBlockOrder> const& extents) const -> const_block_type
568 {
569 if constexpr (ImmediatePackedLeafStorage<LeafStorage, T>)
570 return view_traits::const_block(buffer_, offsets_[ordinal], make_extents<extents_type>(extents));
571 else
572 return view_traits::const_block(buffer_, offsets_[ordinal], make_extents<extents_type>(extents), ordinal);
573 }
574
575 auto buffer() noexcept -> buffer_type& { return buffer_; }
576 auto buffer() const noexcept -> buffer_type const& { return buffer_; }
577 auto offsets() const noexcept -> std::span<std::size_t const> { return offsets_; }
578
580 decltype(auto) allocation_context() const noexcept
581 requires requires(buffer_type const& buffer) { LeafStorage::allocation_context(buffer); }
582 {
583 return LeafStorage::allocation_context(buffer_);
584 }
585
589 auto block_ends() const noexcept -> std::span<std::size_t const> { return block_ends_; }
590
592 [[nodiscard]] bool has_padding() const noexcept
593 {
594 for (std::size_t ordinal = 0; ordinal < block_ends_.size(); ++ordinal)
595 if (block_ends_[ordinal] != offsets_[ordinal + 1]) return true;
596 return false;
597 }
598
602 [[nodiscard]] auto
603 allocate_like(StorageInitialization initialization = StorageInitialization::Zero) const -> PackedBlockStorageData
604 {
605 return PackedBlockStorageData(Layout{.keys = keys_, .offsets = offsets_, .block_ends = block_ends_}, buffer_,
606 initialization);
607 }
608
609 private:
610 struct Layout
611 {
612 std::vector<key_type> keys;
613 std::vector<std::size_t> offsets;
614 std::vector<std::size_t> block_ends;
615 };
616
617 static constexpr std::size_t alignment_elements = BlockAlignment / std::gcd(BlockAlignment, sizeof(T));
618
619 static auto align_offset(std::size_t offset) -> std::size_t
620 {
621 std::size_t const remainder = offset % alignment_elements;
622 if (remainder == 0) return offset;
623 std::size_t const padding = alignment_elements - remainder;
624 if (offset > std::numeric_limits<std::size_t>::max() - padding)
625 throw std::length_error("packed BlockTensor alignment overflows size_t");
626 return offset + padding;
627 }
628
629 static auto make_layout(std::vector<BlockSpec<KeyCoordinateCount, DenseBlockOrder>> const& specs) -> Layout
630 {
631 Layout layout;
632 layout.keys.reserve(specs.size());
633 layout.offsets.reserve(specs.size() + 1);
634 layout.block_ends.reserve(specs.size());
635
636 std::size_t end_offset = 0;
637
638 for (auto const& spec : specs)
639 {
640 std::size_t const block_offset = align_offset(end_offset);
641 layout.keys.push_back(spec.key);
642 layout.offsets.push_back(block_offset);
643 std::size_t const block_size = checked_block_size(spec.extents);
644 if (block_offset > std::numeric_limits<std::size_t>::max() - block_size)
645 {
646 throw std::length_error("packed BlockTensor size overflows size_t");
647 }
648 end_offset = block_offset + block_size;
649 layout.block_ends.push_back(end_offset);
650 }
651 layout.offsets.push_back(end_offset);
652 return layout;
653 }
654
655 explicit PackedBlockStorageData(Layout layout, StorageInitialization initialization)
656 : keys_(std::move(layout.keys)), offsets_(std::move(layout.offsets)), block_ends_(std::move(layout.block_ends)),
657 buffer_(make_packed_storage<LeafStorage, T>(offsets_.back(), offsets_, initialization))
658 {
659 if constexpr (BlockAlignment > 1)
660 {
661 if (initialization == StorageInitialization::Uninitialized)
662 initialize_packed_padding<LeafStorage, T>(buffer_, offsets_, block_ends_);
663 }
664 }
665
666 PackedBlockStorageData(Layout layout, buffer_type const& prototype, StorageInitialization initialization)
667 : keys_(std::move(layout.keys)), offsets_(std::move(layout.offsets)), block_ends_(std::move(layout.block_ends)),
668 buffer_(make_packed_storage_like<LeafStorage, T>(prototype, offsets_.back(), offsets_, initialization))
669 {
670 if constexpr (BlockAlignment > 1)
671 {
672 if (initialization == StorageInitialization::Uninitialized)
673 initialize_packed_padding<LeafStorage, T>(buffer_, offsets_, block_ends_);
674 }
675 }
676
677 template <class Context>
678 requires requires(Context& context, std::size_t size, std::span<std::size_t const> offsets,
679 StorageInitialization initialization) {
680 {
681 LeafStorage::template make_packed_storage<T>(context, size, offsets, initialization)
682 } -> std::same_as<buffer_type>;
683 }
684 PackedBlockStorageData(Layout layout, Context& context, StorageInitialization initialization)
685 : keys_(std::move(layout.keys)), offsets_(std::move(layout.offsets)), block_ends_(std::move(layout.block_ends)),
686 buffer_(LeafStorage::template make_packed_storage<T>(context, offsets_.back(), offsets_, initialization))
687 {
688 if constexpr (BlockAlignment > 1)
689 {
690 if (initialization == StorageInitialization::Uninitialized)
691 initialize_packed_padding<LeafStorage, T>(buffer_, offsets_, block_ends_);
692 }
693 }
694
695 std::vector<key_type> keys_;
696 std::vector<std::size_t> offsets_;
697 std::vector<std::size_t> block_ends_;
698 buffer_type buffer_;
699};
700
701template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder, class LeafStorage>
702class PackedDiagonalBlockStorageData {
703 public:
704 using key_type = BlockKey<KeyCoordinateCount>;
705 using buffer_type = typename LeafStorage::template storage_t<T>;
706 using extents_type = stdex::dextents<index_type, DenseBlockOrder>;
707 using mapping_type = typename GeneratedLayout::template mapping<extents_type>;
708 using accessor_type = diagonal_accessor<T, extents_type>;
709 using const_accessor_type = diagonal_accessor<T const, extents_type>;
710 using mutable_mdspan_type = stdex::mdspan<T, extents_type, GeneratedLayout, accessor_type>;
711 using const_mdspan_type = stdex::mdspan<T const, extents_type, GeneratedLayout, const_accessor_type>;
712 using component_extents_type = stdex::dextents<index_type, 1>;
713 using component_mapping_type = stdex::layout_stride::mapping<component_extents_type>;
714 using mutable_components_type = stdex::mdspan<T, component_extents_type, stdex::layout_stride>;
715 using const_components_type = stdex::mdspan<T const, component_extents_type, stdex::layout_stride>;
716 using mutable_block_type = MdspecTensorView<mutable_mdspan_type, const_mdspan_type, LeafStorage>;
717 using const_block_type = MdspecTensorView<const_mdspan_type, const_mdspan_type, LeafStorage>;
718
723
724 static_assert(std::same_as<detail::tensor_accessor_factory_t<LeafStorage>, DefaultAccessorFactory>,
725 "packed diagonal block storage currently requires default-accessor leaf storage");
726 static_assert(
727 requires(buffer_type& buffer, buffer_type const& const_buffer) {
728 { LeafStorage::make_handle(buffer) } -> std::same_as<T*>;
729 { LeafStorage::make_handle(const_buffer) } -> std::same_as<T const*>;
730 }, "packed diagonal block storage currently requires immediate contiguous host leaf storage");
731
732 explicit PackedDiagonalBlockStorageData(std::vector<BlockSpec<KeyCoordinateCount, DenseBlockOrder>> const& specs,
734 : PackedDiagonalBlockStorageData(make_layout(specs), initialization)
735 {}
736
737 auto size() const noexcept -> std::size_t { return keys_.size(); }
738 auto keys() const noexcept -> std::span<key_type const> { return keys_; }
739
740 auto block(std::size_t ordinal, std::array<std::size_t, DenseBlockOrder> const& extents) -> mutable_block_type
741 {
742 auto const block_extents = make_extents<extents_type>(extents);
743 auto* mutable_data = LeafStorage::make_handle(buffer_);
744 auto const* const_data = LeafStorage::make_handle(std::as_const(buffer_));
745 if (offsets_[ordinal] != 0)
746 {
747 mutable_data += offsets_[ordinal];
748 const_data += offsets_[ordinal];
749 }
750 auto const component_extents =
751 component_extents_type{static_cast<index_type>(offsets_[ordinal + 1] - offsets_[ordinal])};
752 auto const component_mapping =
753 component_mapping_type{component_extents, std::array<index_type, 1>{index_type{1}}};
754 auto mutable_components = mutable_components_type{mutable_data, component_mapping};
755 auto read_components = const_components_type{const_data, component_mapping};
756 return mutable_block_type{make_diagonal_mdspan(block_extents, mutable_components),
757 make_diagonal_mdspan(block_extents, read_components)};
758 }
759
760 auto block(std::size_t ordinal, std::array<std::size_t, DenseBlockOrder> const& extents) const -> const_block_type
761 {
762 auto const block_extents = make_extents<extents_type>(extents);
763 auto const* data = LeafStorage::make_handle(buffer_);
764 if (offsets_[ordinal] != 0) data += offsets_[ordinal];
765 auto const component_extents =
766 component_extents_type{static_cast<index_type>(offsets_[ordinal + 1] - offsets_[ordinal])};
767 auto const component_mapping =
768 component_mapping_type{component_extents, std::array<index_type, 1>{index_type{1}}};
769 auto components = const_components_type{data, component_mapping};
770 auto span = make_diagonal_mdspan(block_extents, components);
771 return const_block_type{span, span};
772 }
773
775 auto diagonal_values(std::size_t ordinal) -> std::span<T>
776 {
777 auto* data = LeafStorage::make_handle(buffer_);
778 if (offsets_[ordinal] != 0) data += offsets_[ordinal];
779 return {data, offsets_[ordinal + 1] - offsets_[ordinal]};
780 }
781
783 auto diagonal_values(std::size_t ordinal) const -> std::span<T const>
784 {
785 auto const* data = LeafStorage::make_handle(buffer_);
786 if (offsets_[ordinal] != 0) data += offsets_[ordinal];
787 return {data, offsets_[ordinal + 1] - offsets_[ordinal]};
788 }
789
790 auto buffer() noexcept -> buffer_type& { return buffer_; }
791 auto buffer() const noexcept -> buffer_type const& { return buffer_; }
792 auto offsets() const noexcept -> std::span<std::size_t const> { return offsets_; }
793
794 private:
795 struct Layout
796 {
797 std::vector<key_type> keys;
798 std::vector<std::size_t> offsets;
799 };
800
801 static auto make_layout(std::vector<BlockSpec<KeyCoordinateCount, DenseBlockOrder>> const& specs) -> Layout
802 {
803 Layout layout;
804 layout.keys.reserve(specs.size());
805 layout.offsets.reserve(specs.size() + 1);
806 layout.offsets.push_back(0);
807 for (auto const& spec : specs)
808 {
809 layout.keys.push_back(spec.key);
810 std::size_t const block_size = diagonal_extent(spec.extents);
811 if (layout.offsets.back() > std::numeric_limits<std::size_t>::max() - block_size)
812 {
813 throw std::length_error("packed diagonal BlockTensor size overflows size_t");
814 }
815 layout.offsets.push_back(layout.offsets.back() + block_size);
816 }
817 return layout;
818 }
819
820 explicit PackedDiagonalBlockStorageData(Layout layout, StorageInitialization initialization)
821 : keys_(std::move(layout.keys)), offsets_(std::move(layout.offsets)),
822 buffer_(make_storage<LeafStorage, T>(offsets_.back(), initialization))
823 {}
824
825 std::vector<key_type> keys_;
826 std::vector<std::size_t> offsets_;
827 buffer_type buffer_;
828};
829
834template <class AsyncBlock> class AsyncBlockDataDescriptor {
835 public:
836 using async_block_type = AsyncBlock;
837
838 explicit AsyncBlockDataDescriptor(async_block_type& block) noexcept : block_(&block) {}
839
841 auto async_block() const noexcept -> async_block_type& { return *block_; }
842
843 private:
844 async_block_type* block_;
845};
846
847template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder, class LeafStorage>
848class AsyncSeparateSparseBlockStorageData {
849 public:
850 using key_type = BlockKey<KeyCoordinateCount>;
851 using block_value_type = ColumnMajorTensor<T, DenseBlockOrder, LeafStorage>;
852 using async_block_type = async::Async<block_value_type>;
853 using extents_type = stdex::dextents<index_type, DenseBlockOrder>;
854 using mapping_type = typename ColumnMajor::template mapping<extents_type>;
855 using accessor_type = stdex::default_accessor<T>;
856 using const_accessor_type = stdex::default_accessor<T const>;
857 using mutable_descriptor_type = AsyncBlockDataDescriptor<async_block_type>;
858 using const_descriptor_type = AsyncBlockDataDescriptor<async_block_type const>;
859 using mutable_mdspec_type = mdspec<T, extents_type, ColumnMajor, accessor_type, mutable_descriptor_type>;
860 using const_mdspec_type = mdspec<T const, extents_type, ColumnMajor, const_accessor_type, const_descriptor_type>;
861 using mutable_block_type = MdspecTensorView<mutable_mdspec_type, const_mdspec_type, LeafStorage>;
862 using const_block_type = MdspecTensorView<const_mdspec_type, const_mdspec_type, LeafStorage>;
863
865 "async separate sparse block storage currently requires immediate leaf access");
866 static_assert(std::same_as<detail::tensor_accessor_factory_t<LeafStorage>, DefaultAccessorFactory>,
867 "async separate sparse block storage currently requires default-accessor leaf storage");
868
869 explicit AsyncSeparateSparseBlockStorageData(
870 std::vector<BlockSpec<KeyCoordinateCount, DenseBlockOrder>> const& specs,
872 {
873 keys_.reserve(specs.size());
874 blocks_.reserve(specs.size());
875 for (auto const& spec : specs)
876 {
877 keys_.push_back(spec.key);
878 blocks_.emplace_back(make_block_tensor<block_value_type>(spec.extents, initialization));
879 }
880 }
881
882 auto size() const noexcept -> std::size_t { return keys_.size(); }
883 auto keys() const noexcept -> std::span<key_type const> { return keys_; }
884
885 auto block(std::size_t ordinal, std::array<std::size_t, DenseBlockOrder> const& extents) -> mutable_block_type
886 {
887 auto mapping = mapping_type(make_extents<extents_type>(extents));
888 return mutable_block_type{
889 mutable_mdspec_type{mutable_descriptor_type{blocks_[ordinal]}, mapping, accessor_type{}},
890 const_mdspec_type{const_descriptor_type{std::as_const(blocks_[ordinal])}, mapping, const_accessor_type{}}};
891 }
892
893 auto block(std::size_t ordinal, std::array<std::size_t, DenseBlockOrder> const& extents) const -> const_block_type
894 {
895 auto span = const_mdspec_type{const_descriptor_type{blocks_[ordinal]},
896 mapping_type(make_extents<extents_type>(extents)), const_accessor_type{}};
897 return const_block_type{span, span};
898 }
899
900 auto async_block(std::size_t ordinal) noexcept -> async_block_type& { return blocks_[ordinal]; }
901 auto async_block(std::size_t ordinal) const noexcept -> async_block_type const& { return blocks_[ordinal]; }
902
903 private:
904 std::vector<key_type> keys_;
905 std::vector<async_block_type> blocks_;
906};
907
908} // namespace detail
909
912template <class LeafStorage = HostStorage> struct SeparateSparseBlockStorage
913{
914 using leaf_storage_policy = LeafStorage;
915 using backend_selector_type = typename leaf_storage_policy::backend_selector_type;
917 static constexpr bool stores_all_legal_blocks = false;
918 static constexpr bool is_distributed = false;
919
920 template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
921 using storage_t =
922 detail::SeparateSparseBlockStorageData<T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy>;
923
924 [[nodiscard]] static constexpr auto backend_selector() noexcept -> backend_selector_type
925 {
926 return leaf_storage_policy::backend_selector();
927 }
928};
929
935template <class LeafStorage = HostStorage> struct ParallelSeparateSparseBlockStorage
936{
937 using leaf_storage_policy = LeafStorage;
938 using backend_selector_type = typename leaf_storage_policy::backend_selector_type;
940 static constexpr bool stores_all_legal_blocks = false;
941 static constexpr bool is_distributed = false;
942
943 template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
944 using storage_t =
945 detail::SeparateSparseBlockStorageData<T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy>;
946
947 [[nodiscard]] static constexpr auto backend_selector() noexcept -> backend_selector_type
948 {
949 return leaf_storage_policy::backend_selector();
950 }
951};
952
958template <class LeafStorage = HostStorage, std::size_t BlockAlignment = 1> struct PackedSparseBlockStorage
959{
960 using leaf_storage_policy = LeafStorage;
961 using backend_selector_type = typename leaf_storage_policy::backend_selector_type;
963 static constexpr bool stores_all_legal_blocks = false;
964 static constexpr bool is_distributed = false;
965
966 template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
967 using storage_t =
968 detail::PackedBlockStorageData<T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy, BlockAlignment>;
969
970 [[nodiscard]] static constexpr auto backend_selector() noexcept -> backend_selector_type
971 {
972 return leaf_storage_policy::backend_selector();
973 }
974};
975
984template <class LeafStorage = HostStorage, std::size_t BlockAlignment = 1> struct ParallelPackedSparseBlockStorage
985{
986 using leaf_storage_policy = LeafStorage;
987 using backend_selector_type = typename leaf_storage_policy::backend_selector_type;
989 static constexpr bool stores_all_legal_blocks = false;
990 static constexpr bool is_distributed = false;
991
992 template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
993 using storage_t =
994 detail::PackedBlockStorageData<T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy, BlockAlignment>;
995
996 [[nodiscard]] static constexpr auto backend_selector() noexcept -> backend_selector_type
997 {
998 return leaf_storage_policy::backend_selector();
999 }
1000};
1001
1009template <class LeafStorage = HostStorage, std::size_t BlockAlignment = 1> struct PackedCompleteBlockStorage
1010{
1011 using leaf_storage_policy = LeafStorage;
1012 using backend_selector_type = typename leaf_storage_policy::backend_selector_type;
1014 static constexpr bool stores_all_legal_blocks = true;
1015 static constexpr bool is_distributed = false;
1016
1017 template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
1019 detail::PackedBlockStorageData<T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy, BlockAlignment>;
1020
1021 [[nodiscard]] static constexpr auto backend_selector() noexcept -> backend_selector_type
1022 {
1023 return leaf_storage_policy::backend_selector();
1024 }
1025};
1026
1034template <class LeafStorage = HostStorage, std::size_t BlockAlignment = 1> struct ParallelPackedCompleteBlockStorage
1035{
1036 using leaf_storage_policy = LeafStorage;
1037 using backend_selector_type = typename leaf_storage_policy::backend_selector_type;
1039 static constexpr bool stores_all_legal_blocks = true;
1040 static constexpr bool is_distributed = false;
1041
1042 template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
1044 detail::PackedBlockStorageData<T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy, BlockAlignment>;
1045
1046 [[nodiscard]] static constexpr auto backend_selector() noexcept -> backend_selector_type
1047 {
1048 return leaf_storage_policy::backend_selector();
1049 }
1050};
1051
1057template <class LeafStorage = HostStorage> struct PackedDiagonalBlockStorage
1058{
1059 using leaf_storage_policy = LeafStorage;
1060 using backend_selector_type = typename leaf_storage_policy::backend_selector_type;
1062 static constexpr bool stores_all_legal_blocks = false;
1063 static constexpr bool stores_diagonal_blocks = true;
1064 static constexpr bool is_distributed = false;
1065
1066 template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
1068 detail::PackedDiagonalBlockStorageData<T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy>;
1069
1070 [[nodiscard]] static constexpr auto backend_selector() noexcept -> backend_selector_type
1071 {
1072 return leaf_storage_policy::backend_selector();
1073 }
1074};
1075
1081template <class LeafStorage = HostStorage> struct AsyncSeparateSparseBlockStorage
1082{
1083 using leaf_storage_policy = LeafStorage;
1084 using backend_selector_type = typename leaf_storage_policy::backend_selector_type;
1086 static constexpr bool stores_all_legal_blocks = false;
1087 static constexpr bool is_distributed = false;
1088
1089 template <typename T, std::size_t KeyCoordinateCount, std::size_t DenseBlockOrder>
1091 detail::AsyncSeparateSparseBlockStorageData<T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy>;
1092
1093 [[nodiscard]] static constexpr auto backend_selector() noexcept -> backend_selector_type
1094 {
1095 return leaf_storage_policy::backend_selector();
1096 }
1097};
1098
1099static_assert(SparseBlockStorage<SeparateSparseBlockStorage<>>);
1100static_assert(SparseBlockStorage<ParallelSeparateSparseBlockStorage<>>);
1101static_assert(SparseBlockStorage<PackedSparseBlockStorage<>>);
1102static_assert(SparseBlockStorage<ParallelPackedSparseBlockStorage<>>);
1103static_assert(CompleteBlockStorage<PackedCompleteBlockStorage<>>);
1104static_assert(CompleteBlockStorage<ParallelPackedCompleteBlockStorage<>>);
1105static_assert(SparseBlockStorage<PackedDiagonalBlockStorage<>>);
1106static_assert(DiagonalBlockStorage<PackedDiagonalBlockStorage<>>);
1107static_assert(SparseBlockStorage<AsyncSeparateSparseBlockStorage<>>);
1108static_assert(BlockTensorStorageFor<SeparateSparseBlockStorage<>, double, 2, 2>);
1109static_assert(BlockTensorStorageFor<SeparateSparseBlockStorage<>, double, 4, 0>);
1110static_assert(BlockTensorStorageFor<ParallelSeparateSparseBlockStorage<>, double, 2, 2>);
1111static_assert(BlockTensorStorageFor<PackedSparseBlockStorage<>, double, 2, 2>);
1112static_assert(BlockTensorStorageFor<ParallelPackedSparseBlockStorage<>, double, 2, 2>);
1113static_assert(BlockTensorStorageFor<PackedCompleteBlockStorage<>, double, 2, 2>);
1114static_assert(BlockTensorStorageFor<ParallelPackedCompleteBlockStorage<>, double, 2, 2>);
1115static_assert(BlockTensorStorageFor<PackedSparseBlockStorage<>, double, 4, 0>);
1116static_assert(BlockTensorStorageFor<PackedDiagonalBlockStorage<>, double, 2, 2>);
1117static_assert(BlockTensorStorageFor<PackedDiagonalBlockStorage<>, double, 0, 3>);
1118static_assert(LocalBlockStorageFor<PackedCompleteBlockStorage<>, double, 4, 0>);
1119static_assert(LocalBlockStorageFor<AsyncSeparateSparseBlockStorage<>, double, 4, 0>);
1120static_assert(ImmediateLocalBlockStorageFor<SeparateSparseBlockStorage<>, double, 2, 2>);
1121static_assert(ImmediateLocalBlockStorageFor<ParallelSeparateSparseBlockStorage<>, double, 2, 2>);
1122static_assert(ImmediateLocalBlockStorageFor<PackedSparseBlockStorage<>, double, 4, 0>);
1123static_assert(ImmediateLocalBlockStorageFor<ParallelPackedSparseBlockStorage<>, double, 4, 0>);
1124static_assert(ImmediateLocalBlockStorageFor<PackedCompleteBlockStorage<>, double, 4, 0>);
1125static_assert(ImmediateLocalBlockStorageFor<ParallelPackedCompleteBlockStorage<>, double, 4, 0>);
1126static_assert(ImmediateLocalBlockStorageFor<PackedDiagonalBlockStorage<>, double, 2, 2>);
1127static_assert(AsyncLocalBlockStorageFor<AsyncSeparateSparseBlockStorage<>, double, 2, 2>);
1128static_assert(AsyncLocalBlockStorageFor<AsyncSeparateSparseBlockStorage<>, double, 4, 0>);
1129
1130} // namespace uni20
The Async<T> container: coroutine‐safe asynchronous read/write.
Defines fixed-order logical block coordinates.
static constexpr bool immediately_writable
Whether mutable storage provides a writable data handle without acquisition.
Definition basic_tensor.hpp:141
static constexpr bool immediately_readable
Whether const storage provides a readable data handle without acquisition.
Definition basic_tensor.hpp:136
stdex::mdspan< element_type, extents_type, layout_policy, accessor_type > mdspan_type
Definition basic_tensor.hpp:130
stdex::mdspan< element_type const, extents_type, layout_policy, const_accessor_type > const_mdspan_type
Definition basic_tensor.hpp:131
Async<T> is a container for coroutine-safe asynchronous read/write.
Definition async/async.hpp:93
Local BlockTensor storage with one independently scheduled async value per block.
Definition block_tensor_storage.hpp:142
Storage policy instantiated for one block scalar and tensor order.
Definition block_tensor_storage.hpp:81
Storage policy for a BlockTensor container.
Definition block_tensor_storage.hpp:46
BlockTensor storage which contains every symmetry-legal block.
Definition block_tensor_storage.hpp:63
BlockTensor storage whose stored numerical blocks are generalized diagonals.
Definition block_tensor_storage.hpp:71
Full logical mdspec with a rank-one view of its generalized diagonal components.
Definition mdspan/concepts.hpp:465
Distributed BlockTensor storage refinement.
Definition block_tensor_storage.hpp:168
Local BlockTensor storage whose block TensorViews are immediately accessible.
Definition block_tensor_storage.hpp:127
BlockTensor storage whose blocks reside within one local process.
Definition block_tensor_storage.hpp:118
Writable generalized-diagonal mdspec with writable rank-one components.
Definition mdspan/concepts.hpp:477
MutableImmediateTensorView whose writable mdspan has a specified static rank.
Definition tensor/concepts.hpp:209
MutableTensorView with a specified static rank.
Definition tensor/concepts.hpp:166
ImmediateTensorView whose readable mdspan has a specified static rank.
Definition tensor/concepts.hpp:201
TensorView whose readable mdspec has a specified static rank.
Definition tensor/concepts.hpp:149
BlockTensor storage whose stored key set may omit legal blocks.
Definition block_tensor_storage.hpp:58
cuda::ResourceLease< HandleSlot > handle
Definition cublas/execution.cpp:33
locale_t value
Definition data_table.cpp:49
Accessor support for compressed generalized diagonal tensors.
Synthetic mdspan layout for values generated from logical indices.
constexpr stdex::default_accessor< T const > const_accessor(stdex::default_accessor< T > const &accessor_policy)
Wrap a default_accessor<T> into a const_default_accessor<T>.
Definition mdspan/concepts.hpp:160
Mdspan-shaped metadata for storage whose data handle requires acquisition.
Concrete tensor-level views over owned mdspan or mdspec metadata.
Definition qnum.hpp:403
Definition async/async.hpp:26
constexpr uninitialized_t uninitialized
Explicit allocation tag for overwrite outputs and scratch space.
Definition common/initialization.hpp:22
std::remove_cv_t< typename tensor_mdspec_t< T >::element_type > tensor_element_t
Scalar value type exposed by a tensor-level object.
Definition tensor/concepts.hpp:126
std::ptrdiff_t index_type
Definition types.hpp:19
mpreal remainder(mpreal const &a, mpreal const &b)
Nearest-even-quotient remainder; exact operands retain exact rational results.
Definition mpreal_functions.hpp:534
Tensor(InputTensor const &) -> Tensor< tensor_element_t< InputTensor >, tensor_mdspec_t< InputTensor >::rank(), HostStorage, detail::materialized_layout_t< void, tensor_mdspec_t< InputTensor > >, DefaultAccessorFactory >
Deduce a runtime-extents host tensor that materializes a tensor view.
std::remove_cvref_t< detail::normalized_const_mdspec_t< T > > tensor_mdspec_t
Normalized readable MdspecLike type exposed by a tensor-level object.
Definition tensor/concepts.hpp:123
constexpr auto make_diagonal_mdspan(Extents logical_extents, Components const &components)
Present rank-one strided components as a full generalized-diagonal mdspan.
Definition diagonal_accessor.hpp:295
StorageInitialization
Numerical initialization requested from a storage implementation.
Definition common/initialization.hpp:26
std::size_t span
Definition presentation.cpp:2017
Sparse storage with one independently scheduled dense Tensor per block.
Definition block_tensor_storage.hpp:1082
typename leaf_storage_policy::backend_selector_type backend_selector_type
Definition block_tensor_storage.hpp:1084
detail::AsyncSeparateSparseBlockStorageData< T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy > storage_t
Definition block_tensor_storage.hpp:1091
static constexpr bool is_distributed
Definition block_tensor_storage.hpp:1087
LeafStorage leaf_storage_policy
Definition block_tensor_storage.hpp:1083
static constexpr auto backend_selector() noexcept -> backend_selector_type
Definition block_tensor_storage.hpp:1093
static constexpr bool stores_all_legal_blocks
Definition block_tensor_storage.hpp:1086
Complete storage packing every symmetry-legal dense block into one leaf buffer.
Definition block_tensor_storage.hpp:1010
typename leaf_storage_policy::backend_selector_type backend_selector_type
Definition block_tensor_storage.hpp:1012
LeafStorage leaf_storage_policy
Definition block_tensor_storage.hpp:1011
static constexpr bool stores_all_legal_blocks
Definition block_tensor_storage.hpp:1014
static constexpr auto backend_selector() noexcept -> backend_selector_type
Definition block_tensor_storage.hpp:1021
static constexpr bool is_distributed
Definition block_tensor_storage.hpp:1015
detail::PackedBlockStorageData< T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy, BlockAlignment > storage_t
Definition block_tensor_storage.hpp:1019
Sparse BlockTensor storage packing each generalized diagonal block into one leaf buffer.
Definition block_tensor_storage.hpp:1058
LeafStorage leaf_storage_policy
Definition block_tensor_storage.hpp:1059
static constexpr bool stores_diagonal_blocks
Definition block_tensor_storage.hpp:1063
static constexpr bool stores_all_legal_blocks
Definition block_tensor_storage.hpp:1062
typename leaf_storage_policy::backend_selector_type backend_selector_type
Definition block_tensor_storage.hpp:1060
static constexpr auto backend_selector() noexcept -> backend_selector_type
Definition block_tensor_storage.hpp:1070
detail::PackedDiagonalBlockStorageData< T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy > storage_t
Definition block_tensor_storage.hpp:1068
static constexpr bool is_distributed
Definition block_tensor_storage.hpp:1064
Sparse storage packing every stored dense block into one leaf buffer.
Definition block_tensor_storage.hpp:959
typename leaf_storage_policy::backend_selector_type backend_selector_type
Definition block_tensor_storage.hpp:961
static constexpr bool stores_all_legal_blocks
Definition block_tensor_storage.hpp:963
static constexpr bool is_distributed
Definition block_tensor_storage.hpp:964
detail::PackedBlockStorageData< T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy, BlockAlignment > storage_t
Definition block_tensor_storage.hpp:968
LeafStorage leaf_storage_policy
Definition block_tensor_storage.hpp:960
static constexpr auto backend_selector() noexcept -> backend_selector_type
Definition block_tensor_storage.hpp:970
Complete packed storage whose disjoint blocks may be processed in a scheduler batch.
Definition block_tensor_storage.hpp:1035
typename leaf_storage_policy::backend_selector_type backend_selector_type
Definition block_tensor_storage.hpp:1037
detail::PackedBlockStorageData< T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy, BlockAlignment > storage_t
Definition block_tensor_storage.hpp:1044
static constexpr bool is_distributed
Definition block_tensor_storage.hpp:1040
static constexpr bool stores_all_legal_blocks
Definition block_tensor_storage.hpp:1039
LeafStorage leaf_storage_policy
Definition block_tensor_storage.hpp:1036
static constexpr auto backend_selector() noexcept -> backend_selector_type
Definition block_tensor_storage.hpp:1046
Packed sparse storage whose disjoint dense blocks may be processed in a scheduler batch.
Definition block_tensor_storage.hpp:985
static constexpr auto backend_selector() noexcept -> backend_selector_type
Definition block_tensor_storage.hpp:996
static constexpr bool is_distributed
Definition block_tensor_storage.hpp:990
detail::PackedBlockStorageData< T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy, BlockAlignment > storage_t
Definition block_tensor_storage.hpp:994
static constexpr bool stores_all_legal_blocks
Definition block_tensor_storage.hpp:989
typename leaf_storage_policy::backend_selector_type backend_selector_type
Definition block_tensor_storage.hpp:987
LeafStorage leaf_storage_policy
Definition block_tensor_storage.hpp:986
Sparse storage whose separate dense blocks may be processed in a scheduler batch.
Definition block_tensor_storage.hpp:936
detail::SeparateSparseBlockStorageData< T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy > storage_t
Definition block_tensor_storage.hpp:945
LeafStorage leaf_storage_policy
Definition block_tensor_storage.hpp:937
static constexpr bool stores_all_legal_blocks
Definition block_tensor_storage.hpp:940
static constexpr bool is_distributed
Definition block_tensor_storage.hpp:941
static constexpr auto backend_selector() noexcept -> backend_selector_type
Definition block_tensor_storage.hpp:947
typename leaf_storage_policy::backend_selector_type backend_selector_type
Definition block_tensor_storage.hpp:938
Execute independent block-level work through the active scheduler's synchronous batch interface.
Definition block_tensor_storage.hpp:41
Sparse storage with one independently owning dense Tensor per stored block.
Definition block_tensor_storage.hpp:913
static constexpr bool is_distributed
Definition block_tensor_storage.hpp:918
LeafStorage leaf_storage_policy
Definition block_tensor_storage.hpp:914
static constexpr bool stores_all_legal_blocks
Definition block_tensor_storage.hpp:917
detail::SeparateSparseBlockStorageData< T, KeyCoordinateCount, DenseBlockOrder, leaf_storage_policy > storage_t
Definition block_tensor_storage.hpp:922
typename leaf_storage_policy::backend_selector_type backend_selector_type
Definition block_tensor_storage.hpp:915
static constexpr auto backend_selector() noexcept -> backend_selector_type
Definition block_tensor_storage.hpp:924
Execute block-level work serially on the calling thread.
Definition block_tensor_storage.hpp:37
General-purpose owning tensors with runtime extents.