dune-fem  2.8-git
hybrid.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_COMMON_HYBRID_HH
2 #define DUNE_FEM_COMMON_HYBRID_HH
3 
4 #include <cstddef>
5 
6 #include <tuple>
7 #include <type_traits>
8 #include <utility>
9 
10 #include <dune/common/hybridutilities.hh>
11 #include <dune/common/typetraits.hh>
12 
14 
15 namespace Dune
16 {
17 
18  namespace Hybrid
19  {
20 
21  namespace Impl
22  {
23 
24  template< class Range, class = void >
25  struct Index;
26 
27  template< class T, T... i >
28  struct Index< std::integer_sequence< T, i... > >
29  {
30  typedef T Type;
31  };
32 
33  template< class Range >
34  struct Index< Range, void_t< typename Range::Index > >
35  {
36  typedef typename Range::Index Type;
37  };
38 
39 
40  template< class Index, class = void >
41  struct FlatIndex;
42 
43  template< class Index >
44  struct FlatIndex< Index, std::enable_if_t< std::is_integral< Index >::value > >
45  {
46  typedef Index Type;
47  };
48 
49  template< class T, T value >
50  struct FlatIndex< std::integral_constant< T, value >, void >
51  {
52  typedef T Type;
53  };
54 
55  template< class Index >
56  struct FlatIndex< Index, void_t< typename Index::FlatIndex > >
57  {
58  typedef typename Index::FlatIndex Type;
59  };
60 
61  } // namespace Impl
62 
63 
64 
65  // IndexType
66  // ---------
67 
68  template< class Range >
69  using IndexType = typename Impl::Index< Range >::Type;
70 
71 
72 
73  // FlatIndexType
74  // -------------
75 
76  template< class Index >
77  using FlatIndexType = typename Impl::FlatIndex< Index >::Type;
78 
79 
80 
81  // IndexRange
82  // ----------
83 
84  template< class T, T sz >
85  struct IndexRange
86  {
87  typedef T Index;
88 
89  static constexpr Index size () { return sz; }
90  };
91 
92 
93 
94  // CompositeIndexRange
95  // -------------------
96 
97  template< class... SR >
99  {
100  typedef std::common_type_t< IndexType< SR >... > Index;
101 
102  template< std::size_t i >
103  using SubRange = std::tuple_element_t< i, std::tuple< SR... > >;
104 
105  template< std::size_t i >
106  static constexpr Index offset ( std::integral_constant< std::size_t, i > = {} )
107  {
108  return size( std::make_index_sequence< i >() );
109  }
110 
111  static constexpr Index size () { return size( std::index_sequence_for< SR... >() ); }
112 
113  private:
114  static constexpr Index size ( std::index_sequence<> ) { return 0; }
115 
116  template< std::size_t... i >
117  static constexpr Index size ( std::index_sequence< i... > )
118  {
119  return Std::sum( Hybrid::size( SubRange< i >() )... );
120  }
121  };
122 
123 
124 
125  // forEach for IndexRange
126  // ----------------------
127 
128  template< class T, T sz, class F >
129  inline static void forEach ( IndexRange< T, sz > range, F &&f )
130  {
131  for( T i = 0; i < sz; ++i )
132  f( i );
133  }
134 
135 
136 
137  // CompositeIndex
138  // --------------
139 
140  template< std::size_t component, class I, I offset, class SI >
142  {
143  typedef I FlatIndex;
144  typedef SI SubIndex;
145 
146  private:
147  static constexpr std::integral_constant< std::size_t, component > access ( SubIndex subIndex, std::integral_constant< std::size_t, 0 > ) { return {}; }
148 
149  static constexpr FlatIndexType< SubIndex > access ( FlatIndexType< SubIndex > subIndex, std::integral_constant< std::size_t, 1 > ) { return subIndex; }
150 
151  template< std::size_t _component, class _I, _I _offset, class _SI, std::size_t i >
152  static constexpr decltype( auto ) access ( CompositeIndex< _component, _I, _offset, _SI > subIndex, std::integral_constant< std::size_t, i > )
153  {
154  return subIndex[ std::integral_constant< std::size_t, i-1 >() ];
155  }
156 
157  template< std::size_t i >
158  using Access = decltype( access( std::declval< SubIndex >(), std::integral_constant< std::size_t, i >() ) );
159 
160  public:
161  explicit constexpr CompositeIndex ( SubIndex subIndex ) : subIndex_( std::move( subIndex ) ) {}
162 
163  constexpr operator I () const { return (offset + static_cast< FlatIndexType< SubIndex > >( subIndex() )); }
164 
165  template< std::size_t i >
166  constexpr auto operator[] ( std::integral_constant< std::size_t, i > ) const
167  -> std::enable_if_t< !IsIntegralConstant< Access< i > >::value, Access< i > >
168  {
169  return access( subIndex(), std::integral_constant< std::size_t, i >() );
170  }
171 
172  template< std::size_t i >
173  constexpr auto operator[] ( std::integral_constant< std::size_t, i > ) const
174  -> std::enable_if_t< IsIntegralConstant< Access< i > >::value, std::decay_t< Access< i > > >
175  {
176  return {};
177  }
178 
179  const SubIndex &subIndex () const { return subIndex_; }
180 
181  private:
182  SubIndex subIndex_;
183  };
184 
185 
186 
187  // forEach for CompositeIndexRange
188  // -------------------------------
189 
190  template< class... SR, class F >
191  inline static void forEach ( CompositeIndexRange< SR... >, F &&f );
192 
193  namespace Impl
194  {
195 
196  template< class Range, class F >
197  struct CompositeIndexRangeInnerLoop
198  {
199  explicit CompositeIndexRangeInnerLoop ( F f )
200  : f_( std::move( f ) )
201  {}
202 
203  template< std::size_t component >
204  void operator() ( std::integral_constant< std::size_t, component > )
205  {
206  typedef IndexType< Range > Index;
207  typedef typename Range::template SubRange< component > SubRange;
208 
209  Hybrid::forEach( SubRange(), [ this ] ( auto subIndex ) {
210  f_( CompositeIndex< component, Index, Range::template offset< component >(), std::decay_t< decltype( subIndex ) > >( std::move( subIndex ) ) );
211  } );
212  }
213 
214  private:
215  F f_;
216  };
217 
218  } // namespace Impl
219 
220  template< class... SR, class F >
221  inline static void forEach ( CompositeIndexRange< SR... >, F &&f )
222  {
223  Impl::CompositeIndexRangeInnerLoop< CompositeIndexRange< SR... >, F > innerLoop( std::forward< F >( f ) );
224  forEach( std::index_sequence_for< SR... >(), innerLoop );
225  }
226 
227  } // namespace Hybrid
228 
229 } // namespace Dune
230 
231 #endif // #ifndef DUNE_FEM_COMMON_HYBRID_HH
Definition: bindguard.hh:11
typename Impl::Index< Range >::Type IndexType
Definition: hybrid.hh:69
static void forEach(IndexRange< T, sz > range, F &&f)
Definition: hybrid.hh:129
typename Impl::FlatIndex< Index >::Type FlatIndexType
Definition: hybrid.hh:77
static constexpr std::decay_t< T > sum(T a)
Definition: utility.hh:33
Definition: hybrid.hh:86
static constexpr Index size()
Definition: hybrid.hh:89
T Index
Definition: hybrid.hh:87
Definition: hybrid.hh:99
static constexpr Index offset(std::integral_constant< std::size_t, i >={})
Definition: hybrid.hh:106
std::tuple_element_t< i, std::tuple< SR... > > SubRange
Definition: hybrid.hh:103
static constexpr Index size()
Definition: hybrid.hh:111
std::common_type_t< IndexType< SR >... > Index
Definition: hybrid.hh:100
Definition: hybrid.hh:142
constexpr auto operator[](std::integral_constant< std::size_t, i >) const -> std::enable_if_t< !IsIntegralConstant< Access< i > >::value, Access< i > >
Definition: hybrid.hh:166
constexpr CompositeIndex(SubIndex subIndex)
Definition: hybrid.hh:161
const SubIndex & subIndex() const
Definition: hybrid.hh:179
SI SubIndex
Definition: hybrid.hh:144
I FlatIndex
Definition: hybrid.hh:143