Intrepid2
Intrepid2_FunctorIterator.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Intrepid2 Package
4//
5// Copyright 2007 NTESS and the Intrepid2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10
11#ifndef Intrepid2_FunctorIterator_h
12#define Intrepid2_FunctorIterator_h
13
19namespace Intrepid2
20{
22 template<typename FunctorType, typename ScalarType, int rank>
24
26 template<typename FunctorType, typename ScalarType>
27 class functor_returns_ref<FunctorType,ScalarType,0>
28 {
29 using return_type = decltype(std::declval<FunctorType>().operator()());
30 using return_type_no_ref = typename std::remove_reference<return_type>::type;
31 public:
32 static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
33 };
34
36 template<typename FunctorType, typename ScalarType>
37 class functor_returns_ref<FunctorType,ScalarType,1>
38 {
39 using return_type = decltype(std::declval<FunctorType>().operator()(0));
40 using return_type_no_ref = typename std::remove_reference<return_type>::type;
41 public:
42 static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
43 };
44
46 template<typename FunctorType, typename ScalarType>
47 class functor_returns_ref<FunctorType,ScalarType,2>
48 {
49 using return_type = decltype(std::declval<FunctorType>().operator()(0,0));
50 using return_type_no_ref = typename std::remove_reference<return_type>::type;
51 public:
52 static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
53 };
54
56 template<typename FunctorType, typename ScalarType>
57 class functor_returns_ref<FunctorType,ScalarType,3>
58 {
59 using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0));
60 using return_type_no_ref = typename std::remove_reference<return_type>::type;
61 public:
62 static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
63 };
64
66 template<typename FunctorType, typename ScalarType>
67 class functor_returns_ref<FunctorType,ScalarType,4>
68 {
69 using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0,0));
70 using return_type_no_ref = typename std::remove_reference<return_type>::type;
71 public:
72 static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
73 };
74
76 template<typename FunctorType, typename ScalarType>
77 class functor_returns_ref<FunctorType,ScalarType,5>
78 {
79 using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0,0,0));
80 using return_type_no_ref = typename std::remove_reference<return_type>::type;
81 public:
82 static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
83 };
84
86 template<typename FunctorType, typename ScalarType>
87 class functor_returns_ref<FunctorType,ScalarType,6>
88 {
89 using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0,0,0,0));
90 using return_type_no_ref = typename std::remove_reference<return_type>::type;
91 public:
92 static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
93 };
94
96 template<typename FunctorType, typename ScalarType>
97 class functor_returns_ref<FunctorType,ScalarType,7>
98 {
99 using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0,0,0,0,0));
100 using return_type_no_ref = typename std::remove_reference<return_type>::type;
101 public:
102 static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
103 };
104
106 template<class FunctorType, typename ScalarType, int rank>
108 {
109 const FunctorType &functor_;
110 Kokkos::Array<int,7> dims_; // 7 is the maximum rank of a Kokkos view
111 Kokkos::Array<int,7> index_;
112 public:
115 KOKKOS_INLINE_FUNCTION
116 FunctorIterator(const FunctorType &functor)
117 :
118 functor_(functor)
119 {
120 for (int d=0; d<rank; d++)
121 {
122 dims_[d] = functor.extent_int(d);
123 index_[d] = 0;
124 }
125 for (int d=rank; d<7; d++)
126 {
127 dims_[d] = 1;
128 index_[d] = 0;
129 }
130 }
131
132 using return_type = typename std::conditional< functor_returns_ref<FunctorType, ScalarType, rank>::value, const ScalarType &, const ScalarType>::type;
133
134 template< bool B, class T = return_type >
135 using enable_if_t = typename std::enable_if<B,T>::type;
136
139 template<int M = rank>
140 enable_if_t<M==0>
141 KOKKOS_INLINE_FUNCTION
142 get() const
143 {
144 return functor_();
145 }
146
149 template<int M = rank>
150 enable_if_t<M==1>
151 KOKKOS_INLINE_FUNCTION
152 get() const
153 {
154 return functor_(index_[0]);
155 }
156
159 template<int M = rank>
160 enable_if_t<M==2>
161 KOKKOS_INLINE_FUNCTION
162 get() const
163 {
164 return functor_(index_[0], index_[1]);
165 }
166
169 template<int M = rank>
170 enable_if_t<M==3>
171 KOKKOS_INLINE_FUNCTION
172 get() const
173 {
174 return functor_(index_[0], index_[1], index_[2]);
175 }
176
179 template<int M = rank>
180 enable_if_t<M==4>
181 KOKKOS_INLINE_FUNCTION
182 get() const
183 {
184 return functor_(index_[0], index_[1], index_[2], index_[3]);
185 }
186
189 template<int M = rank>
190 enable_if_t<M==5>
191 KOKKOS_INLINE_FUNCTION
192 get() const
193 {
194 return functor_(index_[0], index_[1], index_[2], index_[3], index_[4]);
195 }
196
199
200 template<int M = rank>
201 enable_if_t<M==6>
202 KOKKOS_INLINE_FUNCTION
203 get() const
204 {
205 return functor_(index_[0], index_[1], index_[2], index_[3], index_[4], index_[5]);
206 }
207
210 template<int M = rank>
211 enable_if_t<M==7>
212 KOKKOS_INLINE_FUNCTION
213 get() const
214 {
215 return functor_(index_[0], index_[1], index_[2], index_[3], index_[4], index_[5], index_[6]);
216 }
217
220 KOKKOS_INLINE_FUNCTION
222 {
223 for (int r=rank-1; r>=0; r--)
224 {
225 if (index_[r]+1 < dims_[r]) // can increment without going out of bounds in this dimension
226 {
227 return r;
228 }
229 }
230 // next increment will take us out of bounds
231 return -1;
232 }
233
236 KOKKOS_INLINE_FUNCTION
238 {
239 for (int r=rank-1; r>=0; r--)
240 {
241 if (index_[r]+1 < dims_[r]) // can increment without going out of bounds in this dimension
242 {
243 index_[r]++;
244 // we've completed the increment
245 return r;
246 }
247 else
248 {
249 // next rank should be incremented -- this one should reset to 0
250 index_[r] = 0;
251 }
252 }
253 // if we get here, we have run through all ranks, setting them to 0 -- we've cycled around
254 // and in that sense have not completed the increment
255 return -1;
256 }
257
260 KOKKOS_INLINE_FUNCTION
262 {
263 for (int r=rank-1; r>=0; r--)
264 {
265 if (index_[r]-1 >= 0) // can decrement without going out of bounds in this dimension
266 {
267 index_[r]--;
268 return true; // we've completed the decrement
269 }
270 else
271 {
272 // next rank should be decremented -- this one should cycle round to dim_[r]-1
273 index_[r] = dims_[r]-1;
274 }
275 }
276 // if we get here, we've gone past 0 in every dimension, so we should return false
277 // -- we have not completed the decrement in an in-bounds fashion, but have cycled round to the last value
278 // to maintain a clean state, let's reset
279 reset();
280 return false;
281 }
282
285 KOKKOS_INLINE_FUNCTION
287 {
288 int index_1D = 0;
289 for (int d=0; d<7; d++)
290 {
291 if (d>0) index_1D *= dims_[d-1];
292 index_1D += index_[d];
293 }
294
295 return index_1D;
296 }
297
300 KOKKOS_INLINE_FUNCTION
301 void setEnumerationIndex(const int &enumerationIndex)
302 {
303 Kokkos::Array<int,7> location;
304 int remainder = enumerationIndex;
305 for (int d=6; d>=0; d--)
306 {
307 location[d] = remainder % dims_[d];
308 remainder /= dims_[d];
309 }
310
311 setLocation(location);
312 }
313
317 KOKKOS_INLINE_FUNCTION
318 int getIndex(int dimension)
319 {
320 return index_[dimension];
321 }
322
326 KOKKOS_INLINE_FUNCTION
327 int getExtent(int dimension)
328 {
329 return dims_[dimension];
330 }
331
334 KOKKOS_INLINE_FUNCTION
335 void reset(unsigned from_rank_number=0)
336 {
337 for (unsigned d=from_rank_number; d<functor_.rank(); d++)
338 {
339 index_[d] = 0;
340 }
341 }
342
345 KOKKOS_INLINE_FUNCTION
346 void setLocation(const Kokkos::Array<int,7> &location)
347 {
348 index_ = location;
349 }
350
354 KOKKOS_INLINE_FUNCTION
355 void setLocationInDim(const int &dim, const int &i)
356 {
357 index_[dim] = i;
358 }
359
362 KOKKOS_INLINE_FUNCTION
363 Kokkos::Array<int,7> & getLocation()
364 {
365 return index_;
366 }
367 };
368} // end namespace Intrepid2
369
370#endif /* Intrepid2_FunctorIterator_h */
essentially, a read-only variant of ViewIterator, for a general functor (extent_int() and rank() supp...
KOKKOS_INLINE_FUNCTION FunctorIterator(const FunctorType &functor)
KOKKOS_INLINE_FUNCTION int increment()
enable_if_t< M==0 > KOKKOS_INLINE_FUNCTION get() const
enable_if_t< M==5 > KOKKOS_INLINE_FUNCTION get() const
KOKKOS_INLINE_FUNCTION int getEnumerationIndex()
enable_if_t< M==3 > KOKKOS_INLINE_FUNCTION get() const
KOKKOS_INLINE_FUNCTION void setLocationInDim(const int &dim, const int &i)
KOKKOS_INLINE_FUNCTION int getIndex(int dimension)
enable_if_t< M==1 > KOKKOS_INLINE_FUNCTION get() const
KOKKOS_INLINE_FUNCTION void setEnumerationIndex(const int &enumerationIndex)
enable_if_t< M==4 > KOKKOS_INLINE_FUNCTION get() const
KOKKOS_INLINE_FUNCTION void reset(unsigned from_rank_number=0)
KOKKOS_INLINE_FUNCTION void setLocation(const Kokkos::Array< int, 7 > &location)
KOKKOS_INLINE_FUNCTION int nextIncrementRank()
KOKKOS_INLINE_FUNCTION Kokkos::Array< int, 7 > & getLocation()
enable_if_t< M==2 > KOKKOS_INLINE_FUNCTION get() const
KOKKOS_INLINE_FUNCTION bool decrement()
enable_if_t< M==7 > KOKKOS_INLINE_FUNCTION get() const
enable_if_t< M==6 > KOKKOS_INLINE_FUNCTION get() const
KOKKOS_INLINE_FUNCTION int getExtent(int dimension)
SFINAE helper to detect whether a functor returns a reference type.