Kokkos Core Kernels Package  Version of the Day
Kokkos_Parallel_Reduce.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 2.0
6 // Copyright (2014) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact H. Carter Edwards (hcedwar@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 */
43 
44 
45 namespace Kokkos {
46 
47 
48 template<class T, class Enable = void>
49 struct is_reducer_type {
50  enum { value = 0 };
51 };
52 
53 
54 template<class T>
55 struct is_reducer_type<T,typename std::enable_if<
56  std::is_same<typename std::remove_cv<T>::type,
57  typename std::remove_cv<typename T::reducer_type>::type>::value
58  >::type> {
59  enum { value = 1 };
60 };
61 
62 namespace Experimental {
63 
64 
65 template<class Scalar,class Space = HostSpace>
66 struct Sum {
67 public:
68  //Required
69  typedef Sum reducer_type;
70  typedef Scalar value_type;
71 
73 
74  value_type init_value;
75 
76 private:
77  result_view_type result;
78 
79  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
80  struct InitWrapper;
81 
82  template<class ValueType >
83  struct InitWrapper<ValueType,true> {
84  static ValueType value() {
85  return static_cast<value_type>(0);
86  }
87  };
88 
89  template<class ValueType >
90  struct InitWrapper<ValueType,false> {
91  static ValueType value() {
92  return value_type();
93  }
94  };
95 
96 public:
97 
98  Sum(value_type& result_):
99  init_value(InitWrapper<value_type>::value()),result(&result_) {}
100  Sum(const result_view_type& result_):
101  init_value(InitWrapper<value_type>::value()),result(result_) {}
102  Sum(value_type& result_, const value_type& init_value_):
103  init_value(init_value_),result(&result_) {}
104  Sum(const result_view_type& result_, const value_type& init_value_):
105  init_value(init_value_),result(result_) {}
106 
107  //Required
108  KOKKOS_INLINE_FUNCTION
109  void join(value_type& dest, const value_type& src) const {
110  dest += src;
111  }
112 
113  KOKKOS_INLINE_FUNCTION
114  void join(volatile value_type& dest, const volatile value_type& src) const {
115  dest += src;
116  }
117 
118  //Optional
119  KOKKOS_INLINE_FUNCTION
120  void init( value_type& val) const {
121  val = init_value;
122  }
123 
124  result_view_type result_view() const {
125  return result;
126  }
127 };
128 
129 template<class Scalar,class Space = HostSpace>
130 struct Prod {
131 public:
132  //Required
133  typedef Prod reducer_type;
134  typedef Scalar value_type;
135 
137 
138  value_type init_value;
139 
140 private:
141  result_view_type result;
142 
143  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
144  struct InitWrapper;
145 
146  template<class ValueType >
147  struct InitWrapper<ValueType,true> {
148  static ValueType value() {
149  return static_cast<value_type>(1);
150  }
151  };
152 
153  template<class ValueType >
154  struct InitWrapper<ValueType,false> {
155  static ValueType value() {
156  return value_type();
157  }
158  };
159 
160 public:
161 
162  Prod(value_type& result_):
163  init_value(InitWrapper<value_type>::value()),result(&result_) {}
164  Prod(const result_view_type& result_):
165  init_value(InitWrapper<value_type>::value()),result(result_) {}
166  Prod(value_type& result_, const value_type& init_value_):
167  init_value(init_value_),result(&result_) {}
168  Prod(const result_view_type& result_, const value_type& init_value_):
169  init_value(init_value_),result(result_) {}
170 
171  //Required
172  KOKKOS_INLINE_FUNCTION
173  void join(value_type& dest, const value_type& src) const {
174  dest *= src;
175  }
176 
177  KOKKOS_INLINE_FUNCTION
178  void join(volatile value_type& dest, const volatile value_type& src) const {
179  dest *= src;
180  }
181 
182  //Optional
183  KOKKOS_INLINE_FUNCTION
184  void init( value_type& val) const {
185  val = init_value;
186  }
187 
188  result_view_type result_view() const {
189  return result;
190  }
191 };
192 
193 template<class Scalar, class Space = HostSpace>
194 struct Min {
195 public:
196  //Required
197  typedef Min reducer_type;
198  typedef typename std::remove_cv<Scalar>::type value_type;
199 
201 
202  value_type init_value;
203 
204 private:
205  result_view_type result;
206 
207  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
208  struct InitWrapper;
209 
210  template<class ValueType >
211  struct InitWrapper<ValueType,true> {
212  static ValueType value() {
213  return std::numeric_limits<value_type>::max();
214  }
215  };
216 
217  template<class ValueType >
218  struct InitWrapper<ValueType,false> {
219  static ValueType value() {
220  return value_type();
221  }
222  };
223 
224 public:
225 
226  Min(value_type& result_):
227  init_value(InitWrapper<value_type>::value()),result(&result_) {}
228  Min(const result_view_type& result_):
229  init_value(InitWrapper<value_type>::value()),result(result_) {}
230  Min(value_type& result_, const value_type& init_value_):
231  init_value(init_value_),result(&result_) {}
232  Min(const result_view_type& result_, const value_type& init_value_):
233  init_value(init_value_),result(result_) {}
234 
235  //Required
236  KOKKOS_INLINE_FUNCTION
237  void join(value_type& dest, const value_type& src) const {
238  if ( src < dest )
239  dest = src;
240  }
241 
242  KOKKOS_INLINE_FUNCTION
243  void join(volatile value_type& dest, const volatile value_type& src) const {
244  if ( src < dest )
245  dest = src;
246  }
247 
248  //Optional
249  KOKKOS_INLINE_FUNCTION
250  void init( value_type& val) const {
251  val = init_value;
252  }
253 
254  result_view_type result_view() const {
255  return result;
256  }
257 };
258 
259 template<class Scalar, class Space = HostSpace>
260 struct Max {
261 public:
262  //Required
263  typedef Max reducer_type;
264  typedef typename std::remove_cv<Scalar>::type value_type;
265 
267 
268  value_type init_value;
269 
270 private:
271  result_view_type result;
272 
273  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
274  struct InitWrapper;
275 
276  template<class ValueType >
277  struct InitWrapper<ValueType,true> {
278  static ValueType value() {
279  return std::numeric_limits<value_type>::min();
280  }
281  };
282 
283  template<class ValueType >
284  struct InitWrapper<ValueType,false> {
285  static ValueType value() {
286  return value_type();
287  }
288  };
289 
290 public:
291 
292  Max(value_type& result_):
293  init_value(InitWrapper<value_type>::value()),result(&result_) {}
294  Max(const result_view_type& result_):
295  init_value(InitWrapper<value_type>::value()),result(result_) {}
296  Max(value_type& result_, const value_type& init_value_):
297  init_value(init_value_),result(&result_) {}
298  Max(const result_view_type& result_, const value_type& init_value_):
299  init_value(init_value_),result(result_) {}
300 
301  //Required
302  KOKKOS_INLINE_FUNCTION
303  void join(value_type& dest, const value_type& src) const {
304  if ( src > dest )
305  dest = src;
306  }
307 
308  KOKKOS_INLINE_FUNCTION
309  void join(volatile value_type& dest, const volatile value_type& src) const {
310  if ( src > dest )
311  dest = src;
312  }
313 
314  //Optional
315  KOKKOS_INLINE_FUNCTION
316  void init( value_type& val) const {
317  val = init_value;
318  }
319 
320  result_view_type result_view() const {
321  return result;
322  }
323 };
324 
325 template<class Scalar, class Space = HostSpace>
326 struct LAnd {
327 public:
328  //Required
329  typedef LAnd reducer_type;
330  typedef Scalar value_type;
331 
333 
334 private:
335  result_view_type result;
336 
337 public:
338 
339  LAnd(value_type& result_):result(&result_) {}
340  LAnd(const result_view_type& result_):result(result_) {}
341 
342  //Required
343  KOKKOS_INLINE_FUNCTION
344  void join(value_type& dest, const value_type& src) const {
345  dest = dest && src;
346  }
347 
348  KOKKOS_INLINE_FUNCTION
349  void join(volatile value_type& dest, const volatile value_type& src) const {
350  dest = dest && src;
351  }
352 
353  //Optional
354  KOKKOS_INLINE_FUNCTION
355  void init( value_type& val) const {
356  val = 1;
357  }
358 
359  result_view_type result_view() const {
360  return result;
361  }
362 };
363 
364 template<class Scalar, class Space = HostSpace>
365 struct LOr {
366 public:
367  //Required
368  typedef LOr reducer_type;
369  typedef Scalar value_type;
370 
372 
373 private:
374  result_view_type result;
375 
376 public:
377 
378  LOr(value_type& result_):result(&result_) {}
379  LOr(const result_view_type& result_):result(result_) {}
380 
381  //Required
382  KOKKOS_INLINE_FUNCTION
383  void join(value_type& dest, const value_type& src) const {
384  dest = dest || src;
385  }
386 
387  KOKKOS_INLINE_FUNCTION
388  void join(volatile value_type& dest, const volatile value_type& src) const {
389  dest = dest || src;
390  }
391 
392  //Optional
393  KOKKOS_INLINE_FUNCTION
394  void init( value_type& val) const {
395  val = 0;
396  }
397 
398  result_view_type result_view() const {
399  return result;
400  }
401 };
402 
403 template<class Scalar, class Space = HostSpace>
404 struct LXor {
405 public:
406  //Required
407  typedef LXor reducer_type;
408  typedef Scalar value_type;
409 
411 
412 private:
413  result_view_type result;
414 
415 public:
416 
417  LXor(value_type& result_):result(&result_) {}
418  LXor(const result_view_type& result_):result(result_) {}
419 
420  //Required
421  KOKKOS_INLINE_FUNCTION
422  void join(value_type& dest, const value_type& src) const {
423  dest = dest? (!src) : src;
424  }
425 
426  KOKKOS_INLINE_FUNCTION
427  void join(volatile value_type& dest, const volatile value_type& src) const {
428  dest = dest? (!src) : src;
429  }
430 
431  //Optional
432  KOKKOS_INLINE_FUNCTION
433  void init( value_type& val) const {
434  val = 0;
435  }
436 
437  result_view_type result_view() const {
438  return result;
439  }
440 };
441 
442 template<class Scalar, class Space = HostSpace>
443 struct BAnd {
444 public:
445  //Required
446  typedef BAnd reducer_type;
447  typedef typename std::remove_cv<Scalar>::type value_type;
448 
450 
451  value_type init_value;
452 
453 private:
454  result_view_type result;
455 
456 public:
457 
458  BAnd(value_type& result_):
459  init_value(value_type() | (~value_type())),result(&result_) {}
460  BAnd(const result_view_type& result_):
461  init_value(value_type() | (~value_type())),result(result_) {}
462 
463  //Required
464  KOKKOS_INLINE_FUNCTION
465  void join(value_type& dest, const value_type& src) const {
466  dest = dest & src;
467  }
468 
469  KOKKOS_INLINE_FUNCTION
470  void join(volatile value_type& dest, const volatile value_type& src) const {
471  dest = dest & src;
472  }
473 
474  //Optional
475  KOKKOS_INLINE_FUNCTION
476  void init( value_type& val) const {
477  val = init_value;
478  }
479 
480  result_view_type result_view() const {
481  return result;
482  }
483 };
484 
485 template<class Scalar, class Space = HostSpace>
486 struct BOr {
487 public:
488  //Required
489  typedef BOr reducer_type;
490  typedef typename std::remove_cv<Scalar>::type value_type;
491 
493 
494  value_type init_value;
495 
496 private:
497  result_view_type result;
498 
499 public:
500 
501  BOr(value_type& result_):
502  init_value(value_type() & (~value_type())),result(&result_) {}
503  BOr(const result_view_type& result_):
504  init_value(value_type() & (~value_type())),result(result_) {}
505 
506  //Required
507  KOKKOS_INLINE_FUNCTION
508  void join(value_type& dest, const value_type& src) const {
509  dest = dest | src;
510  }
511 
512  KOKKOS_INLINE_FUNCTION
513  void join(volatile value_type& dest, const volatile value_type& src) const {
514  dest = dest | src;
515  }
516 
517  //Optional
518  KOKKOS_INLINE_FUNCTION
519  void init( value_type& val) const {
520  val = init_value;
521  }
522 
523  result_view_type result_view() const {
524  return result;
525  }
526 };
527 
528 template<class Scalar, class Space = HostSpace>
529 struct BXor {
530 public:
531  //Required
532  typedef BXor reducer_type;
533  typedef typename std::remove_cv<Scalar>::type value_type;
534 
536 
537  value_type init_value;
538 
539 private:
540  result_view_type result;
541 
542 public:
543 
544  BXor(value_type& result_):
545  init_value(value_type() & (~value_type())),result(&result_) {}
546  BXor(const result_view_type& result_):
547  init_value(value_type() & (~value_type())),result(result_) {}
548 
549  //Required
550  KOKKOS_INLINE_FUNCTION
551  void join(value_type& dest, const value_type& src) const {
552  dest = dest ^ src;
553  }
554 
555  KOKKOS_INLINE_FUNCTION
556  void join(volatile value_type& dest, const volatile value_type& src) const {
557  dest = dest ^ src;
558  }
559 
560  //Optional
561  KOKKOS_INLINE_FUNCTION
562  void init( value_type& val) const {
563  val = init_value;
564  }
565 
566  result_view_type result_view() const {
567  return result;
568  }
569 };
570 
571 template<class Scalar, class Index>
572 struct ValLocScalar {
573  Scalar val;
574  Index loc;
575 
576  KOKKOS_INLINE_FUNCTION
577  void operator = (const ValLocScalar& rhs) {
578  val = rhs.val;
579  loc = rhs.loc;
580  }
581 
582  KOKKOS_INLINE_FUNCTION
583  void operator = (const volatile ValLocScalar& rhs) volatile {
584  val = rhs.val;
585  loc = rhs.loc;
586  }
587 };
588 
589 template<class Scalar, class Index, class Space = HostSpace>
590 struct MinLoc {
591 private:
592  typedef typename std::remove_cv<Scalar>::type scalar_type;
593  typedef typename std::remove_cv<Index>::type index_type;
594 
595 public:
596  //Required
597  typedef MinLoc reducer_type;
598  typedef ValLocScalar<scalar_type,index_type> value_type;
599 
601 
602  scalar_type init_value;
603 
604 private:
605  result_view_type result;
606 
607  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
608  struct InitWrapper;
609 
610  template<class ValueType >
611  struct InitWrapper<ValueType,true> {
612  static ValueType value() {
613  return std::numeric_limits<scalar_type>::max();
614  }
615  };
616 
617  template<class ValueType >
618  struct InitWrapper<ValueType,false> {
619  static ValueType value() {
620  return scalar_type();
621  }
622  };
623 
624 public:
625 
626  MinLoc(value_type& result_):
627  init_value(InitWrapper<scalar_type>::value()),result(&result_) {}
628  MinLoc(const result_view_type& result_):
629  init_value(InitWrapper<scalar_type>::value()),result(result_) {}
630  MinLoc(value_type& result_, const scalar_type& init_value_):
631  init_value(init_value_),result(&result_) {}
632  MinLoc(const result_view_type& result_, const scalar_type& init_value_):
633  init_value(init_value_),result(result_) {}
634 
635 
636  //Required
637  KOKKOS_INLINE_FUNCTION
638  void join(value_type& dest, const value_type& src) const {
639  if ( src.val < dest.val )
640  dest = src;
641  }
642 
643  KOKKOS_INLINE_FUNCTION
644  void join(volatile value_type& dest, const volatile value_type& src) const {
645  if ( src.val < dest.val )
646  dest = src;
647  }
648 
649  //Optional
650  KOKKOS_INLINE_FUNCTION
651  void init( value_type& val) const {
652  val.val = init_value;
653  }
654 
655  result_view_type result_view() const {
656  return result;
657  }
658 };
659 
660 template<class Scalar, class Index, class Space = HostSpace>
661 struct MaxLoc {
662 private:
663  typedef typename std::remove_cv<Scalar>::type scalar_type;
664  typedef typename std::remove_cv<Index>::type index_type;
665 
666 public:
667  //Required
668  typedef MaxLoc reducer_type;
669  typedef ValLocScalar<scalar_type,index_type> value_type;
670 
672 
673  scalar_type init_value;
674 
675 private:
676  result_view_type result;
677 
678  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
679  struct InitWrapper;
680 
681  template<class ValueType >
682  struct InitWrapper<ValueType,true> {
683  static ValueType value() {
684  return std::numeric_limits<scalar_type>::min();
685  }
686  };
687 
688  template<class ValueType >
689  struct InitWrapper<ValueType,false> {
690  static ValueType value() {
691  return scalar_type();
692  }
693  };
694 
695 public:
696 
697  MaxLoc(value_type& result_):
698  init_value(InitWrapper<scalar_type>::value()),result(&result_) {}
699  MaxLoc(const result_view_type& result_):
700  init_value(InitWrapper<scalar_type>::value()),result(result_) {}
701  MaxLoc(value_type& result_, const scalar_type& init_value_):
702  init_value(init_value_),result(&result_) {}
703  MaxLoc(const result_view_type& result_, const scalar_type& init_value_):
704  init_value(init_value_),result(result_) {}
705 
706  //Required
707  KOKKOS_INLINE_FUNCTION
708  void join(value_type& dest, const value_type& src) const {
709  if ( src.val > dest.val )
710  dest = src;
711  }
712 
713  KOKKOS_INLINE_FUNCTION
714  void join(volatile value_type& dest, const volatile value_type& src) const {
715  if ( src.val > dest.val )
716  dest = src;
717  }
718 
719  //Optional
720  KOKKOS_INLINE_FUNCTION
721  void init( value_type& val) const {
722  val.val = init_value;
723  }
724 
725  result_view_type result_view() const {
726  return result;
727  }
728 };
729 
730 template<class Scalar>
731 struct MinMaxScalar {
732  Scalar min_val,max_val;
733 
734  KOKKOS_INLINE_FUNCTION
735  void operator = (const MinMaxScalar& rhs) {
736  min_val = rhs.min_val;
737  max_val = rhs.max_val;
738  }
739 
740  KOKKOS_INLINE_FUNCTION
741  void operator = (const volatile MinMaxScalar& rhs) volatile {
742  min_val = rhs.min_val;
743  max_val = rhs.max_val;
744  }
745 };
746 
747 template<class Scalar, class Space = HostSpace>
748 struct MinMax {
749 private:
750  typedef typename std::remove_cv<Scalar>::type scalar_type;
751 
752 public:
753  //Required
754  typedef MinMax reducer_type;
755  typedef MinMaxScalar<scalar_type> value_type;
756 
758 
759  scalar_type min_init_value;
760  scalar_type max_init_value;
761 
762 private:
763  result_view_type result;
764 
765  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
766  struct MinInitWrapper;
767 
768  template<class ValueType >
769  struct MinInitWrapper<ValueType,true> {
770  static ValueType value() {
771  return std::numeric_limits<scalar_type>::max();
772  }
773  };
774 
775  template<class ValueType >
776  struct MinInitWrapper<ValueType,false> {
777  static ValueType value() {
778  return scalar_type();
779  }
780  };
781 
782  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
783  struct MaxInitWrapper;
784 
785  template<class ValueType >
786  struct MaxInitWrapper<ValueType,true> {
787  static ValueType value() {
788  return std::numeric_limits<scalar_type>::min();
789  }
790  };
791 
792  template<class ValueType >
793  struct MaxInitWrapper<ValueType,false> {
794  static ValueType value() {
795  return scalar_type();
796  }
797  };
798 
799 public:
800 
801  MinMax(value_type& result_):
802  min_init_value(MinInitWrapper<scalar_type>::value()),max_init_value(MaxInitWrapper<scalar_type>::value()),result(&result_) {}
803  MinMax(const result_view_type& result_):
804  min_init_value(MinInitWrapper<scalar_type>::value()),max_init_value(MaxInitWrapper<scalar_type>::value()),result(result_) {}
805  MinMax(value_type& result_, const scalar_type& min_init_value_, const scalar_type& max_init_value_):
806  min_init_value(min_init_value_),max_init_value(max_init_value_),result(&result_) {}
807  MinMax(const result_view_type& result_, const scalar_type& min_init_value_, const scalar_type& max_init_value_):
808  min_init_value(min_init_value_),max_init_value(max_init_value_),result(result_) {}
809 
810  //Required
811  KOKKOS_INLINE_FUNCTION
812  void join(value_type& dest, const value_type& src) const {
813  if ( src.min_val < dest.min_val ) {
814  dest.min_val = src.min_val;
815  }
816  if ( src.max_val > dest.max_val ) {
817  dest.max_val = src.max_val;
818  }
819  }
820 
821  KOKKOS_INLINE_FUNCTION
822  void join(volatile value_type& dest, const volatile value_type& src) const {
823  if ( src.min_val < dest.min_val ) {
824  dest.min_val = src.min_val;
825  }
826  if ( src.max_val > dest.max_val ) {
827  dest.max_val = src.max_val;
828  }
829  }
830 
831  //Optional
832  KOKKOS_INLINE_FUNCTION
833  void init( value_type& val) const {
834  val.min_val = min_init_value;
835  val.max_val = max_init_value;
836  }
837 
838  result_view_type result_view() const {
839  return result;
840  }
841 };
842 
843 template<class Scalar, class Index>
844 struct MinMaxLocScalar {
845  Scalar min_val,max_val;
846  Index min_loc,max_loc;
847 
848  KOKKOS_INLINE_FUNCTION
849  void operator = (const MinMaxLocScalar& rhs) {
850  min_val = rhs.min_val;
851  min_loc = rhs.min_loc;
852  max_val = rhs.max_val;
853  max_loc = rhs.max_loc;
854  }
855 
856  KOKKOS_INLINE_FUNCTION
857  void operator = (const volatile MinMaxLocScalar& rhs) volatile {
858  min_val = rhs.min_val;
859  min_loc = rhs.min_loc;
860  max_val = rhs.max_val;
861  max_loc = rhs.max_loc;
862  }
863 };
864 
865 template<class Scalar, class Index, class Space = HostSpace>
866 struct MinMaxLoc {
867 private:
868  typedef typename std::remove_cv<Scalar>::type scalar_type;
869  typedef typename std::remove_cv<Index>::type index_type;
870 
871 public:
872  //Required
873  typedef MinMaxLoc reducer_type;
874  typedef MinMaxLocScalar<scalar_type,index_type> value_type;
875 
877 
878  scalar_type min_init_value;
879  scalar_type max_init_value;
880 
881 private:
882  result_view_type result;
883 
884  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
885  struct MinInitWrapper;
886 
887  template<class ValueType >
888  struct MinInitWrapper<ValueType,true> {
889  static ValueType value() {
890  return std::numeric_limits<scalar_type>::max();
891  }
892  };
893 
894  template<class ValueType >
895  struct MinInitWrapper<ValueType,false> {
896  static ValueType value() {
897  return scalar_type();
898  }
899  };
900 
901  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
902  struct MaxInitWrapper;
903 
904  template<class ValueType >
905  struct MaxInitWrapper<ValueType,true> {
906  static ValueType value() {
907  return std::numeric_limits<scalar_type>::min();
908  }
909  };
910 
911  template<class ValueType >
912  struct MaxInitWrapper<ValueType,false> {
913  static ValueType value() {
914  return scalar_type();
915  }
916  };
917 
918 public:
919 
920  MinMaxLoc(value_type& result_):
921  min_init_value(MinInitWrapper<scalar_type>::value()),max_init_value(MaxInitWrapper<scalar_type>::value()),result(&result_) {}
922  MinMaxLoc(const result_view_type& result_):
923  min_init_value(MinInitWrapper<scalar_type>::value()),max_init_value(MaxInitWrapper<scalar_type>::value()),result(result_) {}
924  MinMaxLoc(value_type& result_, const scalar_type& min_init_value_, const scalar_type& max_init_value_):
925  min_init_value(min_init_value_),max_init_value(max_init_value_),result(&result_) {}
926  MinMaxLoc(const result_view_type& result_, const scalar_type& min_init_value_, const scalar_type& max_init_value_):
927  min_init_value(min_init_value_),max_init_value(max_init_value_),result(result_) {}
928 
929  //Required
930  KOKKOS_INLINE_FUNCTION
931  void join(value_type& dest, const value_type& src) const {
932  if ( src.min_val < dest.min_val ) {
933  dest.min_val = src.min_val;
934  dest.min_loc = src.min_loc;
935  }
936  if ( src.max_val > dest.max_val ) {
937  dest.max_val = src.max_val;
938  dest.max_loc = src.max_loc;
939  }
940  }
941 
942  KOKKOS_INLINE_FUNCTION
943  void join(volatile value_type& dest, const volatile value_type& src) const {
944  if ( src.min_val < dest.min_val ) {
945  dest.min_val = src.min_val;
946  dest.min_loc = src.min_loc;
947  }
948  if ( src.max_val > dest.max_val ) {
949  dest.max_val = src.max_val;
950  dest.max_loc = src.max_loc;
951  }
952  }
953 
954  //Optional
955  KOKKOS_INLINE_FUNCTION
956  void init( value_type& val) const {
957  val.min_val = min_init_value;
958  val.max_val = max_init_value;
959  }
960 
961  result_view_type result_view() const {
962  return result;
963  }
964 };
965 }
966 }
967 
968 
969 namespace Kokkos {
970 namespace Impl {
971 
972 template< class T, class ReturnType , class ValueTraits>
973 struct ParallelReduceReturnValue;
974 
975 template< class ReturnType , class FunctorType >
976 struct ParallelReduceReturnValue<typename std::enable_if<Kokkos::is_view<ReturnType>::value>::type, ReturnType, FunctorType> {
977  typedef ReturnType return_type;
978  typedef InvalidType reducer_type;
979 
980  typedef typename return_type::value_type value_type_scalar;
981  typedef typename return_type::value_type value_type_array[];
982 
983  typedef typename if_c<return_type::rank==0,value_type_scalar,value_type_array>::type value_type;
984 
985  static return_type& return_value(ReturnType& return_val, const FunctorType&) {
986  return return_val;
987  }
988 };
989 
990 template< class ReturnType , class FunctorType>
991 struct ParallelReduceReturnValue<typename std::enable_if<
992  !Kokkos::is_view<ReturnType>::value &&
993  (!std::is_array<ReturnType>::value && !std::is_pointer<ReturnType>::value) &&
994  !Kokkos::is_reducer_type<ReturnType>::value
995  >::type, ReturnType, FunctorType> {
996  typedef Kokkos::View< ReturnType
998  , Kokkos::MemoryUnmanaged
999  > return_type;
1000 
1001  typedef InvalidType reducer_type;
1002 
1003  typedef typename return_type::value_type value_type;
1004 
1005  static return_type return_value(ReturnType& return_val, const FunctorType&) {
1006  return return_type(&return_val);
1007  }
1008 };
1009 
1010 template< class ReturnType , class FunctorType>
1011 struct ParallelReduceReturnValue<typename std::enable_if<
1012  (is_array<ReturnType>::value || std::is_pointer<ReturnType>::value)
1013  >::type, ReturnType, FunctorType> {
1016  , Kokkos::MemoryUnmanaged
1017  > return_type;
1018 
1019  typedef InvalidType reducer_type;
1020 
1021  typedef typename return_type::value_type value_type[];
1022 
1023  static return_type return_value(ReturnType& return_val,
1024  const FunctorType& functor) {
1025  return return_type(return_val,functor.value_count);
1026  }
1027 };
1028 
1029 template< class ReturnType , class FunctorType>
1030 struct ParallelReduceReturnValue<typename std::enable_if<
1031  Kokkos::is_reducer_type<ReturnType>::value
1032  >::type, ReturnType, FunctorType> {
1033  typedef ReturnType return_type;
1034  typedef ReturnType reducer_type;
1035  typedef typename return_type::value_type value_type;
1036 
1037  static return_type return_value(ReturnType& return_val,
1038  const FunctorType& functor) {
1039  return return_val;
1040  }
1041 };
1042 }
1043 
1044 namespace Impl {
1045 template< class T, class ReturnType , class FunctorType>
1046 struct ParallelReducePolicyType;
1047 
1048 template< class PolicyType , class FunctorType >
1049 struct ParallelReducePolicyType<typename std::enable_if<Kokkos::Impl::is_execution_policy<PolicyType>::value>::type, PolicyType,FunctorType> {
1050 
1051  typedef PolicyType policy_type;
1052  static PolicyType policy(const PolicyType& policy_) {
1053  return policy_;
1054  }
1055 };
1056 
1057 template< class PolicyType , class FunctorType >
1058 struct ParallelReducePolicyType<typename std::enable_if<std::is_integral<PolicyType>::value>::type, PolicyType,FunctorType> {
1059  typedef typename
1060  Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
1061  execution_space ;
1062 
1063  typedef Kokkos::RangePolicy<execution_space> policy_type;
1064 
1065  static policy_type policy(const PolicyType& policy_) {
1066  return policy_type(0,policy_);
1067  }
1068 };
1069 
1070 }
1071 
1072 namespace Impl {
1073  template< class FunctorType, class ExecPolicy, class ValueType, class ExecutionSpace>
1074  struct ParallelReduceFunctorType {
1075  typedef FunctorType functor_type;
1076  static const functor_type& functor(const functor_type& functor) {
1077  return functor;
1078  }
1079  };
1080 }
1081 
1082 namespace Impl {
1083 
1084  template< class PolicyType, class FunctorType, class ReturnType >
1085  struct ParallelReduceAdaptor {
1086  typedef Impl::ParallelReduceReturnValue<void,ReturnType,FunctorType> return_value_adapter;
1087  #ifdef KOKKOS_IMPL_NEED_FUNCTOR_WRAPPER
1088  typedef Impl::ParallelReduceFunctorType<FunctorType,PolicyType,
1089  typename return_value_adapter::value_type,
1090  typename PolicyType::execution_space> functor_adaptor;
1091  #endif
1092  static inline
1093  void execute(const std::string& label,
1094  const PolicyType& policy,
1095  const FunctorType& functor,
1096  ReturnType& return_value) {
1097  #if (KOKKOS_ENABLE_PROFILING)
1098  uint64_t kpID = 0;
1099  if(Kokkos::Profiling::profileLibraryLoaded()) {
1100  Kokkos::Profiling::beginParallelReduce("" == label ? typeid(FunctorType).name() : label, 0, &kpID);
1101  }
1102  #endif
1103 
1104  Kokkos::Impl::shared_allocation_tracking_claim_and_disable();
1105  #ifdef KOKKOS_IMPL_NEED_FUNCTOR_WRAPPER
1106  Impl::ParallelReduce<typename functor_adaptor::functor_type, PolicyType, typename return_value_adapter::reducer_type >
1107  closure(functor_adaptor::functor(functor),
1108  policy,
1109  return_value_adapter::return_value(return_value,functor));
1110  #else
1111  Impl::ParallelReduce<FunctorType, PolicyType, typename return_value_adapter::reducer_type >
1112  closure(functor,
1113  policy,
1114  return_value_adapter::return_value(return_value,functor));
1115  #endif
1116  Kokkos::Impl::shared_allocation_tracking_release_and_enable();
1117  closure.execute();
1118 
1119  #if (KOKKOS_ENABLE_PROFILING)
1120  if(Kokkos::Profiling::profileLibraryLoaded()) {
1121  Kokkos::Profiling::endParallelReduce(kpID);
1122  }
1123  #endif
1124  }
1125 
1126  };
1127 }
1175 // ReturnValue is scalar or array: take by reference
1176 
1177 template< class PolicyType, class FunctorType, class ReturnType >
1178 inline
1179 void parallel_reduce(const std::string& label,
1180  const PolicyType& policy,
1181  const FunctorType& functor,
1182  ReturnType& return_value,
1183  typename Impl::enable_if<
1184  Kokkos::Impl::is_execution_policy<PolicyType>::value
1185  >::type * = 0) {
1186  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,ReturnType>::execute(label,policy,functor,return_value);
1187 }
1188 
1189 template< class PolicyType, class FunctorType, class ReturnType >
1190 inline
1191 void parallel_reduce(const PolicyType& policy,
1192  const FunctorType& functor,
1193  ReturnType& return_value,
1194  typename Impl::enable_if<
1195  Kokkos::Impl::is_execution_policy<PolicyType>::value
1196  >::type * = 0) {
1197  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,ReturnType>::execute("",policy,functor,return_value);
1198 }
1199 
1200 template< class FunctorType, class ReturnType >
1201 inline
1202 void parallel_reduce(const size_t& policy,
1203  const FunctorType& functor,
1204  ReturnType& return_value) {
1205  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1206  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute("",policy_type(0,policy),functor,return_value);
1207 }
1208 
1209 template< class FunctorType, class ReturnType >
1210 inline
1211 void parallel_reduce(const std::string& label,
1212  const size_t& policy,
1213  const FunctorType& functor,
1214  ReturnType& return_value) {
1215  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1216  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute(label,policy_type(0,policy),functor,return_value);
1217 }
1218 
1219 // ReturnValue as View or Reducer: take by copy to allow for inline construction
1220 
1221 template< class PolicyType, class FunctorType, class ReturnType >
1222 inline
1223 void parallel_reduce(const std::string& label,
1224  const PolicyType& policy,
1225  const FunctorType& functor,
1226  const ReturnType& return_value,
1227  typename Impl::enable_if<
1228  Kokkos::Impl::is_execution_policy<PolicyType>::value
1229  >::type * = 0) {
1230  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,const ReturnType>::execute(label,policy,functor,return_value);
1231 }
1232 
1233 template< class PolicyType, class FunctorType, class ReturnType >
1234 inline
1235 void parallel_reduce(const PolicyType& policy,
1236  const FunctorType& functor,
1237  const ReturnType& return_value,
1238  typename Impl::enable_if<
1239  Kokkos::Impl::is_execution_policy<PolicyType>::value
1240  >::type * = 0) {
1241  ReturnType return_value_impl = return_value;
1242  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,ReturnType>::execute("",policy,functor,return_value_impl);
1243 }
1244 
1245 template< class FunctorType, class ReturnType >
1246 inline
1247 void parallel_reduce(const size_t& policy,
1248  const FunctorType& functor,
1249  const ReturnType& return_value) {
1250  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1251  ReturnType return_value_impl = return_value;
1252  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute("",policy_type(0,policy),functor,return_value_impl);
1253 }
1254 
1255 template< class FunctorType, class ReturnType >
1256 inline
1257 void parallel_reduce(const std::string& label,
1258  const size_t& policy,
1259  const FunctorType& functor,
1260  const ReturnType& return_value) {
1261  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1262  ReturnType return_value_impl = return_value;
1263  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute(label,policy_type(0,policy),functor,return_value_impl);
1264 }
1265 
1266 // No Return Argument
1267 
1268 template< class PolicyType, class FunctorType>
1269 inline
1270 void parallel_reduce(const std::string& label,
1271  const PolicyType& policy,
1272  const FunctorType& functor,
1273  typename Impl::enable_if<
1274  Kokkos::Impl::is_execution_policy<PolicyType>::value
1275  >::type * = 0) {
1276  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
1277  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
1278  , typename ValueTraits::value_type
1279  , typename ValueTraits::pointer_type
1280  >::type value_type ;
1281 
1282  typedef Kokkos::View< value_type
1284  , Kokkos::MemoryUnmanaged
1285  > result_view_type;
1286  result_view_type result_view ;
1287 
1288  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,result_view_type>::execute(label,policy,functor,result_view);
1289 }
1290 
1291 template< class PolicyType, class FunctorType >
1292 inline
1293 void parallel_reduce(const PolicyType& policy,
1294  const FunctorType& functor,
1295  typename Impl::enable_if<
1296  Kokkos::Impl::is_execution_policy<PolicyType>::value
1297  >::type * = 0) {
1298  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
1299  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
1300  , typename ValueTraits::value_type
1301  , typename ValueTraits::pointer_type
1302  >::type value_type ;
1303 
1304  typedef Kokkos::View< value_type
1306  , Kokkos::MemoryUnmanaged
1307  > result_view_type;
1308  result_view_type result_view ;
1309 
1310  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,result_view_type>::execute("",policy,functor,result_view);
1311 }
1312 
1313 template< class FunctorType >
1314 inline
1315 void parallel_reduce(const size_t& policy,
1316  const FunctorType& functor) {
1317  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1318  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
1319  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
1320  , typename ValueTraits::value_type
1321  , typename ValueTraits::pointer_type
1322  >::type value_type ;
1323 
1324  typedef Kokkos::View< value_type
1326  , Kokkos::MemoryUnmanaged
1327  > result_view_type;
1328  result_view_type result_view ;
1329 
1330  Impl::ParallelReduceAdaptor<policy_type,FunctorType,result_view_type>::execute("",policy_type(0,policy),functor,result_view);
1331 }
1332 
1333 template< class FunctorType>
1334 inline
1335 void parallel_reduce(const std::string& label,
1336  const size_t& policy,
1337  const FunctorType& functor) {
1338  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1339  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
1340  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
1341  , typename ValueTraits::value_type
1342  , typename ValueTraits::pointer_type
1343  >::type value_type ;
1344 
1345  typedef Kokkos::View< value_type
1347  , Kokkos::MemoryUnmanaged
1348  > result_view_type;
1349  result_view_type result_view ;
1350 
1351  Impl::ParallelReduceAdaptor<policy_type,FunctorType,result_view_type>::execute(label,policy_type(0,policy),functor,result_view);
1352 }
1353 
1354 
1355 
1356 } //namespace Kokkos
void parallel_reduce(const std::string &label, const PolicyType &policy, const FunctorType &functor, ReturnType &return_value, typename Impl::enable_if< Kokkos::Impl::is_execution_policy< PolicyType >::value >::type *=0)
Parallel reduction.
View to an array of data.
Memory management for host memory.
Execution policy for work over a range of an integral type.