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
52namespace 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
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
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 */
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.