Loading...
Searching...
No Matches
hybridmultiindex.hh
Go to the documentation of this file.
// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=8 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 OR LGPL-3.0-or-later
#ifndef DUNE_COMMON_HYBRIDMULTIINDEX_HH
#define DUNE_COMMON_HYBRIDMULTIINDEX_HH
#include <cstddef>
#include <cassert>
#include <iostream>
#include <type_traits>
#include <dune/common/typetraits.hh>
#include <dune/common/indices.hh>
#include <dune/common/hybridutilities.hh>
namespace Dune {
// The Impl namespace collects some free standing functions helper functions
namespace Impl {
template<class T>
constexpr bool isHybridSizeT()
{
if constexpr (std::is_same_v<T, std::size_t>)
return true;
else
{
if constexpr (requires { T::value; })
return std::is_same_v<T, std::integral_constant<std::size_t, T::value>>;
else
return false;
}
}
template<class T>
constexpr auto castToHybridSizeT(T t)
{
if constexpr (Dune::IsIntegralConstant<T>::value)
{
using VT = typename T::value_type;
static_assert(
std::is_convertible_v<VT,std::size_t> &&
std::is_integral_v<VT> &&
T::value >= 0,
"HybridMultiIndex indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
return std::integral_constant<std::size_t, T::value>{};
}
if constexpr (std::is_integral_v<T>)
{
static_assert(
std::is_convertible_v<T,std::size_t> &&
std::is_integral_v<T>,
"HybridMultiIndex indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
assert(t >= 0 &&
"HybridMultiIndex indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
return std::size_t(t);
}
if constexpr (not (Dune::IsIntegralConstant<T>::value or std::is_integral_v<T>))
{
return std::size_t(0);
}
}
}
template<typename... T>
class HybridMultiIndex
{
// make sure that all indices use std::size_t as the underlying number type
static_assert((... && Impl::isHybridSizeT<T>()),
"HybridMultiIndex index storage must be std::size_t or std::integral_constant<std::size_t,v>");
public:
using index_sequence = std::index_sequence_for<T...>;
constexpr HybridMultiIndex() = default;
constexpr HybridMultiIndex(const HybridMultiIndex& tp) = default;
constexpr HybridMultiIndex(HybridMultiIndex&& tp) = default;
constexpr HybridMultiIndex& operator=(const HybridMultiIndex& tp) = default;
constexpr HybridMultiIndex& operator=(HybridMultiIndex&& tp) = default;
explicit constexpr HybridMultiIndex(std::tuple<T...> t)
: _data(t)
{}
template<typename... I>
requires ((sizeof...(T) > 0 && sizeof...(I) == sizeof...(T))
and ((std::is_integral_v<I> or Dune::IsIntegralConstant<I>::value) && ...))
explicit constexpr HybridMultiIndex(I... i)
: _data(Impl::castToHybridSizeT(i)...) // we assume that all arguments are convertible to the types T...
{}
[[nodiscard]] constexpr static index_sequence enumerate()
{
return {};
}
[[nodiscard]] constexpr static std::size_t size()
{
return sizeof...(T);
}
[[nodiscard]] constexpr static std::size_t max_size()
{
return size();
}
template<std::size_t i>
requires (sizeof...(T) > i)
[[nodiscard]] constexpr auto get() const
{
return std::get<i>(_data);
}
template<std::size_t i>
requires (sizeof...(T) > i)
[[nodiscard]] constexpr auto operator[](Dune::index_constant<i>) const
{
return std::get<i>(_data);
}
[[nodiscard]] constexpr std::size_t operator[](std::size_t pos) const
{
std::size_t entry = 0;
Dune::Hybrid::forEach(enumerate(), [&] (auto i) {
if (i==pos)
entry = (*this)[i];
});
return entry;
}
template<std::size_t i>
requires (sizeof...(T) > i)
[[deprecated("Method will be removed after Dune 2.11. Use operator[] instead.")]]
[[nodiscard]] constexpr auto element(Dune::index_constant<i> pos = {}) const
{
return std::get<i>(_data);
}
[[deprecated("Method will be removed after Dune 2.11. Use operator[] instead.")]]
[[nodiscard]] constexpr std::size_t element(std::size_t pos) const
{
std::size_t entry = 0;
Dune::Hybrid::forEach(enumerate(), [&] (auto i) {
if (i==pos)
entry = (*this)[i];
});
return entry;
}
template<std::size_t n = sizeof...(T)>
requires (n > 0 && n == sizeof...(T))
[[nodiscard]] constexpr auto front() const
{
return std::get<0>(_data);
}
template<std::size_t n = sizeof...(T)>
requires (n > 0 && n == sizeof...(T))
[[nodiscard]] constexpr auto back() const
{
return std::get<n-1>(_data);
}
private:
template<class... Head, class... Other>
friend constexpr auto join(const HybridMultiIndex<Head...>&, const Other&...);
std::tuple<T...> _data;
};
template<typename... I>
requires (((std::is_integral_v<I> or Dune::IsIntegralConstant<I>::value) && ...))
HybridMultiIndex(I... i) -> HybridMultiIndex<decltype(Impl::castToHybridSizeT(i))...>;
template<typename... I>
HybridMultiIndex(std::tuple<I...>) -> HybridMultiIndex<I...>;
template<typename... T>
[[nodiscard]] constexpr auto back(const HybridMultiIndex<T...>& tp)
-> decltype(tp.back())
{
return tp.back();
}
template<typename... T>
[[nodiscard]] constexpr auto front(const HybridMultiIndex<T...>& tp)
-> decltype(tp.front())
{
return tp.front();
}
template<typename... T>
[[nodiscard]] constexpr HybridMultiIndex<T...,std::size_t> push_back(const HybridMultiIndex<T...>& tp, std::size_t i)
{
return unpackIntegerSequence([&](auto... j){
return HybridMultiIndex(tp[j] ..., i);
}, tp.enumerate());
}
template<std::size_t i, typename... T>
[[nodiscard]] constexpr HybridMultiIndex<T...,index_constant<i>> push_back(const HybridMultiIndex<T...>& tp, index_constant<i> iConstant = {})
{
return unpackIntegerSequence([&](auto... j){
return HybridMultiIndex(tp[j] ..., iConstant);
}, tp.enumerate());
}
template<typename... T>
[[nodiscard]] constexpr HybridMultiIndex<std::size_t,T...> push_front(const HybridMultiIndex<T...>& tp, std::size_t i)
{
return unpackIntegerSequence([&](auto... j){
return HybridMultiIndex(i, tp[j] ...);
}, tp.enumerate());
}
template<std::size_t i, typename... T>
[[nodiscard]] constexpr HybridMultiIndex<index_constant<i>,T...> push_front(const HybridMultiIndex<T...>& tp, index_constant<i> iConstant = {})
{
return unpackIntegerSequence([&](auto... j){
return HybridMultiIndex(iConstant, tp[j] ...);
}, tp.enumerate());
}
template<typename I, typename... T>
requires (sizeof...(T) > 0)
[[nodiscard]] constexpr auto accumulate_back(const HybridMultiIndex<T...>& tp, I i) {
using ::Dune::Hybrid::plus;
return push_back(pop_back(tp), plus(back(tp), i));
}
template<typename I, typename... T>
requires (sizeof...(T) > 0)
[[nodiscard]] constexpr auto accumulate_front(const HybridMultiIndex<T...>& tp, I i) {
using ::Dune::Hybrid::plus;
return push_front(pop_front(tp), plus(front(tp), i));
}
template<class... Head, class... Other>
[[nodiscard]] constexpr auto join(const HybridMultiIndex<Head...>& head, const Other&... tail) {
return Dune::HybridMultiIndex{std::tuple_cat(head._data, tail._data...)};
}
template<class... T>
[[nodiscard]] constexpr auto reverse(const HybridMultiIndex<T...>& tp) {
constexpr std::size_t size = sizeof...(T);
return unpackIntegerSequence([&](auto... i){
return HybridMultiIndex(tp[index_constant<size-i-1>{}] ...);
}, std::make_index_sequence<size>{});
}
template <class... T>
requires (sizeof...(T) > 0)
[[nodiscard]] constexpr auto pop_front(const HybridMultiIndex<T...>& tp)
{
return unpackIntegerSequence([&](auto... i){
return HybridMultiIndex{std::make_tuple(tp[Dune::index_constant<i+1>{}]...)};
}, std::make_index_sequence<(sizeof...(T) - 1)>{});
}
template <class... T>
requires (sizeof...(T) > 0)
[[nodiscard]] constexpr auto pop_back(const HybridMultiIndex<T...>& tp)
{
return unpackIntegerSequence([&](auto... i){
return HybridMultiIndex{std::make_tuple(tp[i]...)};
}, std::make_index_sequence<(sizeof...(T) - 1)>{});
}
template <class... S, class... T>
[[nodiscard]] constexpr bool operator==(
const HybridMultiIndex<S...>& lhs,
const HybridMultiIndex<T...>& rhs)
{
if constexpr (sizeof...(S) == sizeof...(T)) {
if constexpr ((Dune::IsInteroperable<S,T>::value &&...)) {
return unpackIntegerSequence([&](auto... i){
return ((lhs[i] == rhs[i]) &&...);
}, lhs.enumerate());
} else {
return false;
}
} else {
return false;
}
}
template <class S, S... lhs, class T, T... rhs>
[[nodiscard]] constexpr auto operator==(
const HybridMultiIndex<std::integral_constant<S,lhs>...>&,
const HybridMultiIndex<std::integral_constant<T,rhs>...>&)
{
// If we directly put the expression into std::bool_constant,
// gcc-10 deduced the return type of this method as `HybridMultiIndex<>.
constexpr auto result = (HybridMultiIndex(lhs...) == HybridMultiIndex(rhs...));
return std::bool_constant<result>{};
}
template <class... S, class... T>
[[nodiscard]] constexpr auto operator!=(
const HybridMultiIndex<S...>& lhs,
const HybridMultiIndex<T...>& rhs)
{
return !(lhs == rhs);
}
template <class S, S... lhs, class T, T... rhs>
[[nodiscard]] constexpr auto operator!=(
const HybridMultiIndex<std::integral_constant<S,lhs>...>&,
const HybridMultiIndex<std::integral_constant<T,rhs>...>&)
{
// If we directly put the expression into std::bool_constant,
// gcc-10 deduced the return type of this method as `HybridMultiIndex<>.
constexpr auto result = (HybridMultiIndex(lhs...) != HybridMultiIndex(rhs...));
return std::bool_constant<result>{};
}
template<typename... T>
std::ostream& operator<<(std::ostream& os, const HybridMultiIndex<T...>& tp)
{
os << "HybridMultiIndex< ";
Dune::Hybrid::forEach(tp, [&] (auto tp_i) {
os << tp_i << " ";
});
os << ">";
return os;
}
} //namespace Dune
// Implement the tuple-protocol for HybridMultiIndex
namespace std {
template<typename... T>
struct tuple_size<Dune::HybridMultiIndex<T...>> : public std::integral_constant<std::size_t,sizeof...(T)> {};
template <size_t i, typename... T>
struct tuple_element<i, Dune::HybridMultiIndex<T...> >
{
using type = std::tuple_element_t<i, std::tuple<T...> >;
};
}
#endif // DUNE_COMMON_HYBRIDMULTIINDEX_HH
typetraits.hh
Traits for type conversions and type information.
indices.hh
hybridutilities.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::index_constant
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition indices.hh:29
Dune::Hybrid::forEach
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition hybridutilities.hh:261
Dune::Hybrid::plus
constexpr auto plus
Function object for performing addition.
Definition hybridutilities.hh:533
Dune::operator<<
std::ostream & operator<<(std::ostream &s, const bigunsignedint< k > &x)
Definition bigunsignedint.hh:301
std
STL namespace.
Dune
Dune namespace
Definition alignedallocator.hh:13
Dune::HybridMultiIndex
HybridMultiIndex(I... i) -> HybridMultiIndex< decltype(Impl::castToHybridSizeT(i))... >
Dune::join
constexpr auto join(const HybridMultiIndex< Head... > &head, const Other &... tail)
Join two hybrid multi-indices into one.
Definition hybridmultiindex.hh:355
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::reverse
constexpr auto reverse(const HybridMultiIndex< T... > &tp)
Reverses the order of the elements in the multi-index.
Definition hybridmultiindex.hh:361
Dune::pop_back
constexpr auto pop_back(const HybridMultiIndex< T... > &tp)
Removes last index on a HybridMultiIndex.
Definition hybridmultiindex.hh:387
Dune::pop_front
constexpr auto pop_front(const HybridMultiIndex< T... > &tp)
Removes first index on a HybridMultiIndex.
Definition hybridmultiindex.hh:374
Dune::accumulate_back
constexpr auto accumulate_back(const HybridMultiIndex< T... > &tp, I i)
Hybrid utility that accumulates to the back of a multi-index.
Definition hybridmultiindex.hh:328
Dune::back
constexpr auto back(const HybridMultiIndex< T... > &tp) -> decltype(tp.back())
Returns a copy of the last element of the HybridMultiIndex.
Definition hybridmultiindex.hh:225
Dune::push_front
constexpr HybridMultiIndex< std::size_t, T... > push_front(const HybridMultiIndex< T... > &tp, std::size_t i)
Prepends a run time index to a HybridMultiIndex.
Definition hybridmultiindex.hh:284
Dune::accumulate_front
constexpr auto accumulate_front(const HybridMultiIndex< T... > &tp, I i)
Hybrid utility that accumulates to the front of a multi-index.
Definition hybridmultiindex.hh:348
Dune::operator!=
constexpr auto operator!=(const HybridMultiIndex< S... > &lhs, const HybridMultiIndex< T... > &rhs)
Compare two HybridMultiIndexs for inequality.
Definition hybridmultiindex.hh:441
Dune::tail
constexpr std::integer_sequence< T, II... > tail(std::integer_sequence< T, I0, II... >)
For a sequence [head,tail...) return the tail sequence.
Definition integersequence.hh:58
Dune::push_back
constexpr HybridMultiIndex< T..., std::size_t > push_back(const HybridMultiIndex< T... > &tp, std::size_t i)
Appends a run time index to a HybridMultiIndex.
Definition hybridmultiindex.hh:249
Dune::front
constexpr auto front(const HybridMultiIndex< T... > &tp) -> decltype(tp.front())
Returns a copy of the first element of the HybridMultiIndex.
Definition hybridmultiindex.hh:238
Dune::head
constexpr std::integral_constant< T, I0 > head(std::integer_sequence< T, I0, II... >)
For a sequence [head,tail...) return the single head element.
Definition integersequence.hh:53
Dune::operator==
constexpr bool operator==(const HybridMultiIndex< S... > &lhs, const HybridMultiIndex< T... > &rhs)
Compare two HybridMultiIndexs for value equality.
Definition hybridmultiindex.hh:404
Dune::HybridMultiIndex
A hybrid multi-index class that supports both compile time and run time indices.
Definition hybridmultiindex.hh:81
Dune::HybridMultiIndex::size
static constexpr std::size_t size()
Get the size (length) of this multi-index.
Definition hybridmultiindex.hh:122
Dune::HybridMultiIndex::max_size
static constexpr std::size_t max_size()
Get the size (length) of this multi-index.
Definition hybridmultiindex.hh:128
Dune::HybridMultiIndex::HybridMultiIndex
constexpr HybridMultiIndex()=default
Dune::HybridMultiIndex::front
constexpr auto front() const
Get the first index value. Only available in non-empty multi-indices.
Definition hybridmultiindex.hh:189
Dune::HybridMultiIndex::HybridMultiIndex
constexpr HybridMultiIndex(const HybridMultiIndex &tp)=default
Dune::HybridMultiIndex::enumerate
static constexpr index_sequence enumerate()
Returns an index_sequence for enumerating the components of this HybridMultiIndex.
Definition hybridmultiindex.hh:116
Dune::HybridMultiIndex::HybridMultiIndex
constexpr HybridMultiIndex(HybridMultiIndex &&tp)=default
Dune::HybridMultiIndex::join
friend constexpr auto join(const HybridMultiIndex< Head... > &, const Other &...)
Dune::HybridMultiIndex::get
constexpr auto get() const
Get the index value at position pos.
Definition hybridmultiindex.hh:141
Dune::HybridMultiIndex::HybridMultiIndex
constexpr HybridMultiIndex(std::tuple< T... > t)
Constructor from a std::tuple.
Definition hybridmultiindex.hh:103
Dune::HybridMultiIndex::back
constexpr auto back() const
Get the last index value. Only available in non-empty multi-indices.
Definition hybridmultiindex.hh:197
Dune::HybridMultiIndex::element
constexpr auto element(Dune::index_constant< i > pos={}) const
Get the last index value.
Definition hybridmultiindex.hh:169
Dune::HybridMultiIndex::operator=
constexpr HybridMultiIndex & operator=(HybridMultiIndex &&tp)=default
Dune::HybridMultiIndex::operator=
constexpr HybridMultiIndex & operator=(const HybridMultiIndex &tp)=default
Dune::HybridMultiIndex::index_sequence
std::index_sequence_for< T... > index_sequence
An index_sequence for the entries in this HybridMultiIndex.
Definition hybridmultiindex.hh:90
Dune::HybridMultiIndex::operator[]
constexpr std::size_t operator[](std::size_t pos) const
Get the index value at position pos.
Definition hybridmultiindex.hh:155
Dune::HybridMultiIndex::HybridMultiIndex
constexpr HybridMultiIndex(I... i)
Constructor from arguments.
Definition hybridmultiindex.hh:111
Dune::HybridMultiIndex::element
constexpr std::size_t element(std::size_t pos) const
Get the index value at position pos.
Definition hybridmultiindex.hh:176
std::tuple_element< i, Dune::HybridMultiIndex< T... > >::type
std::tuple_element_t< i, std::tuple< T... > > type
Definition hybridmultiindex.hh:485
Dune::IsInteroperable::value
static constexpr bool value
True if either a conversion from T1 to T2 or vice versa exists.
Definition typetraits.hh:70
Dune::IsIntegralConstant
Check if T is an std::integral_constant<I, i>.
Definition typetraits.hh:384