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 
19 namespace 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
237  int increment()
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
261  bool decrement()
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 */
KOKKOS_INLINE_FUNCTION int increment()
KOKKOS_INLINE_FUNCTION bool decrement()
KOKKOS_INLINE_FUNCTION void reset(unsigned from_rank_number=0)
KOKKOS_INLINE_FUNCTION Kokkos::Array< int, 7 > & getLocation()
KOKKOS_INLINE_FUNCTION int getIndex(int dimension)
essentially, a read-only variant of ViewIterator, for a general functor (extent_int() and rank() supp...
SFINAE helper to detect whether a functor returns a reference type.
KOKKOS_INLINE_FUNCTION void setEnumerationIndex(const int &enumerationIndex)
KOKKOS_INLINE_FUNCTION FunctorIterator(const FunctorType &functor)
KOKKOS_INLINE_FUNCTION void setLocation(const Kokkos::Array< int, 7 > &location)
KOKKOS_INLINE_FUNCTION int getExtent(int dimension)
KOKKOS_INLINE_FUNCTION void setLocationInDim(const int &dim, const int &i)
KOKKOS_INLINE_FUNCTION int nextIncrementRank()
KOKKOS_INLINE_FUNCTION int getEnumerationIndex()