Skip to content

Commit 9101d09

Browse files
authored
Add generic indexer (#583)
* Add generic indexer * Add test for GenericIndexer * Clang format * Update changelog
1 parent 36dee9c commit 9101d09

4 files changed

Lines changed: 129 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Added (new features/APIs/variables/...)
66
- [[PR556]](https://github.com/lanl/singularity-eos/pull/556) Add introspection into types available in the variant
77
- [[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
8+
- [[PR583]](https://github.com/lanl/singularity-eos/pull/583) Added GenericIndexer class to provide more complex array indirection
89

910
### Fixed (Repair bugs, etc)
1011
- [[PR567]](https://github.com/lanl/singularity-eos/pull/567) Fixed an OOB array access bug in the Fixed T PTE solver
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//------------------------------------------------------------------------------
2+
// © 2021-2025. Triad National Security, LLC. All rights reserved. This
3+
// program was produced under U.S. Government contract 89233218CNA000001
4+
// for Los Alamos National Laboratory (LANL), which is operated by Triad
5+
// National Security, LLC for the U.S. Department of Energy/National
6+
// Nuclear Security Administration. All rights in the program are
7+
// reserved by Triad National Security, LLC, and the U.S. Department of
8+
// Energy/National Nuclear Security Administration. The Government is
9+
// granted for itself and others acting on its behalf a nonexclusive,
10+
// paid-up, irrevocable worldwide license in this material to reproduce,
11+
// prepare derivative works, distribute copies to the public, perform
12+
// publicly and display publicly, and to permit others to do so.
13+
//------------------------------------------------------------------------------
14+
15+
#ifndef SINGULARITY_EOS_BASE_GENERIC_INDEXER_HPP_
16+
#define SINGULARITY_EOS_BASE_GENERIC_INDEXER_HPP_
17+
18+
#include <utility>
19+
20+
namespace singularity {
21+
22+
template <typename Arr, typename Map>
23+
struct GenericIndexer {
24+
Arr arr_;
25+
Map map_;
26+
27+
template <typename ArrT_, typename MapT_>
28+
constexpr GenericIndexer(ArrT_ &&arr_in, MapT_ &&map_in)
29+
: arr_(std::forward<ArrT_>(arr_in)), map_(std::forward<MapT_>(map_in)) {}
30+
31+
// & : non-const lvalue
32+
template <class I>
33+
constexpr decltype(auto) operator[](I i) & {
34+
return arr_[map_[i]];
35+
}
36+
37+
// const& : const lvalue
38+
template <class I>
39+
constexpr decltype(auto) operator[](I i) const & {
40+
return arr_[map_[i]];
41+
}
42+
43+
// && : rvalue (indexer is a temporary) — forward arr_’s value category
44+
template <class I>
45+
constexpr decltype(auto) operator[](I i) && {
46+
return std::forward<Arr>(arr_)[map_[i]]; // move only if Arr is a value type
47+
}
48+
49+
// const rvalue indexer
50+
template <class I>
51+
constexpr decltype(auto) operator[](I i) const && {
52+
return std::forward<const Arr>(arr_)[map_[i]]; // preserves const
53+
}
54+
};
55+
56+
// CTAD: preserve references for lvalues, decay for rvalues
57+
template <class ArrT_, class MapT_>
58+
GenericIndexer(ArrT_ &&, MapT_ &&) -> GenericIndexer<ArrT_, MapT_>;
59+
60+
} // namespace singularity
61+
62+
#endif // #ifndef SINGULARITY_EOS_BASE_GENERIC_INDEXER_HPP_

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ add_executable(
4040
test_variadic_utils.cpp
4141
test_bounds.cpp
4242
test_indexable_types.cpp
43+
test_generic_indxer.cpp
4344
)
4445

4546
add_executable(

test/test_generic_indxer.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//------------------------------------------------------------------------------
2+
// © 2021-2025. Triad National Security, LLC. All rights reserved. This
3+
// program was produced under U.S. Government contract 89233218CNA000001
4+
// for Los Alamos National Laboratory (LANL), which is operated by Triad
5+
// National Security, LLC for the U.S. Department of Energy/National
6+
// Nuclear Security Administration. All rights in the program are
7+
// reserved by Triad National Security, LLC, and the U.S. Department of
8+
// Energy/National Nuclear Security Administration. The Government is
9+
// granted for itself and others acting on its behalf a nonexclusive,
10+
// paid-up, irrevocable worldwide license in this material to reproduce,
11+
// prepare derivative works, distribute copies to the public, perform
12+
// publicly and display publicly, and to permit others to do so.
13+
//------------------------------------------------------------------------------
14+
15+
#include <array>
16+
17+
#include <ports-of-call/portability.hpp>
18+
#include <singularity-eos/base/generic_indexer.hpp>
19+
20+
#ifndef CATCH_CONFIG_FAST_COMPILE
21+
#define CATCH_CONFIG_FAST_COMPILE
22+
#include <catch2/catch_test_macros.hpp>
23+
#endif
24+
#include <catch2/matchers/catch_matchers_floating_point.hpp>
25+
26+
SCENARIO("Generic Indexer", "[GenericIndexer]") {
27+
GIVEN("An array of arays populated with data") {
28+
constexpr std::size_t n = 5;
29+
constexpr std::size_t m = 7;
30+
auto data = std::array<std::array<Real, m>, n>{};
31+
for (std::size_t i = 0; i < n; i++) {
32+
for (std::size_t j = 0; j < m; j++) {
33+
data[i][j] = (i + 1) * (j + 1);
34+
}
35+
}
36+
WHEN("A flattened array is created with the same size and populated with "
37+
"the same data") {
38+
auto flat_data = std::array<Real, n * m>{};
39+
for (std::size_t i = 0; i < n; i++) {
40+
for (std::size_t j = 0; j < m; j++) {
41+
flat_data[i * m + j] = data[i][j];
42+
}
43+
}
44+
WHEN("We use the generic indexer to index into material data") {
45+
struct constant_offset {
46+
std::size_t offset;
47+
constexpr constant_offset(std::size_t offset_) : offset{offset_} {}
48+
constexpr std::size_t operator[](std::size_t i) { return i * offset; }
49+
};
50+
auto mat_indexer =
51+
singularity::GenericIndexer(flat_data.data(), constant_offset{m});
52+
THEN("The data returned should be same as if we accessed the array of "
53+
"arrays") {
54+
for (std::size_t i = 0; i < n; i++) {
55+
auto *mat_array = &mat_indexer[i];
56+
for (std::size_t j = 0; j < m; j++) {
57+
INFO("i: " << i << " j: " << j);
58+
CHECK_THAT(data[i][j], Catch::Matchers::WithinRel(mat_array[j], 1.0e-12));
59+
}
60+
}
61+
}
62+
}
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)