1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#ifndef DUNE_COMMON_STD_LAYOUT_LEFT_HH
#define DUNE_COMMON_STD_LAYOUT_LEFT_HH
#include <array>
#include <type_traits>
#include <dune/common/indices.hh>
#include <dune/common/std/impl/fwd_layouts.hh>
namespace Dune::Std {
/// \brief A layout mapping where the leftmost extent has stride 1.
template <class Extents>
class layout_left::mapping
{
template <class> friend class mapping;
public:
using extents_type = Extents;
using size_type = typename extents_type::size_type;
using rank_type = typename extents_type::rank_type;
using index_type = typename extents_type::index_type;
using layout_type = layout_left;
/// \brief The default construction is possible for default constructible extents
constexpr mapping () noexcept = default;
/// \brief Copy constructor for the mapping
constexpr mapping (const mapping&) noexcept = default;
/// \brief Construct the mapping with from given extents
constexpr mapping (const extents_type& e) noexcept
: extents_(e)
{}
/// \brief Construct the mapping from another mapping with a different extents type
template <class OtherExtents,
std::enable_if_t<std::is_constructible_v<extents_type, OtherExtents>, int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(!std::is_convertible_v<OtherExtents, extents_type>)
#endif
constexpr mapping (const mapping<OtherExtents>& m) noexcept
: extents_(m.extents())
{}
/// \brief Construct the mapping from a layout_right
template <class OtherExtents, class E = extents_type,
std::enable_if_t<(E::rank() <= 1), int> = 0,
std::enable_if_t<std::is_constructible_v<extents_type, OtherExtents>, int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(!std::is_convertible_v<OtherExtents, extents_type>)
#endif
constexpr mapping (const layout_right::mapping<OtherExtents>& m) noexcept
: extents_(m.extents())
{}
/// \brief Construct the mapping from a layout_stride
template <class OtherExtents,
std::enable_if_t<std::is_constructible_v<extents_type, OtherExtents>, int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(extents_type::rank() > 0)
#endif
constexpr mapping (const layout_stride::mapping<OtherExtents>& m)
: extents_(m.extents())
{
#ifndef NDEBUG
if constexpr(extents_type::rank() > 0) {
index_type prod = 1;
for (rank_type r = 0; r < extents_type::rank()-1; ++r) {
assert(m.strides(r) == prod);
prod *= m.extents().extent(r);
}
assert(m.strides(extents_type::rank()-1) == prod);
}
#endif
}
/// \brief Copy-assignment for the mapping
constexpr mapping& operator= (const mapping&) noexcept = default;
constexpr const extents_type& extents () const noexcept { return extents_; }
constexpr index_type required_span_size () const noexcept { return extents_.product(); }
/// \brief Compute the offset i0 + E(0)*(i1 + E(1)*(i2 + E(2)*i3))
template <class... Indices,
std::enable_if_t<(sizeof...(Indices) == extents_type::rank()), int> = 0,
std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>), int> = 0,
std::enable_if_t<(... && std::is_nothrow_constructible_v<Indices, index_type>), int> = 0>
constexpr index_type operator() (Indices... ii) const noexcept
{
const std::array indices{index_type(std::move(ii))...};
index_type value = indices.back();
for (rank_type r = 1; r < extents_type::rank(); ++r) {
const rank_type j = extents_type::rank()-r;
value = indices[j-1] + extents_.extent(j-1) * value;
}
return value;
}
/// \brief The default offset for rank-0 tensors is 0
constexpr index_type operator() () const noexcept
{
return 0;
}
static constexpr bool is_always_unique () noexcept { return true; }
static constexpr bool is_always_exhaustive () noexcept { return true; }
static constexpr bool is_always_strided () noexcept { return true; }
static constexpr bool is_unique () noexcept { return true; }
static constexpr bool is_exhaustive () noexcept { return true; }
static constexpr bool is_strided () noexcept { return true; }
/// \brief The stride is the product of the extents `E(0)*E(1)*...*E(i-1)`
template <class E = extents_type,
std::enable_if_t<(E::rank() > 0), int> = 0>
constexpr index_type stride (rank_type i) const noexcept
{
assert(i < extents_type::rank());
index_type prod = 1;
for (rank_type r = 0; r < i; ++r)
prod *= extents().extent(r);
return prod;
}
template <class OtherExtents,
std::enable_if_t<(Extents::rank() == OtherExtents::rank()), int> = 0>
friend constexpr bool operator== (const mapping& a, const mapping<OtherExtents>& b) noexcept
{
return a.extents_ == b.extents_;
}
private:
[[no_unique_address]] extents_type extents_;
};
} // end namespace Dune::Std
#endif // DUNE_COMMON_STD_LAYOUT_LEFT_HH
|