Loading...
Searching...
No Matches
layout_stride.hh
Go to the documentation of this file.
// -*- 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_STRIDE_HH
#define DUNE_COMMON_STD_LAYOUT_STRIDE_HH
#include <array>
#include <span>
#include <type_traits>
#include <dune/common/indices.hh>
#include <dune/common/std/no_unique_address.hh>
#include <dune/common/std/impl/fwd_layouts.hh>
namespace Dune::Std {
template <class Extents>
class layout_stride::mapping
{
template <class> friend class mapping;
static constexpr typename Extents::rank_type rank_ = Extents::rank();
public:
using extents_type = Extents;
using index_type = typename extents_type::index_type;
using size_type = typename extents_type::size_type;
using rank_type = typename extents_type::rank_type;
using layout_type = layout_stride;
private:
using strides_type = std::array<index_type,rank_>;
public:
constexpr mapping () noexcept
: mapping(layout_right::template mapping<extents_type>{})
{}
constexpr mapping (const mapping&) noexcept = default;
template <class OtherIndexType,
std::enable_if_t<std::is_convertible_v<const OtherIndexType&, index_type>, int> = 0,
std::enable_if_t<std::is_nothrow_constructible_v<index_type, const OtherIndexType&>, int> = 0>
constexpr mapping (const extents_type& e, const std::array<OtherIndexType,rank_>& s) noexcept
: extents_(e)
, strides_{}
{
for (rank_type r = 0; r < rank_; ++r)
strides_[r] = s[r];
}
template <class OtherIndexType,
std::enable_if_t<std::is_convertible_v<const OtherIndexType&, index_type>, int> = 0,
std::enable_if_t<std::is_nothrow_constructible_v<index_type, const OtherIndexType&>, int> = 0>
constexpr mapping (const extents_type& e, const std::span<OtherIndexType,rank_>& s) noexcept
: extents_(e)
, strides_{}
{
for (rank_type r = 0; r < rank_; ++r)
strides_[r] = s[r];
}
template <class M,
std::enable_if_t<(M::extents_type::rank() == extents_type::rank()), int> = 0,
std::enable_if_t<(M::is_always_unique()), int> = 0,
std::enable_if_t<(M::is_always_strided()), int> = 0,
decltype(std::declval<M>().extents(), bool{}) = true,
decltype(std::declval<M>().stride(std::declval<rank_type>()), bool{}) = true>
constexpr mapping (const M& m) noexcept
: extents_(m.extents())
, strides_{}
{
for (rank_type r = 0; r < rank_; ++r)
strides_[r] = m.stride(r);
}
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 size(extents_,strides_);
}
template <class... Indices,
std::enable_if_t<(sizeof...(Indices) == 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<index_type, Indices> && ...), int> = 0>
constexpr index_type operator() (Indices... ii) const noexcept
{
return unpackIntegerSequence([&](auto... r) {
return ((static_cast<index_type>(ii)*strides_[r]) + ... + 0); },
std::make_index_sequence<rank_>{});
}
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 false; }
static constexpr bool is_always_strided () noexcept { return true; }
static constexpr bool is_unique () noexcept { return true; }
static constexpr bool is_strided () noexcept { return true; }
constexpr bool is_exhaustive () const noexcept
{
// Actually this could be improved. A strided layout can still be exhaustive.
// This test is more complicated to implement, though. See §24.7.3.4.7.4 line (5.2)
// in the C++ standard document N4971
return extents_type::rank() == 0 || (required_span_size() > 0 && required_span_size() == extents().product());
}
constexpr const strides_type& strides () const noexcept
{
return strides_;
}
template <class E = extents_type,
std::enable_if_t<(E::rank() > 0), int> = 0>
constexpr index_type stride (rank_type i) const noexcept
{
return strides_[i];
}
template <class OtherMapping,
std::enable_if_t<(OtherMapping::extents_type::rank() == extents_type::rank()), int> = 0,
std::enable_if_t<(OtherMapping::is_always_strided()), int> = 0>
friend constexpr bool operator== (const mapping& a, const OtherMapping& b) noexcept
{
if (offset(b))
return false;
if constexpr(extents_type::rank() == 0)
return true;
return a.extents_ == b.extents_ && a.strides_ == b.strides_;
}
private:
template <class E, class S>
static constexpr index_type size (const E& extents, const S& strides) noexcept
{
if constexpr (E::rank() == 0)
return 1;
else {
if (extents.product() == 0)
return 0;
else {
index_type result = 1;
for (rank_type r = 0; r < E::rank(); ++r)
result += (extents.extent(r)-1) * strides[r];
return result;
}
}
}
template <class M>
static constexpr size_type offset (const M& m) noexcept
{
if constexpr (M::extents_type::rank() == 0)
return m();
else {
if (m.required_span_size() == 0)
return 0;
else {
return unpackIntegerSequence([&](auto... r) {
return m((r,0)...); }, // map the index tuple (0,0...)
std::make_index_sequence<M::extents_type::rank()>{});
}
}
}
private:
DUNE_NO_UNIQUE_ADDRESS extents_type extents_;
strides_type strides_;
};
} // end namespace Dune::Std
#endif // DUNE_COMMON_STD_LAYOUT_STRIDE_HH
fwd_layouts.hh
no_unique_address.hh
DUNE_NO_UNIQUE_ADDRESS
#define DUNE_NO_UNIQUE_ADDRESS
Definition no_unique_address.hh:24
indices.hh
Dune::unpackIntegerSequence
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition indices.hh:124
Dune::size
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition integersequence.hh:75
Dune::Indices
Namespace with predefined compile time indices for the range [0,19].
Definition indices.hh:50
Dune::Std
Namespace for features backported from new C++ standards.
Definition algorithm.hh:19
Dune::Std::extents
Multidimensional index space with dynamic and static extents.
Definition extents.hh:55
Dune::Std::extents::extent
constexpr index_type extent(rank_type r) const noexcept
Return the extent of dimension i.
Definition extents.hh:101
Dune::Std::layout_right
A layout where the rightmost extent has stride 1, and strides increase right-to-left as the product o...
Definition fwd_layouts.hh:30
Dune::Std::layout_stride
A layout mapping where the strides are user-defined.
Definition fwd_layouts.hh:40
Dune::Std::layout_stride::mapping
A layout mapping where the strides are user-defined.
Definition layout_stride.hh:21
Dune::Std::layout_stride::mapping::extents_type
Extents extents_type
Definition layout_stride.hh:26
Dune::Std::layout_stride::mapping::layout_type
layout_stride layout_type
Definition layout_stride.hh:30
Dune::Std::layout_stride::mapping::operator=
constexpr mapping & operator=(const mapping &) noexcept=default
Copy-assignment for the mapping.
Dune::Std::layout_stride::mapping::is_exhaustive
constexpr bool is_exhaustive() const noexcept
Definition layout_stride.hh:120
Dune::Std::layout_stride::mapping::mapping
constexpr mapping() noexcept
The default construction initializes the strides from layout_right.
Definition layout_stride.hh:38
Dune::Std::layout_stride::mapping::mapping
constexpr mapping(const extents_type &e, const std::array< OtherIndexType, rank_ > &s) noexcept
Construct the mapping from given extents and strides.
Definition layout_stride.hh:49
Dune::Std::layout_stride::mapping::stride
constexpr index_type stride(rank_type i) const noexcept
Get the single stride i.
Definition layout_stride.hh:137
Dune::Std::layout_stride::mapping::index_type
typename extents_type::index_type index_type
Definition layout_stride.hh:27
Dune::Std::layout_stride::mapping::mapping
friend class mapping
Definition layout_stride.hh:22
Dune::Std::layout_stride::mapping::is_always_exhaustive
static constexpr bool is_always_exhaustive() noexcept
Definition layout_stride.hh:114
Dune::Std::layout_stride::mapping::extents
constexpr const extents_type & extents() const noexcept
Definition layout_stride.hh:87
Dune::Std::layout_stride::mapping::is_strided
static constexpr bool is_strided() noexcept
Definition layout_stride.hh:118
Dune::Std::layout_stride::mapping::operator==
friend constexpr bool operator==(const mapping &a, const OtherMapping &b) noexcept
Definition layout_stride.hh:145
Dune::Std::layout_stride::mapping::is_always_strided
static constexpr bool is_always_strided() noexcept
Definition layout_stride.hh:115
Dune::Std::layout_stride::mapping::required_span_size
constexpr index_type required_span_size() const noexcept
Return the sum 1 + (E(0)-1)*S(0) + (E(1)-1)*S(1) + ....
Definition layout_stride.hh:90
Dune::Std::layout_stride::mapping::strides
constexpr const strides_type & strides() const noexcept
Get the array of all strides.
Definition layout_stride.hh:129
Dune::Std::layout_stride::mapping::mapping
constexpr mapping(const mapping &) noexcept=default
Copy constructor for the mapping.
Dune::Std::layout_stride::mapping::rank_type
typename extents_type::rank_type rank_type
Definition layout_stride.hh:29
Dune::Std::layout_stride::mapping::is_unique
static constexpr bool is_unique() noexcept
Definition layout_stride.hh:117
Dune::Std::layout_stride::mapping::operator()
constexpr index_type operator()() const noexcept
The default offset for rank-0 tensors is 0.
Definition layout_stride.hh:108
Dune::Std::layout_stride::mapping::mapping
constexpr mapping(const extents_type &e, const std::span< OtherIndexType, rank_ > &s) noexcept
Construct the mapping from given extents and strides.
Definition layout_stride.hh:61
Dune::Std::layout_stride::mapping::size_type
typename extents_type::size_type size_type
Definition layout_stride.hh:28
Dune::Std::layout_stride::mapping::is_always_unique
static constexpr bool is_always_unique() noexcept
Definition layout_stride.hh:113