Skip to content

Commit

Permalink
Fix size_s / size for std:: ranges
Browse files Browse the repository at this point in the history
* ra/base.hh (size_s): Avoid tuple_size which doesn't do what we need.
  (from_ravel): Renamed from ravel_from_iterators, take range instead.
* test/small-0.cc: More tests for from_ravel.

This patch is backported from c++23 branch 8c47009.
  • Loading branch information
lloda committed May 27, 2024
1 parent 17b6677 commit 3c06656
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 5 deletions.
7 changes: 6 additions & 1 deletion ra/base.hh
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ RA_IS_DEF(is_iterator, IteratorConcept<A>)
template <class A> concept is_ra = is_iterator<A> || SliceConcept<A>;
template <class A> concept is_builtin_array = std::is_array_v<std::remove_cvref_t<A>>;
RA_IS_DEF(is_fov, (!is_scalar<A> && !is_ra<A> && !is_builtin_array<A> && std::ranges::bidirectional_range<A>))
template <class> constexpr bool is_std_array = false; // snowflake
template <class T, std::size_t N> constexpr bool is_std_array<std::array<T, N>> = true;

template <class VV> requires (!std::is_void_v<VV>)
consteval rank_t
Expand Down Expand Up @@ -177,8 +179,11 @@ size_s()
return 1;
} else if constexpr (is_builtin_array<V>) {
return std::apply([] (auto ... i) { return (std::extent_v<V, i> * ... * 1); }, mp::iota<rs> {});
} else if constexpr (is_fov<V> && requires { std::tuple_size<V>::value; }) {
} else if constexpr (is_std_array<V>) {
return std::tuple_size_v<V>;
} else if constexpr (is_fov<V> && requires { V::size(); }) {
return V::size();
// FIXME no std::dynamic_extent in gcc 11
} else if constexpr (is_fov<V> || rs==ANY) {
return ANY;
} else if constexpr (requires { V::size_s(); }) {
Expand Down
8 changes: 5 additions & 3 deletions ra/small.hh
Original file line number Diff line number Diff line change
Expand Up @@ -625,13 +625,15 @@ SmallArray<T, lens, steps, std::tuple<nested_args ...>>

template <class A0, class ... A> SmallArray(A0, A ...) -> Small<A0, 1+sizeof...(A)>;

// FIXME tagged ravel constructor. Then we can pass any rank 1 thing not just iterator pairs.
// FIXME tagged ravel constructor
template <class A>
constexpr auto
ravel_from_iterators(auto && begin, auto && end)
from_ravel(auto && b)
{
A a;
std::copy(RA_FWD(begin), RA_FWD(end), a.begin());
RA_CHECK(1==ra::rank(b) && ra::size(b)==ra::size(a),
"Bad ravel argument [", ra::noshape, ra::shape(b), "] expecting [", ra::size(a), "].");
std::ranges::copy(RA_FWD(b), a.begin());
return a;
}

Expand Down
17 changes: 16 additions & 1 deletion test/small-0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ std::string typecheck(auto && a)
int main()
{
TestRecorder tr;
tr.section("std::array is used internally so these are fundamental");
{
static_assert(3==ra::size(std::array { 3, 4, 5 }));
static_assert(3==ra::size_s(std::array { 3, 4, 5 }));
}
tr.section("Small isn't an aggregate so T; and T {}; are the same, unlike std::array");
{
std::array<int, 9> a; // default init, unlike {} which is aggregate init
Expand Down Expand Up @@ -386,11 +391,21 @@ int main()
tr.section("raveling constructor from iterators");
{
int AA[4] = { 1, 2, 3, 4 };
auto a = ra::ravel_from_iterators<ra::Small<int, 2, 2>>(AA, AA+4);
auto a = ra::from_ravel<ra::Small<int, 2, 2>>(std::ranges::subrange(AA, AA+4));
tr.test_eq(1, a(0, 0));
tr.test_eq(2, a(0, 1));
tr.test_eq(3, a(1, 0));
tr.test_eq(4, a(1, 1));
auto b = ra::from_ravel<ra::Small<int, 2, 2>>(AA);
tr.test_eq(1, b(0, 0));
tr.test_eq(2, b(0, 1));
tr.test_eq(3, b(1, 0));
tr.test_eq(4, b(1, 1));
auto c = ra::from_ravel<ra::Small<int, 2, 2>>(ra::Small<int, 4> { 1, 2, 3, 4});
tr.test_eq(1, c(0, 0));
tr.test_eq(2, c(0, 1));
tr.test_eq(3, c(1, 0));
tr.test_eq(4, c(1, 1));
}
tr.section("nested Small I");
{
Expand Down

0 comments on commit 3c06656

Please sign in to comment.