Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Added (new features/APIs/variables/...)
- [[PR556]](https://github.com/lanl/singularity-eos/pull/556) Add introspection into types available in the variant
- [[PR564]](https://github.com/lanl/singularity-eos/pull/564) Removed Get() function from IndexableTypes since it could have unexpected consequences when a type wasn't present
- [[PR583]](https://github.com/lanl/singularity-eos/pull/583) Added GenericIndexer class to provide more complex array indirection

### Fixed (Repair bugs, etc)
- [[PR567]](https://github.com/lanl/singularity-eos/pull/567) Fixed an OOB array access bug in the Fixed T PTE solver
Expand Down
62 changes: 62 additions & 0 deletions singularity-eos/base/generic_indexer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
// © 2021-2025. Triad National Security, LLC. All rights reserved. This
// program was produced under U.S. Government contract 89233218CNA000001
// for Los Alamos National Laboratory (LANL), which is operated by Triad
// National Security, LLC for the U.S. Department of Energy/National
// Nuclear Security Administration. All rights in the program are
// reserved by Triad National Security, LLC, and the U.S. Department of
// Energy/National Nuclear Security Administration. The Government is
// granted for itself and others acting on its behalf a nonexclusive,
// paid-up, irrevocable worldwide license in this material to reproduce,
// prepare derivative works, distribute copies to the public, perform
// publicly and display publicly, and to permit others to do so.
//------------------------------------------------------------------------------

#ifndef SINGULARITY_EOS_BASE_GENERIC_INDEXER_HPP_
#define SINGULARITY_EOS_BASE_GENERIC_INDEXER_HPP_

#include <utility>

namespace singularity {

template <typename Arr, typename Map>
struct GenericIndexer {
Arr arr_;
Map map_;

template <typename ArrT_, typename MapT_>
constexpr GenericIndexer(ArrT_ &&arr_in, MapT_ &&map_in)
: arr_(std::forward<ArrT_>(arr_in)), map_(std::forward<MapT_>(map_in)) {}

// & : non-const lvalue
template <class I>
constexpr decltype(auto) operator[](I i) & {
return arr_[map_[i]];
}

// const& : const lvalue
template <class I>
constexpr decltype(auto) operator[](I i) const & {
return arr_[map_[i]];
}

// && : rvalue (indexer is a temporary) — forward arr_’s value category
template <class I>
constexpr decltype(auto) operator[](I i) && {
return std::forward<Arr>(arr_)[map_[i]]; // move only if Arr is a value type
}

// const rvalue indexer
template <class I>
constexpr decltype(auto) operator[](I i) const && {
return std::forward<const Arr>(arr_)[map_[i]]; // preserves const
}
};

// CTAD: preserve references for lvalues, decay for rvalues
template <class ArrT_, class MapT_>
GenericIndexer(ArrT_ &&, MapT_ &&) -> GenericIndexer<ArrT_, MapT_>;

} // namespace singularity

#endif // #ifndef SINGULARITY_EOS_BASE_GENERIC_INDEXER_HPP_
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ add_executable(
test_variadic_utils.cpp
test_bounds.cpp
test_indexable_types.cpp
test_generic_indxer.cpp
)

add_executable(
Expand Down
65 changes: 65 additions & 0 deletions test/test_generic_indxer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//------------------------------------------------------------------------------
// © 2021-2025. Triad National Security, LLC. All rights reserved. This
// program was produced under U.S. Government contract 89233218CNA000001
// for Los Alamos National Laboratory (LANL), which is operated by Triad
// National Security, LLC for the U.S. Department of Energy/National
// Nuclear Security Administration. All rights in the program are
// reserved by Triad National Security, LLC, and the U.S. Department of
// Energy/National Nuclear Security Administration. The Government is
// granted for itself and others acting on its behalf a nonexclusive,
// paid-up, irrevocable worldwide license in this material to reproduce,
// prepare derivative works, distribute copies to the public, perform
// publicly and display publicly, and to permit others to do so.
//------------------------------------------------------------------------------

#include <array>

#include <ports-of-call/portability.hpp>
#include <singularity-eos/base/generic_indexer.hpp>

#ifndef CATCH_CONFIG_FAST_COMPILE
#define CATCH_CONFIG_FAST_COMPILE
#include <catch2/catch_test_macros.hpp>
#endif
#include <catch2/matchers/catch_matchers_floating_point.hpp>

SCENARIO("Generic Indexer", "[GenericIndexer]") {
GIVEN("An array of arays populated with data") {
constexpr std::size_t n = 5;
constexpr std::size_t m = 7;
auto data = std::array<std::array<Real, m>, n>{};
for (std::size_t i = 0; i < n; i++) {
for (std::size_t j = 0; j < m; j++) {
data[i][j] = (i + 1) * (j + 1);
}
}
WHEN("A flattened array is created with the same size and populated with "
"the same data") {
auto flat_data = std::array<Real, n * m>{};
for (std::size_t i = 0; i < n; i++) {
for (std::size_t j = 0; j < m; j++) {
flat_data[i * m + j] = data[i][j];
}
}
WHEN("We use the generic indexer to index into material data") {
struct constant_offset {
std::size_t offset;
constexpr constant_offset(std::size_t offset_) : offset{offset_} {}
constexpr std::size_t operator[](std::size_t i) { return i * offset; }
};
auto mat_indexer =
singularity::GenericIndexer(flat_data.data(), constant_offset{m});
THEN("The data returned should be same as if we accessed the array of "
"arrays") {
for (std::size_t i = 0; i < n; i++) {
auto *mat_array = &mat_indexer[i];
for (std::size_t j = 0; j < m; j++) {
INFO("i: " << i << " j: " << j);
CHECK_THAT(data[i][j], Catch::Matchers::WithinRel(mat_array[j], 1.0e-12));
}
}
}
}
}
}
}