3#ifndef DUNE_FUNCTIONS_COMMON_INDEX_ACCESS_HH
4#define DUNE_FUNCTIONS_COMMON_INDEX_ACCESS_HH
10#include <dune/common/typetraits.hh>
11#include <dune/common/concept.hh>
12#include <dune/common/hybridutilities.hh>
14#include <dune/functions/common/utility.hh>
26template<
class size_type>
27struct HasDynamicIndexAccess
30 auto require(C&& c) ->
decltype(
31 c[std::declval<size_type>()]
35struct HasStaticIndexAccess
38 auto require(C&& c) ->
decltype(
61template<
class C,
class I,
class F,
62 typename std::enable_if< Dune::models<Imp::Concept::HasDynamicIndexAccess<I>, C>(),
int>::type = 0>
86template<
class C,
class I,
class F,
87 typename std::enable_if< not Dune::models<Imp::Concept::HasDynamicIndexAccess<I>, C>(),
int>::type = 0>
90 using Size =
decltype(Hybrid::size(c));
91 return Hybrid::switchCases(std::make_index_sequence<Size::value>(), i,
92 [&](
const auto& ii) ->
decltype(
auto){
94 }, [&]() ->
decltype(
auto){
95 return f(c[Dune::Indices::_0]);
115 template<
class Index, std::
size_t offset=1>
116 class ShiftedDynamicMultiIndex
119 ShiftedDynamicMultiIndex(
const Index& index) :
123 std::size_t operator[](std::size_t position)
const
126 return index_[position+offset];
134 ShiftedDynamicMultiIndex<Index, offset+1> pop()
const
139 std::size_t size()
const
141 if (offset < index_.size())
142 return index_.size() - offset;
151 template<
class Index, std::
size_t offset=1>
152 class ShiftedStaticMultiIndex
155 ShiftedStaticMultiIndex(
const Index& index) :
159 template<std::
size_t i>
160 auto operator[](Dune::index_constant<i>)
const
162 auto isContained = Dune::Std::bool_constant<(i<size())>{};
163 return Hybrid::ifElse(isContained, [&](
auto id) {
164 return id(index_)[Dune::index_constant<i+offset>{}];
166 return Dune::Indices::_0;
173 ShiftedStaticMultiIndex<Index, offset+1> pop()
const
178 static constexpr std::size_t size()
180 auto fullSize =
decltype(Hybrid::size(std::declval<Index>()))::value;
181 if (offset < fullSize)
182 return fullSize - offset;
196 template<std::
size_t offset,
class Index>
197 ShiftedDynamicMultiIndex<Index, offset> shiftedDynamicMultiIndex(
const Index& index)
202 template<std::
size_t offset,
class Index>
203 ShiftedStaticMultiIndex<Index, offset> shiftedStaticMultiIndex(
const Index& index)
215template<
class Result,
class Index>
216struct MultiIndexResolver
218 MultiIndexResolver(
const Index& index) :
223 typename std::enable_if<not std::is_convertible<C&, Result>::value,
int>::type = 0>
224 Result operator()(C&& c)
226 auto&& subIndex = Imp::shiftedDynamicMultiIndex<1>(index_);
227 auto&& subIndexResolver = MultiIndexResolver<Result, decltype(subIndex)>(subIndex);
228 return (Result)(
hybridIndexAccess(c, index_[Dune::Indices::_0], subIndexResolver));
232 typename std::enable_if<std::is_convertible<C&, Result>::value,
int>::type = 0>
233 Result operator()(C&& c)
235 return (Result)(std::forward<C>(c));
263template<
class Result,
class C,
class MultiIndex>
267 Imp::MultiIndexResolver<Result, MultiIndex> multiIndexResolver(index);
268 return multiIndexResolver(c);
278 template<
class C,
class MultiIndex,
class IsFinal>
283 return Hybrid::ifElse(isFinal(c), [&, c = forwardCapture(std::forward<C>(c))](
auto id) ->
decltype(
auto) {
284 assert(multiIndex.size() == 0);
286 }, [&](
auto id) ->
decltype(
auto) {
287 auto hasDynamicAccess =
callableCheck([](
auto&& cc) -> void_t<
decltype(cc[0])> {});
290 auto i = multiIndex[0];
291 auto tail = multiIndex.pop();
298 return Hybrid::ifElse(hasDynamicAccess(c), [&](
auto id) ->
decltype(
auto) {
300 }, [&](
auto id) ->
decltype(
auto) {
302 auto indexRange =
typename decltype(range(Hybrid::size(
id(c))))::integer_sequence();
303 return Hybrid::switchCases(indexRange, i, [&](
auto static_i) ->
decltype(
auto){
306 }, [&]() ->
decltype(
auto){
314 template<
class C,
class MultiIndex>
317 auto isExhausted = Hybrid::equals(Hybrid::size(multiIndex), Dune::Indices::_0);
318 return Hybrid::ifElse(isExhausted, [&, c = forwardCapture(std::forward<C>(c))](
auto id) ->
decltype(
auto) {
320 }, [&](
auto id) ->
decltype(
auto) {
321 auto head = multiIndex[Dune::Indices::_0];
322 auto tail = multiIndex.pop();
354template<
class C,
class MultiIndex,
class IsFinal>
376template<
class C,
class MultiIndex>
398template<
class C,
class MultiIndex>
auto hybridIndexAccess(C &&c, const I &i, F &&f) -> decltype(f(c[i]))
Provide operator[] index-access for containers.
Definition: indexaccess.hh:63
constexpr decltype(auto) resolveStaticMultiIndex(C &&c, const MultiIndex &multiIndex)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:399
auto callableCheck(Expression f)
Create a predicate for checking validity of expressions.
Definition: utility.hh:279
constexpr decltype(auto) resolveDynamicMultiIndex(C &&c, const MultiIndex &multiIndex)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:377
Result hybridMultiIndexAccess(C &&c, const MultiIndex &index)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:264
auto negatePredicate(Check check)
Negate given predicate.
Definition: utility.hh:304
Definition: polynomial.hh:10