43#include <gtest/gtest.h>
67template <
class M,
class... Args>
68concept CanCall =
requires(M
m, Args... args) {
m(args...); };
69template <
class M,
class... Args>
70concept CanCallAt =
requires(M
m, Args... args) {
m.at(args...); };
79TEST(AhMdspan, DetectionMacroIsDefined)
83 EXPECT_TRUE(v == 0 or v == 1);
86TEST(AhMdspan, DextentsRankAndRankDynamic)
88 using Ext = dextents<size_t, 3>;
89 static_assert(Ext::rank() == 3);
90 static_assert(Ext::rank_dynamic() == 3);
92 EXPECT_EQ(e.extent(0), 2u);
93 EXPECT_EQ(e.extent(1), 3u);
94 EXPECT_EQ(e.extent(2), 4u);
97TEST(AhMdspan, MixedStaticAndDynamicExtents)
101 static_assert(Ext::rank() == 2);
102 static_assert(Ext::rank_dynamic() == 1);
103 static_assert(Ext::static_extent(1) == 4);
104 static_assert(Ext::static_extent(0) == dynamic_extent);
107 EXPECT_EQ(e.extent(0), 7u);
108 EXPECT_EQ(e.extent(1), 4u);
111TEST(AhMdspan, ExtentsFromArray)
113 std::array<size_t, 2> shape{3, 5};
114 dextents<size_t, 2> e(shape);
115 EXPECT_EQ(e.extent(0), 3u);
116 EXPECT_EQ(e.extent(1), 5u);
121 dextents<size_t, 2> a(2, 3);
122 dextents<size_t, 2> b(2, 3);
123 dextents<size_t, 2> c(3, 2);
125 EXPECT_FALSE(a == c);
128TEST(AhMdspan, BasicConstructionAndShape)
130 std::vector<int> buf(2 * 3, 0);
133 EXPECT_EQ(
m.rank(), 2u);
134 EXPECT_EQ(
m.extent(0), 2u);
135 EXPECT_EQ(
m.extent(1), 3u);
136 EXPECT_EQ(
m.
size(), 6u);
138 EXPECT_EQ(
m.data_handle(), buf.data());
141TEST(AhMdspan, OperatorRequiresExactRankArguments)
143 std::vector<int> buf(6, 0);
147 static_assert(std::is_invocable_v<
decltype(
m),
int,
int>);
150 static_assert(not std::is_invocable_v<
decltype(
m),
int>);
151 static_assert(not std::is_invocable_v<
decltype(
m),
int,
int,
int>);
154TEST(AhMdspan, ConstructFromArrayOfDynamicExtents)
156 std::vector<int> buf(6, 0);
157 std::array<size_t, 2> shape{2, 3};
159 EXPECT_EQ(
m.extent(0), 2u);
160 EXPECT_EQ(
m.extent(1), 3u);
163TEST(AhMdspan, RowMajorIsDefaultAndMatchesFlatBufferOrder)
167 std::vector<int> buf(2 * 3, 0);
171 for (
size_t i = 0; i <
m.extent(0); ++i)
172 for (
size_t j = 0; j <
m.extent(1); ++j)
175 EXPECT_EQ(buf, (std::vector<int>{0, 1, 2, 3, 4, 5}));
178TEST(AhMdspan, LayoutLeftIsColumnMajor)
181 std::vector<int> buf(2 * 3, 0);
185 for (
size_t j = 0; j <
m.extent(1); ++j)
186 for (
size_t i = 0; i <
m.extent(0); ++i)
189 EXPECT_EQ(buf, (std::vector<int>{0, 1, 2, 3, 4, 5}));
192TEST(AhMdspan, WriteThroughViewIsVisibleThroughBuffer)
194 std::vector<double> buf(4, 0.0);
200 EXPECT_EQ(buf, (std::vector<double>{1.0, 2.0, 3.0, 4.0}));
203TEST(AhMdspan, ReadOnlyViewOverConstElement)
205 const std::vector<int> buf{9, 8, 7, 6};
209 static_assert(std::is_const_v<std::remove_reference_t<
decltype(
m(0))>>);
212TEST(AhMdspan, AtThrowsOnOutOfRangeIndex)
214 std::vector<int> buf(6, 0);
216 EXPECT_NO_THROW((
void)
m.at(1, 2));
217 EXPECT_THROW((
void)
m.at(2, 0), std::out_of_range);
218 EXPECT_THROW((
void)
m.at(0, 3), std::out_of_range);
221TEST(AhMdspan, OneDimensionalView)
223 std::vector<int> buf{10, 20, 30};
225 EXPECT_EQ(
m.rank(), 1u);
230TEST(AhMdspan, ThreeDimensionalRowMajorRoundTrip)
232 std::vector<int> buf(2 * 2 * 2, -1);
236 for (
size_t i = 0; i < 2; ++i)
237 for (
size_t j = 0; j < 2; ++j)
238 for (
size_t k = 0;
k < 2; ++
k)
243 EXPECT_EQ(
m(1, 1, 1), 7);
244 EXPECT_EQ(buf.back(), 7);
247TEST(AhMdspan, DefaultConstructedIsEmptyWithNullData)
250 EXPECT_EQ(
m.data_handle(),
nullptr);
252 EXPECT_EQ(
m.
size(), 0u);
255TEST(AhMdspan, MultipleIndependentViewsOverSameBufferDoNotInterfere)
257 std::vector<int> buf(4, 0);
261 EXPECT_EQ(m2(0, 0), 42);
264TEST(AhMdspan, MutableViewConvertsImplicitlyToConstView)
267 int buf[4] = {1, 2, 3, 4};
271 EXPECT_EQ(reader(
m), 4);
#define ALEPH_HAS_STD_MDSPAN
Non-owning multidimensional array view (Aleph::mdspan).
Shape (per-axis sizes) of an mdspan, mixing compile-time and run-time extents.
Non-owning view of a contiguous buffer as a multidimensional grid.
constexpr size_t size() const noexcept
Returns the number of entries in the table.
void empty()
Clears all entries and resets to default capacity.
constexpr size_t dynamic_extent
Sentinel marking an axis whose extent is only known at run time.
typename decltype(mdspan_detail::dextents_of< IndexType >(std::make_index_sequence< Rank >{}))::type dextents
extents<IndexType, ...> with all Rank axes dynamic — the common case.
Column-major layout: the first axis varies fastest (Fortran convention).
Row-major layout: the last axis varies fastest (C convention).
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)