7#ifndef DUNE_FUNCTIONS_COMMON_INDEX_ACCESS_HH
8#define DUNE_FUNCTIONS_COMMON_INDEX_ACCESS_HH
14#include <dune/common/typetraits.hh>
15#include <dune/common/concept.hh>
16#include <dune/common/hybridutilities.hh>
18#include <dune/functions/common/utility.hh>
30template<
class size_type>
31struct HasDynamicIndexAccess
34 auto require(C&& c) ->
decltype(
35 c[std::declval<size_type>()]
39struct HasStaticIndexAccess
42 auto require(C&& c) ->
decltype(
65template<
class C,
class I,
class F,
66 std::enable_if_t< Dune::models<Imp::Concept::HasDynamicIndexAccess<I>, C>(),
int> = 0>
90template<
class C,
class I,
class F,
91 std::enable_if_t< not Dune::models<Imp::Concept::HasDynamicIndexAccess<I>, C>(),
int> = 0>
94 using Size =
decltype(Hybrid::size(c));
95 return Hybrid::switchCases(std::make_index_sequence<Size::value>(), i,
96 [&](
const auto& ii) ->
decltype(
auto){
98 }, [&]() ->
decltype(
auto){
99 return f(c[Dune::Indices::_0]);
119 template<
class Index, std::
size_t offset=1>
120 class ShiftedDynamicMultiIndex
123 ShiftedDynamicMultiIndex(
const Index& index) :
127 std::size_t operator[](std::size_t position)
const
130 return index_[position+offset];
138 ShiftedDynamicMultiIndex<Index, offset+1> pop()
const
143 std::size_t size()
const
145 if (offset < index_.size())
146 return index_.size() - offset;
151 const Index& originalIndex()
const
160 template<
class Index, std::
size_t offset=1>
161 class ShiftedStaticMultiIndex
164 ShiftedStaticMultiIndex(
const Index& index) :
168 template<std::
size_t i>
169 auto operator[](Dune::index_constant<i>)
const
171 if constexpr (i<size()) {
172 return index_[Dune::index_constant<i+offset>{}];
174 return Dune::index_constant<0>{};
181 ShiftedStaticMultiIndex<Index, offset+1> pop()
const
186 static constexpr std::size_t size()
188 auto fullSize =
decltype(Hybrid::size(std::declval<Index>()))::value;
189 if (offset < fullSize)
190 return fullSize - offset;
204 template<std::
size_t offset,
class Index>
205 ShiftedDynamicMultiIndex<Index, offset> shiftedDynamicMultiIndex(
const Index& index)
218 template<std::
size_t offset,
class Index, std::
size_t oldOffset>
219 ShiftedDynamicMultiIndex<Index, offset+oldOffset> shiftedDynamicMultiIndex(
const ShiftedDynamicMultiIndex<Index, oldOffset>& index)
221 return {index.originalIndex()};
224 template<std::
size_t offset,
class Index>
225 ShiftedStaticMultiIndex<Index, offset> shiftedStaticMultiIndex(
const Index& index)
237template<
class Result,
class Index>
238struct MultiIndexResolver
240 MultiIndexResolver(
const Index& index) :
245 std::enable_if_t<not std::is_convertible_v<C&, Result>,
int> = 0>
246 Result operator()(C&& c)
248 auto&& subIndex = Imp::shiftedDynamicMultiIndex<1>(index_);
249 auto&& subIndexResolver = MultiIndexResolver<Result, decltype(subIndex)>(subIndex);
250 return (Result)(
hybridIndexAccess(c, index_[Dune::Indices::_0], subIndexResolver));
254 std::enable_if_t<std::is_convertible_v<C&, Result>,
int> = 0>
255 Result operator()(C&& c)
257 return (Result)(std::forward<C>(c));
285template<
class Result,
class C,
class MultiIndex>
289 Imp::MultiIndexResolver<Result, MultiIndex> multiIndexResolver(index);
290 return multiIndexResolver(c);
300 template<
class C,
class MultiIndex,
class IsFinal>
305 return Hybrid::ifElse(isFinal(c), [&, c = forwardCapture(std::forward<C>(c))](
auto) ->
decltype(
auto) {
306 assert(multiIndex.size() == 0);
308 }, [&](
auto) ->
decltype(
auto) {
309 auto hasDynamicAccess =
callableCheck([](
auto&& cc) -> std::void_t<
decltype(cc[0])> {});
312 auto i = multiIndex[0];
313 auto tail = multiIndex.pop();
320 return Hybrid::ifElse(hasDynamicAccess(c), [&](
auto id) ->
decltype(
auto) {
322 }, [&](
auto id) ->
decltype(
auto) {
324 auto indexRange =
typename decltype(range(Hybrid::size(
id(c))))::integer_sequence();
325 return Hybrid::switchCases(indexRange, i, [&](
auto static_i) ->
decltype(
auto){
328 }, [&]() ->
decltype(
auto){
336 template<
class C,
class MultiIndex>
339 auto isExhausted = Hybrid::equals(Hybrid::size(multiIndex), Dune::Indices::_0);
340 return Hybrid::ifElse(isExhausted, [&, c = forwardCapture(std::forward<C>(c))](
auto) ->
decltype(
auto) {
342 }, [&](
auto id) ->
decltype(
auto) {
343 auto head = multiIndex[Dune::Indices::_0];
344 auto tail = multiIndex.pop();
376template<
class C,
class MultiIndex,
class IsFinal>
398template<
class C,
class MultiIndex>
420template<
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:67
constexpr decltype(auto) resolveStaticMultiIndex(C &&c, const MultiIndex &multiIndex)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:421
auto callableCheck(Expression f)
Create a predicate for checking validity of expressions.
Definition: utility.hh:283
constexpr decltype(auto) resolveDynamicMultiIndex(C &&c, const MultiIndex &multiIndex)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:399
Result hybridMultiIndexAccess(C &&c, const MultiIndex &index)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:286
auto negatePredicate(Check check)
Negate given predicate.
Definition: utility.hh:308
Definition: polynomial.hh:17