Skip to content

Commit

Permalink
Add more constructors for mdarray
Browse files Browse the repository at this point in the history
  • Loading branch information
crtrott committed Mar 15, 2024
1 parent b9e42b9 commit c6a9406
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 22 deletions.
116 changes: 94 additions & 22 deletions examples/mdarray_ctors/mdarray_ctors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
//
//@HEADER

#define MDARRAY_SUPPORT_ALLOC
#define MDARRAY_SUPPORT_ITERATOR
#define MDARRAY_SUPPORT_INITLIST

#include <mdspan/mdspan.hpp>
#include <mdspan/mdarray.hpp>

#include <cassert>

#define SUPPORT_ALLOC

template<class mda_t, class ext_t, class map_t, class Container>
void check(mda_t& a, ext_t ext, map_t map, Container& c) {
Expand Down Expand Up @@ -116,33 +119,33 @@ void test_alloc_set() {
assert(a.container_size() == map_t(ext_t()).required_span_size());
}
{ // integrals -> never directly supported
#ifdef SUPPORT_ALLOC
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(ext_t(10, 15), alloc);
check(a, ext, map, c);
#endif
}
{ // extents
#ifdef SUPPORT_ALLOC
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(ext, alloc);
check(a, ext, map, c);
#endif
}
{ // mapping
#ifdef SUPPORT_ALLOC
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(map, alloc);
check(a, ext, map, c);
#endif
}
{ // extents + container
#ifdef SUPPORT_ALLOC
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(ext, c, alloc);
#else
mda_t a(ext, std::move(Container(c,alloc)));
#endif
check(a, ext, map, c);
}
{ // mapping + container
#ifdef SUPPORT_ALLOC
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(map, c, alloc);
#else
mda_t a(map, std::move(Container(c,alloc)));
Expand All @@ -152,7 +155,7 @@ void test_alloc_set() {
{ // extents + move(container)
auto c2 = c;
double* ptr = c2.data();
#ifdef SUPPORT_ALLOC
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(ext, std::move(c2), alloc);
#else
mda_t a(ext, std::move(Container(std::move(c2),alloc)));
Expand All @@ -163,7 +166,7 @@ void test_alloc_set() {
{ // mapping + move(container)
auto c2 = c;
double* ptr = c2.data();
#ifdef SUPPORT_ALLOC
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(map, std::move(c2), alloc);
#else
mda_t a(map, std::move(Container(std::move(c2),alloc)));
Expand Down Expand Up @@ -204,63 +207,132 @@ void test_value_set() {
assert(a(0,0)==99);
}
{ // extents
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(ext, 99, alloc);
#else
mda_t a(ext, std::move(Container(99, alloc)));
#endif
check(a, ext, map, c);
assert(a(0,0)==99);
}
{ // mapping
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(map, 99, alloc);
#else
mda_t a(map, std::move(Container(99, alloc)));
#endif
check(a, ext, map, c);
assert(a(0,0)==99);
}
}

#ifdef MDARRAY_SUPPORT_ITERATOR
// ctors from iterator 2+2
// requires container constructible from iterators
// precondition: Container(begin, end).size() >= map.required_span_size()
template<class mda_t, class Container>
void test_value_set() {
void test_iterator_set() {
using ext_t = typename mda_t::extents_type;
using map_t = typename mda_t::mapping_type;
ext_t ext(10, 15);
map_t map(ext);
Container c(map.required_span_size());
c[0] = 99;
auto alloc = std::allocator<typename mda_t::element_type>();

{ // default construction
mda_t a;
assert(a.extents() == ext_t());
assert(a.container_size() == map_t(ext_t()).required_span_size());
}
{ // integrals -> never directly supported
mda_t a(ext_t(10, 15), 99);
mda_t a(ext_t(10, 15), c.begin(), c.end());
check(a, ext, map, c);
assert(a(0,0)==99);
}
{ // extents
mda_t a(ext, 99);
mda_t a(ext, c.begin(), c.end());
check(a, ext, map, c);
assert(a(0,0)==99);
}
{ // mapping
mda_t a(map, 99);
mda_t a(map, c.begin(), c.end());
check(a, ext, map, c);
assert(a(0,0)==99);
}
{ // extents
mda_t a(ext, 99, alloc);
#ifdef MDSPAN_SUPPORT_ALLOC
mda_t a(ext, c.begin(), c.end(), alloc);
#else
mda_t a(ext, std::move(Container(c.begin(), c.end(), alloc)));
#endif
check(a, ext, map, c);
assert(a(0,0)==99);
}
{ // mapping
mda_t a(map, 99, alloc);
#ifdef MDSPAN_SUPPORT_ALLOC
mda_t a(map, c.begin(), c.end(), alloc);
#else
mda_t a(map, std::move(Container(c.begin(), c.end(), alloc)));
#endif
check(a, ext, map, c);
assert(a(0,0)==99);
}
}
#endif

#ifdef MDARRAY_SUPPORT_INITLIST
// ctors from iterator 2+2
template<class mda_t, class Container>
void test_initlist_set() {
using ext_t = typename mda_t::extents_type;
using map_t = typename mda_t::mapping_type;
ext_t ext(2, 3);
map_t map(ext);
Container c({99,2,3,4,5,6});
auto alloc = std::allocator<typename mda_t::element_type>();

{ // integrals -> never directly supported
mda_t a(ext_t(2, 3), {99,2,3,4,5,6});
check(a, ext, map, c);
assert(a(0,0)==99);
}
{ // extents
mda_t a(ext, {99,2,3,4,5,6});
check(a, ext, map, c);
assert(a(0,0)==99);
}
{ // mapping
mda_t a(map, {99,2,3,4,5,6});
check(a, ext, map, c);
assert(a(0,0)==99);
}
{ // extents
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(ext, {99,2,3,4,5,6}, alloc);
#else
mda_t a(ext, std::move(Container({99,2,3,4,5,6}, alloc)));
#endif
check(a, ext, map, c);
assert(a(0,0)==99);
}
{ // mapping
#ifdef MDARRAY_SUPPORT_ALLOC
mda_t a(map, {99,2,3,4,5,6}, alloc);
#else
mda_t a(map, std::move(Container({99,2,3,4,5,6}, alloc)));
#endif
check(a, ext, map, c);
assert(a(0,0)==99);
}
}
#endif


int main(int argc, char* argv[]) {
test_minimal_set<Kokkos::Experimental::mdarray<double, Kokkos::extents<int, std::dynamic_extent, std::dynamic_extent>>, std::vector<double>>();
test_alloc_set<Kokkos::Experimental::mdarray<double, Kokkos::extents<int, std::dynamic_extent, std::dynamic_extent>>, std::vector<double>>();
test_value_set<Kokkos::Experimental::mdarray<double, Kokkos::extents<int, std::dynamic_extent, std::dynamic_extent>>, std::vector<double>>();
test_minimal_set<Kokkos::Experimental::mdarray<double, Kokkos::extents<int, Kokkos::dynamic_extent, Kokkos::dynamic_extent>>, std::vector<double>>();
test_alloc_set<Kokkos::Experimental::mdarray<double, Kokkos::extents<int, Kokkos::dynamic_extent, Kokkos::dynamic_extent>>, std::vector<double>>();
test_value_set<Kokkos::Experimental::mdarray<double, Kokkos::extents<int, Kokkos::dynamic_extent, Kokkos::dynamic_extent>>, std::vector<double>>();
#ifdef MDARRAY_SUPPORT_ITERATOR
test_iterator_set<Kokkos::Experimental::mdarray<double, Kokkos::extents<int, Kokkos::dynamic_extent, Kokkos::dynamic_extent>>, std::vector<double>>();
#endif
#ifdef MDARRAY_SUPPORT_INITLIST
test_initlist_set<Kokkos::Experimental::mdarray<double, Kokkos::extents<int, Kokkos::dynamic_extent, Kokkos::dynamic_extent>>, std::vector<double>>();
#endif
return 0;
}
113 changes: 113 additions & 0 deletions include/experimental/__p1684_bits/mdarray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "../mdspan"
#include <cassert>
#include <vector>
#include <type_traits>

namespace MDSPAN_IMPL_STANDARD_NAMESPACE {
namespace MDSPAN_IMPL_PROPOSED_NAMESPACE {
Expand Down Expand Up @@ -191,6 +192,7 @@ class mdarray {
static_assert( std::is_constructible<extents_type, OtherExtents>::value, "");
}

#ifdef MDARRAY_SUPPORT_ALLOC
// Constructors for container types constructible from a size and allocator
MDSPAN_TEMPLATE_REQUIRES(
class Alloc,
Expand Down Expand Up @@ -282,6 +284,117 @@ MDSPAN_TEMPLATE_REQUIRES(
{
static_assert( std::is_constructible<extents_type, OtherExtents>::value, "");
}
#endif

#ifdef MDARRAY_SUPPORT_ITERATOR
// Constructors for container types constructible from a size and allocator
MDSPAN_TEMPLATE_REQUIRES(
class BeginIter, class EndIter,
/* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, BeginIter, EndIter) &&
_MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type) &&
!_MDSPAN_TRAIT( std::is_same, typename std::iterator_traits<BeginIter>::iterator_category, void) &&
!_MDSPAN_TRAIT( std::is_same, typename std::iterator_traits<EndIter>::iterator_category, void))
)
MDSPAN_INLINE_FUNCTION
constexpr mdarray(const extents_type& exts, BeginIter b, EndIter e)
: map_(exts), ctr_(b, e)
{
assert(ctr_.size() >= map_.required_span_size());
}

MDSPAN_TEMPLATE_REQUIRES(
class BeginIter, class EndIter,
/* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, BeginIter, EndIter) &&
!_MDSPAN_TRAIT( std::is_same, typename std::iterator_traits<BeginIter>::iterator_category, void) &&
!_MDSPAN_TRAIT( std::is_same, typename std::iterator_traits<EndIter>::iterator_category, void))
)
MDSPAN_INLINE_FUNCTION
constexpr mdarray(const mapping_type& map, BeginIter b, EndIter e)
: map_(map), ctr_(b, e)
{
assert(ctr_.size() >= map_.required_span_size());
}

#ifdef MDARRAY_SUPPORT_ALLOC
// Constructors for container types constructible from a size and allocator
MDSPAN_TEMPLATE_REQUIRES(
class BeginIter, class EndIter, class Alloc,
/* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, BeginIter, EndIter, Alloc) &&
_MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type) &&
!_MDSPAN_TRAIT( std::is_same, typename std::iterator_traits<BeginIter>::iterator_category, void) &&
!_MDSPAN_TRAIT( std::is_same, typename std::iterator_traits<EndIter>::iterator_category, void))
)
MDSPAN_INLINE_FUNCTION
constexpr mdarray(const extents_type& exts, BeginIter b, EndIter e, const Alloc& alloc)
: map_(exts), ctr_(b, e, alloc)
{
assert(ctr_.size() >= map_.required_span_size());
}

MDSPAN_TEMPLATE_REQUIRES(
class BeginIter, class EndIter, class Alloc,
/* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, BeginIter, EndIter, Alloc) &&
!_MDSPAN_TRAIT( std::is_same, typename std::iterator_traits<BeginIter>::iterator_category, void) &&
!_MDSPAN_TRAIT( std::is_same, typename std::iterator_traits<EndIter>::iterator_category, void))
)
MDSPAN_INLINE_FUNCTION
constexpr mdarray(const mapping_type& map, BeginIter b, EndIter e, const Alloc& alloc)
: map_(map), ctr_(b, e, alloc)
{
assert(ctr_.size() >= map_.required_span_size());
}
#endif
#endif

#ifdef MDARRAY_SUPPORT_INITLIST
// Constructors for container types constructible from a size and allocator
// MDSPAN_TEMPLATE_REQUIRES(
// /* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, std::initializer_list<value_type>) &&
// _MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type))
// )
MDSPAN_INLINE_FUNCTION
constexpr mdarray(const extents_type& exts, std::initializer_list<value_type> il)
: map_(exts), ctr_(il)
{
assert(ctr_.size() >= map_.required_span_size());
}

// MDSPAN_TEMPLATE_REQUIRES(
// /* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, std::initializer_list<value_type>))
// )
MDSPAN_INLINE_FUNCTION
constexpr mdarray(const mapping_type& map, std::initializer_list<value_type> il)
: map_(map), ctr_(il)
{
assert(ctr_.size() >= map_.required_span_size());
}

#ifdef MDARRAY_SUPPORT_ALLOC
// Constructors for container types constructible from a size and allocator
MDSPAN_TEMPLATE_REQUIRES(
class Alloc,
/* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, std::initializer_list<value_type>, Alloc) &&
_MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type))
)
MDSPAN_INLINE_FUNCTION
constexpr mdarray(const extents_type& exts, std::initializer_list<value_type> il, const Alloc& alloc)
: map_(exts), ctr_(il, alloc)
{
assert(ctr_.size() >= map_.required_span_size());
}

MDSPAN_TEMPLATE_REQUIRES(
class Alloc,
/* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, std::initializer_list<value_type>, Alloc))
)
MDSPAN_INLINE_FUNCTION
constexpr mdarray(const mapping_type& map, std::initializer_list<value_type> il, const Alloc& alloc)
: map_(map), ctr_(il, alloc)
{
assert(ctr_.size() >= map_.required_span_size());
}
#endif
#endif

// construction from mdspan
// TODO: needs proper fill operation not just assuming contiguous and construction from iterators
Expand Down

0 comments on commit c6a9406

Please sign in to comment.