Skip to content
Draft
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
114 changes: 114 additions & 0 deletions include/experimental/p3242_bits/copy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//@HEADER
// ************************************************************************
//
// Kokkos v. 4.0
// Copyright (2022) National Technology & Engineering
// Solutions of Sandia, LLC (NTESS).
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
// See https://kokkos.org/LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//@HEADER
#pragma once

#include "../__p0009_bits/default_accessor.hpp"
#include "../__p0009_bits/extents.hpp"
#include "../__p0009_bits/layout_left.hpp"
#include "../__p0009_bits/layout_right.hpp"
#include "../__p0009_bits/mdspan.hpp"
#include <array>
#include <cstring>
#include <functional>
#include <utility>
#include <algorithm>

namespace MDSPAN_IMPL_STANDARD_NAMESPACE {
namespace MDSPAN_IMPL_PROPOSED_NAMESPACE {
namespace detail {

template <class Extents, class F, class ArrayType>
constexpr void apply_fun_over_extents(const Extents &ext, F &&fun,
ArrayType &indices,
std::index_sequence<>) {
std::apply(std::forward<F>(fun), indices);
}

template <class Extents, class F, class ArrayType, size_t R, size_t... Ranks>
constexpr void apply_fun_over_extents(const Extents &ext, F &&fun,
ArrayType &indices,
std::index_sequence<R, Ranks...>) {
using index_type = typename Extents::index_type;
for (index_type i = 0; i < ext.extent(R); ++i) {
indices[R] = i;
apply_fun_over_extents(ext, std::forward<F>(fun), indices, std::index_sequence<Ranks...>{});
}
}

template <size_t N, class Indices> struct make_reverse_index_sequence_impl;

template <size_t N, size_t... Indices>
struct make_reverse_index_sequence_impl<N, std::index_sequence<Indices...>> {
using type = std::index_sequence<(N - 1 - Indices)...>;
};

template <size_t N>
using make_reverse_index_sequence = typename make_reverse_index_sequence_impl<
N, std::make_index_sequence<N>>::type;

template <class SrcMDSpanType, class DstMDSpanType>
struct mdspan_copy_impl {
using extents_type = typename DstMDSpanType::extents_type;

static constexpr void copy_over_extents(const extents_type &ext,
const SrcMDSpanType &src,
const DstMDSpanType &dst) {
// Generic copy algorithm; this assumes a roughly layout-right traversal
// but this may not be cache efficient if we can't determine anything about
// the layout memory ordering
constexpr auto rank = extents_type::rank();
auto indices = std::array<typename extents_type::index_type, rank>{};
apply_fun_over_extents(
ext, [&src, &dst](auto... idxs) { dst[idxs...] = src[idxs...]; },
indices, std::make_index_sequence<rank>{});
}
};

template <class ElementType, class SrcExtents, class SrcLayout, class DstExtents, class DstLayout>
requires (SrcLayout::template mapping<SrcExtents>::is_always_exhaustive() && DstLayout::template mapping<DstExtents>::is_always_exhaustive())
struct mdspan_copy_impl<
mdspan<ElementType, SrcExtents, SrcLayout>,
mdspan<ElementType, DstExtents, DstLayout>> {
using extents_type = DstExtents;
using src_mdspan_type = mdspan<ElementType, SrcExtents, layout_left,
default_accessor<ElementType>>;
using dst_mdspan_type = mdspan<ElementType, DstExtents, layout_left,
default_accessor<ElementType>>;

static constexpr void copy_over_extents(const extents_type &ext,
const src_mdspan_type &src,
const dst_mdspan_type &dst) {
std::copy(src.data_handle(), src.data_handle() + src.mapping().required_span_size(), dst.data_handle());
}
};
} // namespace detail

template <class SrcElementType, class SrcExtents, class SrcLayoutPolicy,
class SrcAccessorPolicy, class DstElementType, class DstExtents,
class DstLayoutPolicy, class DstAccessorPolicy>
constexpr void copy(
mdspan<SrcElementType, SrcExtents, SrcLayoutPolicy, SrcAccessorPolicy> src,
mdspan<DstElementType, DstExtents, DstLayoutPolicy, DstAccessorPolicy>
dst) {
using src_type =
mdspan<SrcElementType, SrcExtents, SrcLayoutPolicy, SrcAccessorPolicy>;
using dst_type =
mdspan<DstElementType, DstExtents, DstLayoutPolicy, DstAccessorPolicy>;
detail::mdspan_copy_impl<src_type, dst_type>::copy_over_extents(DstExtents{src.extents()},
src, dst);
}
} // namespace MDSPAN_IMPL_PROPOSED_NAMESPACE
} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE
1 change: 1 addition & 0 deletions include/mdspan/mdspan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#if MDSPAN_HAS_CXX_17
#include "../experimental/__p2642_bits/layout_padded.hpp"
#include "../experimental/__p2630_bits/submdspan.hpp"
#include "../experimental/p3242_bits/copy.hpp"
#endif
#include "../experimental/__p2389_bits/dims.hpp"

Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ if(NOT CMAKE_CXX_STANDARD STREQUAL "14")
mdspan_add_test(test_submdspan_static_slice)
mdspan_add_test(test_layout_padded_left ENABLE_PRECONDITIONS)
mdspan_add_test(test_layout_padded_right ENABLE_PRECONDITIONS)
mdspan_add_test(test_mdspan_copy_and_fill)
endif()
# both of those don't work yet since its using vector
if(NOT MDSPAN_ENABLE_CUDA AND NOT MDSPAN_ENABLE_HIP)
Expand Down
139 changes: 139 additions & 0 deletions tests/test_mdspan_copy_and_fill.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
//@HEADER
// ************************************************************************
//
// Kokkos v. 4.0
// Copyright (2022) National Technology & Engineering
// Solutions of Sandia, LLC (NTESS).
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
// See https://kokkos.org/LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//@HEADER

#include <mdspan/mdarray.hpp>
#include <mdspan/mdspan.hpp>
#include <array>
#include <gtest/gtest.h>

template <class T, class Layout, class Extents>
constexpr auto make_mdarray(const Extents &exts) {
Kokkos::Experimental::mdarray<T, Extents, Layout> mds{exts};
for (size_t i = 0; i < mds.mapping().required_span_size(); ++i)
mds.data()[i] = static_cast<T>(i);

return mds;
}

template <class T, class Extents, std::size_t... Indices>
constexpr auto make_constexpr_array_impl(std::index_sequence<Indices...>) {
constexpr auto sz = (Extents::static_extent(Indices) * ...);
std::array<T, sz> ret;
for (size_t i = 0; i < sz; ++i)
ret[i] = static_cast<T>(i);

return ret;
}

template <class Extents, std::size_t... Indices>
constexpr auto array_size_impl(std::index_sequence<Indices...>) {
return (Extents::static_extent(Indices) * ...);
}


template <class Extents>
constexpr size_t array_size() {
return array_size_impl<Extents>();
}


template <class T, class Extents>
constexpr auto make_constexpr_array() {
return make_constexpr_array_impl<T, Extents>(std::make_index_sequence<Extents::rank()>{});
}

template <class T, class Extents, class Layout, class SrcExtents,
class SrcLayout>
constexpr auto make_mdarray_copy(const Kokkos::mdspan<T, SrcExtents, SrcLayout> &src) {
Kokkos::Experimental::mdarray<T, Extents, Layout> dst{};
Kokkos::Experimental::copy(src, dst.to_mdspan());

return dst;
}

template <class T, class SrcLayout, class DstLayout, class SrcExtents,
class DstExtents>
constexpr bool test_mdspan_copy_check(const SrcExtents &src_exts,
const DstExtents &dst_exts) {
Kokkos::Experimental::mdarray<T, SrcExtents, SrcLayout> src1 =
make_mdarray<T, SrcLayout>(src_exts);
Kokkos::Experimental::mdarray<T, DstExtents, DstLayout> dst1{dst_exts};

if (dst1.container() == src1.container()) return false;
Kokkos::Experimental::copy(src1.to_mdspan(), dst1.to_mdspan());
return dst1.container() == src1.container();
}

template <class T, class SrcLayout, class DstLayout, class SrcExtents,
class DstExtents>
void test_mdspan_copy_impl(const SrcExtents &src_exts,
const DstExtents &dst_exts) {
ASSERT_TRUE(
(test_mdspan_copy_check<T, SrcLayout, DstLayout>(src_exts, dst_exts)));
}

template <class T, class SrcExtents, class SrcLayout, class DstExtents, class DstLayout>
constexpr bool test_mdspan_copy_constexpr_impl() {
auto arr = make_constexpr_array<T, SrcExtents>();
Kokkos::Experimental::mdarray<T, SrcExtents, SrcLayout, decltype(arr)> src1(SrcExtents{}, arr);
Kokkos::Experimental::mdarray<T, DstExtents, DstLayout> dst1{};

Kokkos::Experimental::copy(src1.to_mdspan(), dst1.to_mdspan());

for ( std::size_t i = 0; i < arr.size(); ++i )
if (dst1.container()[i] != src1.container()[i])
return false;

return true;
}

template <class T, class SrcExtents, class SrcLayout, class DstExtents, class DstLayout>
void test_mdspan_copy_constexpr() {
static_assert(test_mdspan_copy_constexpr_impl<T, SrcExtents, SrcLayout, DstExtents, DstLayout>());
}

TEST(TestMdspanCopyAndFill, test_mdspan_copy) {
test_mdspan_copy_impl<int, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::extents<size_t, 5, 3>{});
test_mdspan_copy_impl<double, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::extents<size_t, 5, 3>{});
test_mdspan_copy_impl<float, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::extents<size_t, 5, 3>{});

test_mdspan_copy_impl<int, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::extents<size_t, 5, 3>{});
test_mdspan_copy_impl<double, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::extents<size_t, 5, 3>{});
test_mdspan_copy_impl<float, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::extents<size_t, 5, 3>{});

test_mdspan_copy_impl<int, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::dextents<size_t, 2>{5, 3});
test_mdspan_copy_impl<double, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::dextents<size_t, 2>{5, 3});
test_mdspan_copy_impl<float, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::extents<size_t, 5, 3>{}, Kokkos::dextents<size_t, 2>{5, 3});

test_mdspan_copy_impl<int, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::dextents<size_t, 2>{5, 3});
test_mdspan_copy_impl<double, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::dextents<size_t, 2>{5, 3});
test_mdspan_copy_impl<float, Kokkos::layout_left, Kokkos::layout_left>(
Kokkos::dextents<size_t, 2>{5, 3}, Kokkos::dextents<size_t, 2>{5, 3});

test_mdspan_copy_constexpr<int, Kokkos::extents<size_t, 5, 3>, Kokkos::layout_left,
Kokkos::extents<size_t, 5, 3>, Kokkos::layout_left>();
}
Loading