21#include <initializer_list>
35template <
class T>
struct IsDomain : std::false_type
38template <
class... Spaces>
struct IsDomain<
Domain<Spaces...>> : std::true_type
41template <
class T>
struct IsCodomain : std::false_type
44template <
class... Spaces>
struct IsCodomain<
Codomain<Spaces...>> : std::true_type
48concept PrototypeBlockFactor =
49 std::same_as<primal_space_t<T>, BlockSpace> || std::same_as<primal_space_t<T>, LocalSpace> ||
50 std::same_as<primal_space_t<T>, QNumSpace>;
52template <
class Boundary>
struct PrototypeBoundary;
54template <
template <
class...>
class Boundary,
class... Spaces>
55struct PrototypeBoundary<Boundary<Spaces...>> : std::bool_constant<(PrototypeBlockFactor<Spaces> && ...)>
58template <
class Boundary>
struct BoundaryBlockShape;
60template <
template <
class...>
class Boundary,
class... Spaces>
struct BoundaryBlockShape<Boundary<Spaces...>>
62 static constexpr std::size_t key_coordinate_count =
63 (std::size_t{0} + ... + (BlockTensorSpaceTraits<std::remove_cvref_t<Spaces>>::has_block_coordinate ? 1U : 0U));
64 static constexpr std::size_t dense_block_order =
65 (std::size_t{0} + ... + (BlockTensorSpaceTraits<std::remove_cvref_t<Spaces>>::has_dense_axis ? 1U : 0U));
68inline auto factor_size(BlockSpace
const& space) -> std::size_t {
return space.size(); }
69inline auto factor_size(LocalSpace
const& space) -> std::size_t {
return space.size(); }
71template <Space SpaceType>
auto factor_size(Dual<SpaceType>
const& space) -> std::size_t
73 return factor_size(space.base());
76inline auto factor_qnum(BlockSpace
const& space, std::size_t coordinate) -> QNum
const& {
return space[coordinate].q; }
78inline auto factor_qnum(LocalSpace
const& space, std::size_t coordinate) -> QNum
const& {
return space[coordinate]; }
80inline auto factor_qnum(QNumSpace
const& space, std::size_t) -> QNum
const& {
return space.qnum(); }
82template <Space SpaceType>
auto factor_qnum(Dual<SpaceType>
const& space, std::size_t coordinate) -> QNum
84 return dual(factor_qnum(space.base(), coordinate));
87inline auto factor_extent(BlockSpace
const& space, std::size_t coordinate) -> std::size_t
89 return space[coordinate].dim;
92template <Space SpaceType>
auto factor_extent(Dual<SpaceType>
const& space, std::size_t coordinate) -> std::size_t
94 return factor_extent(space.base(), coordinate);
97template <
class Boundary,
class Function>
void for_each_boundary_space(Boundary
const& boundary, Function&& function)
99 std::apply([&](
auto const&... spaces) { (function(spaces), ...); }, boundary.spaces());
102template <std::
size_t KeyCoordinateCount,
class DomainType,
class CodomainType>
103auto boundary_factor_sizes(DomainType
const& domain, CodomainType
const& codomain)
104 -> std::array<std::size_t, KeyCoordinateCount>
106 std::array<std::size_t, KeyCoordinateCount> sizes{};
107 std::size_t key_axis = 0;
108 auto append_size = [&](
auto const& space) {
109 using space_type = std::remove_cvref_t<
decltype(space)>;
110 if constexpr (BlockTensorSpaceTraits<space_type>::has_block_coordinate)
112 sizes[key_axis++] = factor_size(space);
115 for_each_boundary_space(domain, append_size);
116 for_each_boundary_space(codomain, append_size);
120template <std::
size_t KeyCoordinateCount,
class DomainType,
class CodomainType>
121auto is_legal_block_key(Symmetry
const& symmetry, DomainType
const& domain, CodomainType
const& codomain,
122 BlockKey<KeyCoordinateCount>
const& key) ->
bool
124 auto const sizes = boundary_factor_sizes<KeyCoordinateCount>(domain, codomain);
125 for (std::size_t axis = 0; axis < KeyCoordinateCount; ++axis)
127 if (key.coordinate(axis) >= sizes[axis])
return false;
132 std::size_t key_axis = 0;
133 auto add_charge = [&](
auto const& space, QNum& charge) {
134 using space_type = std::remove_cvref_t<
decltype(space)>;
135 std::size_t coordinate = 0;
136 if constexpr (BlockTensorSpaceTraits<space_type>::has_block_coordinate)
138 coordinate = key.coordinate(key_axis++);
140 charge = charge + factor_qnum(space, coordinate);
142 for_each_boundary_space(domain, [&](
auto const& space) { add_charge(space, domain_charge); });
143 for_each_boundary_space(codomain, [&](
auto const& space) { add_charge(space, codomain_charge); });
144 return domain_charge == codomain_charge;
158template <
typename T,
class DomainType,
class CodomainType, BlockTensorStorage Storage>
159 requires(detail::IsDomain<DomainType>::value && detail::IsCodomain<CodomainType>::value &&
160 detail::PrototypeBoundary<DomainType>::value && detail::PrototypeBoundary<CodomainType>::value)
168 static constexpr std::size_t static_order = domain_type::size() + codomain_type::size();
169 static constexpr std::size_t static_key_coordinate_count =
170 detail::BoundaryBlockShape<domain_type>::key_coordinate_count +
171 detail::BoundaryBlockShape<codomain_type>::key_coordinate_count;
172 static constexpr std::size_t static_dense_block_order =
173 detail::BoundaryBlockShape<domain_type>::dense_block_order +
174 detail::BoundaryBlockShape<codomain_type>::dense_block_order;
175 static_assert(static_order <= 4,
"the first BlockTensor slice supports orders 0 through 4");
178 "BlockTensor storage does not provide the required block bindings");
182 static_dense_block_order>;
194 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
195 storage_(this->make_storage(std::move(stored_keys)))
199 template <
class Context>
203 std::constructible_from<
205 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>>
const&,
207 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
208 storage_(this->make_storage(std::move(stored_keys), context))
217 std::initializer_list<key_type> stored_keys)
219 :
BlockTensor(symmetry, std::move(domain), std::move(codomain), std::vector<key_type>(stored_keys))
228 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
229 storage_(this->make_complete_storage())
233 template <
class Context>
236 std::constructible_from<
238 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>>
const&,
240 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
241 storage_(this->make_complete_storage(context))
250 std::vector<key_type> stored_keys)
252 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
257 template <
class Context>
259 std::vector<key_type> stored_keys, Context& context)
261 std::constructible_from<
263 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>>
const&,
265 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
275 std::initializer_list<key_type> stored_keys)
278 std::vector<key_type>(stored_keys))
287 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
292 template <
class Context>
295 std::constructible_from<
297 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>>
const&,
299 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
313 static constexpr auto order() noexcept ->
std::
size_t {
return static_order; }
327 std::size_t count = 0;
328 this->for_each_possible_key([&](
key_type const& key) {
329 if (this->is_legal(key)) ++count;
341 std::vector<key_type> result;
342 this->for_each_possible_key([&](
key_type const& key) {
343 if (this->is_legal(key)) result.push_back(key);
356 return detail::is_legal_block_key(symmetry_, domain_, codomain_, key);
360 auto contains(
key_type const& key)
const ->
bool {
return this->ordinal(key).has_value(); }
365 auto const found = this->ordinal(key);
366 if (!found)
return std::nullopt;
367 return this->block_by_ordinal(*found);
373 auto const found = this->ordinal(key);
374 if (!found)
return std::nullopt;
375 return this->block_by_ordinal(*found);
382 auto const found = this->find_block(key);
383 if (!found)
throw std::out_of_range(
"BlockTensor block key is not stored");
391 auto const found = this->find_block(key);
392 if (!found)
throw std::out_of_range(
"BlockTensor block key is not stored");
402 if (ordinal >= storage_.size())
throw std::out_of_range(
"BlockTensor block ordinal is out of range");
403 auto const& key = storage_.keys()[ordinal];
404 return storage_.block(ordinal, this->block_extents(key));
413 if (ordinal >= storage_.size())
throw std::out_of_range(
"BlockTensor block ordinal is out of range");
414 auto const& key = storage_.keys()[ordinal];
415 return storage_.block(ordinal, this->block_extents(key));
423 requires requires(
storage_type& storage) { storage.diagonal_values(std::size_t{}); }
425 auto const found = this->ordinal(key);
426 if (!found)
throw std::out_of_range(
"BlockTensor block key is not stored");
427 return storage_.diagonal_values(*found);
435 requires requires(
storage_type const& storage) { storage.diagonal_values(std::size_t{}); }
437 auto const found = this->ordinal(key);
438 if (!found)
throw std::out_of_range(
"BlockTensor block key is not stored");
439 return storage_.diagonal_values(*found);
445 requires requires(
storage_type& storage) { storage.diagonal_values(std::size_t{}); }
447 if (ordinal >= storage_.size())
throw std::out_of_range(
"BlockTensor block ordinal is out of range");
448 return storage_.diagonal_values(ordinal);
454 requires requires(
storage_type const& storage) { storage.diagonal_values(std::size_t{}); }
456 if (ordinal >= storage_.size())
throw std::out_of_range(
"BlockTensor block ordinal is out of range");
457 return storage_.diagonal_values(ordinal);
468 static_dense_block_order>
470 auto const found = this->ordinal(key);
471 if (!found)
throw std::out_of_range(
"BlockTensor block key is not stored");
472 return storage_.async_block(*found);
481 static_dense_block_order>
483 auto const found = this->ordinal(key);
484 if (!found)
throw std::out_of_range(
"BlockTensor block key is not stored");
485 return storage_.async_block(*found);
494 static_dense_block_order>
496 if (ordinal >= storage_.size())
throw std::out_of_range(
"BlockTensor block ordinal is out of range");
497 return storage_.async_block(ordinal);
506 static_dense_block_order>
508 if (ordinal >= storage_.size())
throw std::out_of_range(
"BlockTensor block ordinal is out of range");
509 return storage_.async_block(ordinal);
518 return storage_policy::backend_selector();
529 requires requires(
storage_type const& storage) { storage.allocation_context(); }
531 return storage_.allocation_context();
545 ValidatedStorageTag{});
557 ValidatedStorageTag{});
561 struct ValidatedStorageTag
564 BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, storage_type storage,
566 : symmetry_(symmetry), domain_(
std::move(domain)), codomain_(
std::move(codomain)), storage_(
std::move(storage))
569 auto make_storage(std::vector<key_type> stored_keys,
572 this->validate_boundaries();
573 return this->make_storage_from_validated_keys(std::move(stored_keys), initialization);
576 template <
class Context>
577 auto make_storage(std::vector<key_type> stored_keys, Context& context,
580 this->validate_boundaries();
581 return this->make_storage_from_validated_keys(std::move(stored_keys), context, initialization);
584 auto make_storage_from_validated_keys(std::vector<key_type> stored_keys,
587 return storage_type(this->make_block_specs(std::move(stored_keys)), initialization);
590 template <
class Context>
591 auto make_storage_from_validated_keys(std::vector<key_type> stored_keys, Context& context,
594 return storage_type(this->make_block_specs(std::move(stored_keys)), context, initialization);
597 auto make_block_specs(std::vector<key_type> stored_keys)
598 -> std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>>
600 std::sort(stored_keys.begin(), stored_keys.end());
601 if (std::adjacent_find(stored_keys.begin(), stored_keys.end()) != stored_keys.end())
603 throw std::invalid_argument(
"BlockTensor stored keys must be unique");
606 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>> specs;
607 specs.reserve(stored_keys.size());
608 for (key_type
const& key : stored_keys)
610 if (!this->is_legal(key))
throw std::invalid_argument(
"BlockTensor stored key is not symmetry-legal");
611 auto const extents = this->block_extents(key);
612 static_cast<void>(detail::checked_block_size(extents));
613 specs.push_back({key, extents});
620 this->validate_boundaries();
621 std::vector<key_type> stored_keys;
622 this->for_each_possible_key([&](key_type
const& key) {
623 if (this->is_legal(key)) stored_keys.push_back(key);
625 return this->make_storage_from_validated_keys(std::move(stored_keys), initialization);
628 template <
class Context>
629 auto make_complete_storage(Context& context,
632 this->validate_boundaries();
633 std::vector<key_type> stored_keys;
634 this->for_each_possible_key([&](key_type
const& key) {
635 if (this->is_legal(key)) stored_keys.push_back(key);
637 return this->make_storage_from_validated_keys(std::move(stored_keys), context, initialization);
640 void validate_boundaries()
const
642 if (!symmetry_.valid())
throw std::invalid_argument(
"BlockTensor requires a valid symmetry");
643 auto validate = [&](
auto const& space) {
644 if (space.symmetry() != symmetry_)
646 throw std::invalid_argument(
"BlockTensor boundary space has the wrong symmetry");
649 detail::for_each_boundary_space(domain_, validate);
650 detail::for_each_boundary_space(codomain_, validate);
653 auto factor_sizes() const ->
std::array<
std::
size_t, static_key_coordinate_count>
655 return detail::boundary_factor_sizes<static_key_coordinate_count>(domain_, codomain_);
658 auto block_extents(key_type
const& key)
const -> std::array<std::size_t, static_dense_block_order>
660 std::array<std::size_t, static_dense_block_order> extents{};
661 std::size_t key_axis = 0;
662 std::size_t dense_axis = 0;
663 auto append_extent = [&](
auto const& space) {
664 using space_type = std::remove_cvref_t<
decltype(space)>;
665 std::size_t coordinate = 0;
666 if constexpr (BlockTensorSpaceTraits<space_type>::has_block_coordinate)
668 coordinate = key.coordinate(key_axis++);
670 if constexpr (BlockTensorSpaceTraits<space_type>::has_dense_axis)
672 std::size_t
const extent = detail::factor_extent(space, coordinate);
673 if (!std::in_range<index_type>(extent))
675 throw std::length_error(
"BlockTensor block extent does not fit index_type");
677 extents[dense_axis++] = extent;
680 detail::for_each_boundary_space(domain_, append_extent);
681 detail::for_each_boundary_space(codomain_, append_extent);
685 template <
class Function>
void for_each_possible_key(Function&& function)
const
687 auto const sizes = this->factor_sizes();
688 if (std::ranges::find(sizes, std::size_t{0}) != sizes.end())
return;
690 if constexpr (static_key_coordinate_count == 0)
692 function(key_type{});
696 std::array<std::size_t, static_key_coordinate_count> coordinates{};
699 function(key_type{coordinates});
700 std::size_t axis = static_key_coordinate_count;
704 if (++coordinates[axis] < sizes[axis])
break;
705 coordinates[axis] = 0;
707 if (axis == 0 && coordinates[0] == 0)
return;
712 auto ordinal(key_type
const& key)
const -> std::optional<std::size_t>
714 auto const keys = storage_.keys();
715 auto const found = std::ranges::lower_bound(keys, key);
716 if (found == keys.end() || *found != key)
return std::nullopt;
717 return static_cast<std::size_t
>(found - keys.begin());
722 codomain_type codomain_;
723 storage_type storage_;
Defines immutable block-structured tensor spaces and regularization helpers.
Classifies tensor spaces for block-key and dense-block storage.
Defines local sparse and packed-complete BlockTensor storage policies.
Opaque logical block-selection coordinates in boundary order.
Definition block_key.hpp:20
Fixed-order tensor whose blocks obey a bosonic abelian selection rule.
Definition block_tensor.hpp:161
auto is_legal(key_type const &key) const -> bool
Return whether a key is in range and satisfies charge conservation.
Definition block_tensor.hpp:354
static constexpr auto key_coordinate_count() noexcept -> std::size_t
Return the number of coordinates stored in each block key.
Definition block_tensor.hpp:316
typename storage_policy::backend_selector_type backend_selector_type
Definition block_tensor.hpp:185
auto block_by_ordinal(std::size_t ordinal) const -> const_block_type
Return a read-only block TensorView by stable canonical ordinal.
Definition block_tensor.hpp:411
auto allocate_like() const -> BlockTensor
Allocate a tensor with identical validated structure.
Definition block_tensor.hpp:539
auto symmetry() const -> Symmetry
Return the explicit symmetry context.
Definition block_tensor.hpp:304
auto stored_keys() const noexcept -> std::span< key_type const >
Return stored keys in canonical lexicographic order.
Definition block_tensor.hpp:513
auto find_block(key_type const &key) -> std::optional< mutable_block_type >
Find a writable block without changing tensor structure.
Definition block_tensor.hpp:363
auto find_block(key_type const &key) const -> std::optional< const_block_type >
Find a read-only block without changing tensor structure.
Definition block_tensor.hpp:371
typename storage_type::const_block_type const_block_type
Definition block_tensor.hpp:184
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain)
Construct zero-initialized blocks for every symmetry-legal key.
Definition block_tensor.hpp:226
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain, std::initializer_list< key_type > stored_keys)
Allocate uninitialized sparse blocks from an initializer list of stored keys.
Definition block_tensor.hpp:274
auto codomain() const -> codomain_type const &
Return the ordered codomain value.
Definition block_tensor.hpp:310
decltype(auto) diagonal_values_by_ordinal(std::size_t ordinal)
Return compressed writable diagonal values by stable block ordinal.
Definition block_tensor.hpp:444
typename storage_type::mutable_block_type mutable_block_type
Definition block_tensor.hpp:183
decltype(auto) diagonal_values(key_type const &key)
Return the compressed writable diagonal values for one stored key.
Definition block_tensor.hpp:422
auto domain() const -> domain_type const &
Return the ordered domain value.
Definition block_tensor.hpp:307
std::remove_cv_t< T > value_type
Definition block_tensor.hpp:164
static constexpr auto dense_block_order() noexcept -> std::size_t
Return the dense mdspan order of each numerical block.
Definition block_tensor.hpp:319
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain)
Allocate every symmetry-legal block without numerical initialization.
Definition block_tensor.hpp:285
decltype(auto) async_block_by_ordinal(std::size_t ordinal) const
Return one independently scheduled value by stable canonical ordinal.
Definition block_tensor.hpp:504
static constexpr auto order() noexcept -> std::size_t
Return the compile-time tensor order.
Definition block_tensor.hpp:313
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, std::initializer_list< key_type > stored_keys)
Construct a sparse tensor from an initializer list of stored keys.
Definition block_tensor.hpp:216
typename storage_policy::template storage_t< element_type, static_key_coordinate_count, static_dense_block_order > storage_type
Definition block_tensor.hpp:182
decltype(auto) async_block(key_type const &key)
Return the independently scheduled value for one stored key.
Definition block_tensor.hpp:466
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector< key_type > stored_keys, Context &context)
Allocate uninitialized sparse blocks in an explicit leaf allocation context.
Definition block_tensor.hpp:258
auto stored_block_count() const noexcept -> std::size_t
Return the number of stored blocks.
Definition block_tensor.hpp:322
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector< key_type > stored_keys)
Allocate uninitialized sparse blocks from an explicit stored-key list.
Definition block_tensor.hpp:249
decltype(auto) async_block_by_ordinal(std::size_t ordinal)
Return one independently scheduled value by stable canonical ordinal.
Definition block_tensor.hpp:492
T element_type
Definition block_tensor.hpp:163
auto has_all_legal_blocks() const -> bool
Return whether this value currently stores every legal block.
Definition block_tensor.hpp:351
auto legal_block_count() const -> std::size_t
Return the number of symmetry-legal blocks.
Definition block_tensor.hpp:325
decltype(auto) diagonal_values(key_type const &key) const
Return the compressed read-only diagonal values for one stored key.
Definition block_tensor.hpp:434
auto contains(key_type const &key) const -> bool
Return whether a key has an allocated numerical block.
Definition block_tensor.hpp:360
auto block(key_type const &key) const -> const_block_type
Return a read-only stored block.
Definition block_tensor.hpp:389
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector< key_type > stored_keys, Context &context)
Construct a sparse tensor in an explicit leaf allocation context.
Definition block_tensor.hpp:200
auto block_by_ordinal(std::size_t ordinal) -> mutable_block_type
Return a writable block TensorView by stable canonical ordinal.
Definition block_tensor.hpp:400
decltype(auto) diagonal_values_by_ordinal(std::size_t ordinal) const
Return compressed read-only diagonal values by stable block ordinal.
Definition block_tensor.hpp:453
Storage storage_policy
Definition block_tensor.hpp:167
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector< key_type > stored_keys)
Construct zero-initialized sparse blocks from an explicit stored-key list.
Definition block_tensor.hpp:192
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain, Context &context)
Allocate uninitialized complete blocks in an explicit leaf allocation context.
Definition block_tensor.hpp:293
auto storage() noexcept -> storage_type &
Return the concrete storage value.
Definition block_tensor.hpp:522
auto storage() const noexcept -> storage_type const &
Return the concrete storage value.
Definition block_tensor.hpp:525
static constexpr auto backend_selector() noexcept -> backend_selector_type
Return the default dense-leaf backend selector for this storage.
Definition block_tensor.hpp:516
DomainType domain_type
Definition block_tensor.hpp:165
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, Context &context)
Construct a complete tensor in an explicit leaf allocation context.
Definition block_tensor.hpp:234
auto block(key_type const &key) -> mutable_block_type
Return a writable stored block.
Definition block_tensor.hpp:380
auto legal_block_keys() const -> std::vector< key_type >
Enumerate every symmetry-legal block key in canonical order.
Definition block_tensor.hpp:339
CodomainType codomain_type
Definition block_tensor.hpp:166
auto allocate_like(uninitialized_t) const -> BlockTensor
Allocate uninitialized blocks with identical validated structure.
Definition block_tensor.hpp:551
decltype(auto) allocation_context() const noexcept
Return the leaf context used for compatible result allocations.
Definition block_tensor.hpp:528
decltype(auto) async_block(key_type const &key) const
Return the independently scheduled value for one stored key.
Definition block_tensor.hpp:479
static auto identity(Symmetry sym) -> QNum
Return the identity irrep of a given symmetry.
Definition qnum.hpp:73
Public handle to a canonicalized direct-product symmetry specification.
Definition symmetry.hpp:24
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
BlockTensor storage which contains every symmetry-legal block.
Definition block_tensor_storage.hpp:63
BlockTensor storage whose stored key set may omit legal blocks.
Definition block_tensor_storage.hpp:58
Defines the generic categorical dual-space adaptor.
Domain
MKL computation domains accepted by domain-specific thread controls.
Definition backend_mkl.hpp:35
Defines immutable ordered local-state spaces.
Defines ordered domain and codomain space values for tensor morphisms.
auto validate(LuRefinementPrecision< F, W, R > p, RefinementOptions< make_real_t< R > > const &options)
Definition lu_refine.hpp:28
Definition async/async.hpp:26
constexpr uninitialized_t uninitialized
Explicit allocation tag for overwrite outputs and scratch space.
Definition common/initialization.hpp:22
Codomain(Spaces &&...) -> Codomain< std::remove_cvref_t< Spaces >... >
Deduce a codomain's concrete value types.
auto dual(SpaceType const &space) -> Dual< std::remove_cvref_t< SpaceType > >
Construct an explicitly dual basis without changing occurrence order.
Definition dual_space.hpp:244
StorageInitialization
Numerical initialization requested from a storage implementation.
Definition common/initialization.hpp:26
std::size_t span
Definition presentation.cpp:2017
Defines single-irrep tensor spaces.
Request storage whose numerical values must be written before being read.
Definition common/initialization.hpp:17