Intrepid2
Intrepid2_FunctorIterator.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Intrepid2 Package
5 // Copyright (2007) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Kyungjoo Kim (kyukim@sandia.gov), or
38 // Mauro Perego (mperego@sandia.gov)
39 //
40 // ************************************************************************
41 // @HEADER
42 
43 
44 #ifndef Intrepid2_FunctorIterator_h
45 #define Intrepid2_FunctorIterator_h
46 
52 namespace Intrepid2
53 {
55  template<typename FunctorType, typename ScalarType, int rank>
57 
59  template<typename FunctorType, typename ScalarType>
60  class functor_returns_ref<FunctorType,ScalarType,0>
61  {
62  using return_type = decltype(std::declval<FunctorType>().operator()());
63  using return_type_no_ref = typename std::remove_reference<return_type>::type;
64  public:
65  static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
66  };
67 
69  template<typename FunctorType, typename ScalarType>
70  class functor_returns_ref<FunctorType,ScalarType,1>
71  {
72  using return_type = decltype(std::declval<FunctorType>().operator()(0));
73  using return_type_no_ref = typename std::remove_reference<return_type>::type;
74  public:
75  static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
76  };
77 
79  template<typename FunctorType, typename ScalarType>
80  class functor_returns_ref<FunctorType,ScalarType,2>
81  {
82  using return_type = decltype(std::declval<FunctorType>().operator()(0,0));
83  using return_type_no_ref = typename std::remove_reference<return_type>::type;
84  public:
85  static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
86  };
87 
89  template<typename FunctorType, typename ScalarType>
90  class functor_returns_ref<FunctorType,ScalarType,3>
91  {
92  using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0));
93  using return_type_no_ref = typename std::remove_reference<return_type>::type;
94  public:
95  static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
96  };
97 
99  template<typename FunctorType, typename ScalarType>
100  class functor_returns_ref<FunctorType,ScalarType,4>
101  {
102  using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0,0));
103  using return_type_no_ref = typename std::remove_reference<return_type>::type;
104  public:
105  static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
106  };
107 
109  template<typename FunctorType, typename ScalarType>
110  class functor_returns_ref<FunctorType,ScalarType,5>
111  {
112  using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0,0,0));
113  using return_type_no_ref = typename std::remove_reference<return_type>::type;
114  public:
115  static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
116  };
117 
119  template<typename FunctorType, typename ScalarType>
120  class functor_returns_ref<FunctorType,ScalarType,6>
121  {
122  using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0,0,0,0));
123  using return_type_no_ref = typename std::remove_reference<return_type>::type;
124  public:
125  static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
126  };
127 
129  template<typename FunctorType, typename ScalarType>
130  class functor_returns_ref<FunctorType,ScalarType,7>
131  {
132  using return_type = decltype(std::declval<FunctorType>().operator()(0,0,0,0,0,0,0));
133  using return_type_no_ref = typename std::remove_reference<return_type>::type;
134  public:
135  static constexpr bool value = !std::is_same<return_type, return_type_no_ref>::value;
136  };
137 
139  template<class FunctorType, typename ScalarType, int rank>
141  {
142  const FunctorType &functor_;
143  Kokkos::Array<int,7> dims_; // 7 is the maximum rank of a Kokkos view
144  Kokkos::Array<int,7> index_;
145  public:
148  KOKKOS_INLINE_FUNCTION
149  FunctorIterator(const FunctorType &functor)
150  :
151  functor_(functor)
152  {
153  for (int d=0; d<rank; d++)
154  {
155  dims_[d] = functor.extent_int(d);
156  index_[d] = 0;
157  }
158  for (int d=rank; d<7; d++)
159  {
160  dims_[d] = 1;
161  index_[d] = 0;
162  }
163  }
164 
165  using return_type = typename std::conditional< functor_returns_ref<FunctorType, ScalarType, rank>::value, const ScalarType &, const ScalarType>::type;
166 
167  template< bool B, class T = return_type >
168  using enable_if_t = typename std::enable_if<B,T>::type;
169 
172  template<int M = rank>
173  enable_if_t<M==0>
174  KOKKOS_INLINE_FUNCTION
175  get() const
176  {
177  return functor_();
178  }
179 
182  template<int M = rank>
183  enable_if_t<M==1>
184  KOKKOS_INLINE_FUNCTION
185  get() const
186  {
187  return functor_(index_[0]);
188  }
189 
192  template<int M = rank>
193  enable_if_t<M==2>
194  KOKKOS_INLINE_FUNCTION
195  get() const
196  {
197  return functor_(index_[0], index_[1]);
198  }
199 
202  template<int M = rank>
203  enable_if_t<M==3>
204  KOKKOS_INLINE_FUNCTION
205  get() const
206  {
207  return functor_(index_[0], index_[1], index_[2]);
208  }
209 
212  template<int M = rank>
213  enable_if_t<M==4>
214  KOKKOS_INLINE_FUNCTION
215  get() const
216  {
217  return functor_(index_[0], index_[1], index_[2], index_[3]);
218  }
219 
222  template<int M = rank>
223  enable_if_t<M==5>
224  KOKKOS_INLINE_FUNCTION
225  get() const
226  {
227  return functor_(index_[0], index_[1], index_[2], index_[3], index_[4]);
228  }
229 
232 
233  template<int M = rank>
234  enable_if_t<M==6>
235  KOKKOS_INLINE_FUNCTION
236  get() const
237  {
238  return functor_(index_[0], index_[1], index_[2], index_[3], index_[4], index_[5]);
239  }
240 
243  template<int M = rank>
244  enable_if_t<M==7>
245  KOKKOS_INLINE_FUNCTION
246  get() const
247  {
248  return functor_(index_[0], index_[1], index_[2], index_[3], index_[4], index_[5], index_[6]);
249  }
250 
253  KOKKOS_INLINE_FUNCTION
255  {
256  for (int r=rank-1; r>=0; r--)
257  {
258  if (index_[r]+1 < dims_[r]) // can increment without going out of bounds in this dimension
259  {
260  return r;
261  }
262  }
263  // next increment will take us out of bounds
264  return -1;
265  }
266 
269  KOKKOS_INLINE_FUNCTION
270  int increment()
271  {
272  for (int r=rank-1; r>=0; r--)
273  {
274  if (index_[r]+1 < dims_[r]) // can increment without going out of bounds in this dimension
275  {
276  index_[r]++;
277  // we've completed the increment
278  return r;
279  }
280  else
281  {
282  // next rank should be incremented -- this one should reset to 0
283  index_[r] = 0;
284  }
285  }
286  // if we get here, we have run through all ranks, setting them to 0 -- we've cycled around
287  // and in that sense have not completed the increment
288  return -1;
289  }
290 
293  KOKKOS_INLINE_FUNCTION
294  bool decrement()
295  {
296  for (int r=rank-1; r>=0; r--)
297  {
298  if (index_[r]-1 >= 0) // can decrement without going out of bounds in this dimension
299  {
300  index_[r]--;
301  return true; // we've completed the decrement
302  }
303  else
304  {
305  // next rank should be decremented -- this one should cycle round to dim_[r]-1
306  index_[r] = dims_[r]-1;
307  }
308  }
309  // if we get here, we've gone past 0 in every dimension, so we should return false
310  // -- we have not completed the decrement in an in-bounds fashion, but have cycled round to the last value
311  // to maintain a clean state, let's reset
312  reset();
313  return false;
314  }
315 
318  KOKKOS_INLINE_FUNCTION
320  {
321  int index_1D = 0;
322  for (int d=0; d<7; d++)
323  {
324  if (d>0) index_1D *= dims_[d-1];
325  index_1D += index_[d];
326  }
327 
328  return index_1D;
329  }
330 
333  KOKKOS_INLINE_FUNCTION
334  void setEnumerationIndex(const int &enumerationIndex)
335  {
336  Kokkos::Array<int,7> location;
337  int remainder = enumerationIndex;
338  for (int d=6; d>=0; d--)
339  {
340  location[d] = remainder % dims_[d];
341  remainder /= dims_[d];
342  }
343 
344  setLocation(location);
345  }
346 
350  KOKKOS_INLINE_FUNCTION
351  int getIndex(int dimension)
352  {
353  return index_[dimension];
354  }
355 
359  KOKKOS_INLINE_FUNCTION
360  int getExtent(int dimension)
361  {
362  return dims_[dimension];
363  }
364 
367  KOKKOS_INLINE_FUNCTION
368  void reset(unsigned from_rank_number=0)
369  {
370  for (unsigned d=from_rank_number; d<functor_.rank(); d++)
371  {
372  index_[d] = 0;
373  }
374  }
375 
378  KOKKOS_INLINE_FUNCTION
379  void setLocation(const Kokkos::Array<int,7> &location)
380  {
381  index_ = location;
382  }
383 
387  KOKKOS_INLINE_FUNCTION
388  void setLocationInDim(const int &dim, const int &i)
389  {
390  index_[dim] = i;
391  }
392 
395  KOKKOS_INLINE_FUNCTION
396  Kokkos::Array<int,7> & getLocation()
397  {
398  return index_;
399  }
400  };
401 } // end namespace Intrepid2
402 
403 #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()