Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_Parallel_Reduce.hpp
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 
17 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
18 #include <Kokkos_Macros.hpp>
19 static_assert(false,
20  "Including non-public Kokkos header files is not allowed.");
21 #endif
22 #ifndef KOKKOS_PARALLEL_REDUCE_HPP
23 #define KOKKOS_PARALLEL_REDUCE_HPP
24 
25 #include <Kokkos_ReductionIdentity.hpp>
26 #include <Kokkos_View.hpp>
27 #include <impl/Kokkos_FunctorAnalysis.hpp>
28 #include <impl/Kokkos_Tools_Generic.hpp>
29 #include <type_traits>
30 
31 namespace Kokkos {
32 
33 template <class Scalar, class Space>
34 struct Sum {
35  public:
36  // Required
37  using reducer = Sum<Scalar, Space>;
38  using value_type = std::remove_cv_t<Scalar>;
39  static_assert(!std::is_pointer_v<value_type> && !std::is_array_v<value_type>);
40 
41  using result_view_type = Kokkos::View<value_type, Space>;
42 
43  private:
44  result_view_type value;
45  bool references_scalar_v;
46 
47  public:
48  KOKKOS_INLINE_FUNCTION
49  Sum(value_type& value_) : value(&value_), references_scalar_v(true) {}
50 
51  KOKKOS_INLINE_FUNCTION
52  Sum(const result_view_type& value_)
53  : value(value_), references_scalar_v(false) {}
54 
55  // Required
56  KOKKOS_INLINE_FUNCTION
57  void join(value_type& dest, const value_type& src) const { dest += src; }
58 
59  KOKKOS_INLINE_FUNCTION
60  void init(value_type& val) const {
61  val = reduction_identity<value_type>::sum();
62  }
63 
64  KOKKOS_INLINE_FUNCTION
65  value_type& reference() const { return *value.data(); }
66 
67  KOKKOS_INLINE_FUNCTION
68  result_view_type view() const { return value; }
69 
70  KOKKOS_INLINE_FUNCTION
71  bool references_scalar() const { return references_scalar_v; }
72 };
73 
74 template <typename Scalar, typename... Properties>
75 Sum(View<Scalar, Properties...> const&)
76  ->Sum<Scalar, typename View<Scalar, Properties...>::memory_space>;
77 
78 template <class Scalar, class Space>
79 struct Prod {
80  public:
81  // Required
82  using reducer = Prod<Scalar, Space>;
83  using value_type = std::remove_cv_t<Scalar>;
84  static_assert(!std::is_pointer_v<value_type> && !std::is_array_v<value_type>);
85 
86  using result_view_type = Kokkos::View<value_type, Space>;
87 
88  private:
89  result_view_type value;
90  bool references_scalar_v;
91 
92  public:
93  KOKKOS_INLINE_FUNCTION
94  Prod(value_type& value_) : value(&value_), references_scalar_v(true) {}
95 
96  KOKKOS_INLINE_FUNCTION
97  Prod(const result_view_type& value_)
98  : value(value_), references_scalar_v(false) {}
99 
100  // Required
101  KOKKOS_INLINE_FUNCTION
102  void join(value_type& dest, const value_type& src) const { dest *= src; }
103 
104  KOKKOS_INLINE_FUNCTION
105  void init(value_type& val) const {
106  val = reduction_identity<value_type>::prod();
107  }
108 
109  KOKKOS_INLINE_FUNCTION
110  value_type& reference() const { return *value.data(); }
111 
112  KOKKOS_INLINE_FUNCTION
113  result_view_type view() const { return value; }
114 
115  KOKKOS_INLINE_FUNCTION
116  bool references_scalar() const { return references_scalar_v; }
117 };
118 
119 template <typename Scalar, typename... Properties>
120 Prod(View<Scalar, Properties...> const&)
121  ->Prod<Scalar, typename View<Scalar, Properties...>::memory_space>;
122 
123 template <class Scalar, class Space>
124 struct Min {
125  public:
126  // Required
127  using reducer = Min<Scalar, Space>;
128  using value_type = std::remove_cv_t<Scalar>;
129  static_assert(!std::is_pointer_v<value_type> && !std::is_array_v<value_type>);
130 
131  using result_view_type = Kokkos::View<value_type, Space>;
132 
133  private:
134  result_view_type value;
135  bool references_scalar_v;
136 
137  public:
138  KOKKOS_INLINE_FUNCTION
139  Min(value_type& value_) : value(&value_), references_scalar_v(true) {}
140 
141  KOKKOS_INLINE_FUNCTION
142  Min(const result_view_type& value_)
143  : value(value_), references_scalar_v(false) {}
144 
145  // Required
146  KOKKOS_INLINE_FUNCTION
147  void join(value_type& dest, const value_type& src) const {
148  if (src < dest) dest = src;
149  }
150 
151  KOKKOS_INLINE_FUNCTION
152  void init(value_type& val) const {
153  val = reduction_identity<value_type>::min();
154  }
155 
156  KOKKOS_INLINE_FUNCTION
157  value_type& reference() const { return *value.data(); }
158 
159  KOKKOS_INLINE_FUNCTION
160  result_view_type view() const { return value; }
161 
162  KOKKOS_INLINE_FUNCTION
163  bool references_scalar() const { return references_scalar_v; }
164 };
165 
166 template <typename Scalar, typename... Properties>
167 Min(View<Scalar, Properties...> const&)
168  ->Min<Scalar, typename View<Scalar, Properties...>::memory_space>;
169 
170 template <class Scalar, class Space>
171 struct Max {
172  public:
173  // Required
174  using reducer = Max<Scalar, Space>;
175  using value_type = std::remove_cv_t<Scalar>;
176  static_assert(!std::is_pointer_v<value_type> && !std::is_array_v<value_type>);
177 
178  using result_view_type = Kokkos::View<value_type, Space>;
179 
180  private:
181  result_view_type value;
182  bool references_scalar_v;
183 
184  public:
185  KOKKOS_INLINE_FUNCTION
186  Max(value_type& value_) : value(&value_), references_scalar_v(true) {}
187 
188  KOKKOS_INLINE_FUNCTION
189  Max(const result_view_type& value_)
190  : value(value_), references_scalar_v(false) {}
191 
192  // Required
193  KOKKOS_INLINE_FUNCTION
194  void join(value_type& dest, const value_type& src) const {
195  if (src > dest) dest = src;
196  }
197 
198  // Required
199  KOKKOS_INLINE_FUNCTION
200  void init(value_type& val) const {
201  val = reduction_identity<value_type>::max();
202  }
203 
204  KOKKOS_INLINE_FUNCTION
205  value_type& reference() const { return *value.data(); }
206 
207  KOKKOS_INLINE_FUNCTION
208  result_view_type view() const { return value; }
209 
210  KOKKOS_INLINE_FUNCTION
211  bool references_scalar() const { return references_scalar_v; }
212 };
213 
214 template <typename Scalar, typename... Properties>
215 Max(View<Scalar, Properties...> const&)
216  ->Max<Scalar, typename View<Scalar, Properties...>::memory_space>;
217 
218 template <class Scalar, class Space>
219 struct LAnd {
220  public:
221  // Required
222  using reducer = LAnd<Scalar, Space>;
223  using value_type = std::remove_cv_t<Scalar>;
224  static_assert(!std::is_pointer_v<value_type> && !std::is_array_v<value_type>);
225 
226  using result_view_type = Kokkos::View<value_type, Space>;
227 
228  private:
229  result_view_type value;
230  bool references_scalar_v;
231 
232  public:
233  KOKKOS_INLINE_FUNCTION
234  LAnd(value_type& value_) : value(&value_), references_scalar_v(true) {}
235 
236  KOKKOS_INLINE_FUNCTION
237  LAnd(const result_view_type& value_)
238  : value(value_), references_scalar_v(false) {}
239 
240  KOKKOS_INLINE_FUNCTION
241  void join(value_type& dest, const value_type& src) const {
242  dest = dest && src;
243  }
244 
245  KOKKOS_INLINE_FUNCTION
246  void init(value_type& val) const {
247  val = reduction_identity<value_type>::land();
248  }
249 
250  KOKKOS_INLINE_FUNCTION
251  value_type& reference() const { return *value.data(); }
252 
253  KOKKOS_INLINE_FUNCTION
254  result_view_type view() const { return value; }
255 
256  KOKKOS_INLINE_FUNCTION
257  bool references_scalar() const { return references_scalar_v; }
258 };
259 
260 template <typename Scalar, typename... Properties>
261 LAnd(View<Scalar, Properties...> const&)
262  ->LAnd<Scalar, typename View<Scalar, Properties...>::memory_space>;
263 
264 template <class Scalar, class Space>
265 struct LOr {
266  public:
267  // Required
268  using reducer = LOr<Scalar, Space>;
269  using value_type = std::remove_cv_t<Scalar>;
270  static_assert(!std::is_pointer_v<value_type> && !std::is_array_v<value_type>);
271 
272  using result_view_type = Kokkos::View<value_type, Space>;
273 
274  private:
275  result_view_type value;
276  bool references_scalar_v;
277 
278  public:
279  KOKKOS_INLINE_FUNCTION
280  LOr(value_type& value_) : value(&value_), references_scalar_v(true) {}
281 
282  KOKKOS_INLINE_FUNCTION
283  LOr(const result_view_type& value_)
284  : value(value_), references_scalar_v(false) {}
285 
286  // Required
287  KOKKOS_INLINE_FUNCTION
288  void join(value_type& dest, const value_type& src) const {
289  dest = dest || src;
290  }
291 
292  KOKKOS_INLINE_FUNCTION
293  void init(value_type& val) const {
294  val = reduction_identity<value_type>::lor();
295  }
296 
297  KOKKOS_INLINE_FUNCTION
298  value_type& reference() const { return *value.data(); }
299 
300  KOKKOS_INLINE_FUNCTION
301  result_view_type view() const { return value; }
302 
303  KOKKOS_INLINE_FUNCTION
304  bool references_scalar() const { return references_scalar_v; }
305 };
306 
307 template <typename Scalar, typename... Properties>
308 LOr(View<Scalar, Properties...> const&)
309  ->LOr<Scalar, typename View<Scalar, Properties...>::memory_space>;
310 
311 template <class Scalar, class Space>
312 struct BAnd {
313  public:
314  // Required
315  using reducer = BAnd<Scalar, Space>;
316  using value_type = std::remove_cv_t<Scalar>;
317  static_assert(!std::is_pointer_v<value_type> && !std::is_array_v<value_type>);
318 
319  using result_view_type = Kokkos::View<value_type, Space>;
320 
321  private:
322  result_view_type value;
323  bool references_scalar_v;
324 
325  public:
326  KOKKOS_INLINE_FUNCTION
327  BAnd(value_type& value_) : value(&value_), references_scalar_v(true) {}
328 
329  KOKKOS_INLINE_FUNCTION
330  BAnd(const result_view_type& value_)
331  : value(value_), references_scalar_v(false) {}
332 
333  // Required
334  KOKKOS_INLINE_FUNCTION
335  void join(value_type& dest, const value_type& src) const {
336  dest = dest & src;
337  }
338 
339  KOKKOS_INLINE_FUNCTION
340  void init(value_type& val) const {
341  val = reduction_identity<value_type>::band();
342  }
343 
344  KOKKOS_INLINE_FUNCTION
345  value_type& reference() const { return *value.data(); }
346 
347  KOKKOS_INLINE_FUNCTION
348  result_view_type view() const { return value; }
349 
350  KOKKOS_INLINE_FUNCTION
351  bool references_scalar() const { return references_scalar_v; }
352 };
353 
354 template <typename Scalar, typename... Properties>
355 BAnd(View<Scalar, Properties...> const&)
356  ->BAnd<Scalar, typename View<Scalar, Properties...>::memory_space>;
357 
358 template <class Scalar, class Space>
359 struct BOr {
360  public:
361  // Required
362  using reducer = BOr<Scalar, Space>;
363  using value_type = std::remove_cv_t<Scalar>;
364  static_assert(!std::is_pointer_v<value_type> && !std::is_array_v<value_type>);
365 
366  using result_view_type = Kokkos::View<value_type, Space>;
367 
368  private:
369  result_view_type value;
370  bool references_scalar_v;
371 
372  public:
373  KOKKOS_INLINE_FUNCTION
374  BOr(value_type& value_) : value(&value_), references_scalar_v(true) {}
375 
376  KOKKOS_INLINE_FUNCTION
377  BOr(const result_view_type& value_)
378  : value(value_), references_scalar_v(false) {}
379 
380  // Required
381  KOKKOS_INLINE_FUNCTION
382  void join(value_type& dest, const value_type& src) const {
383  dest = dest | src;
384  }
385 
386  KOKKOS_INLINE_FUNCTION
387  void init(value_type& val) const {
388  val = reduction_identity<value_type>::bor();
389  }
390 
391  KOKKOS_INLINE_FUNCTION
392  value_type& reference() const { return *value.data(); }
393 
394  KOKKOS_INLINE_FUNCTION
395  result_view_type view() const { return value; }
396 
397  KOKKOS_INLINE_FUNCTION
398  bool references_scalar() const { return references_scalar_v; }
399 };
400 
401 template <typename Scalar, typename... Properties>
402 BOr(View<Scalar, Properties...> const&)
403  ->BOr<Scalar, typename View<Scalar, Properties...>::memory_space>;
404 
405 template <class Scalar, class Index>
406 struct ValLocScalar {
407  Scalar val;
408  Index loc;
409 };
410 
411 template <class Scalar, class Index, class Space>
412 struct MinLoc {
413  private:
414  using scalar_type = std::remove_cv_t<Scalar>;
415  using index_type = std::remove_cv_t<Index>;
416  static_assert(!std::is_pointer_v<scalar_type> &&
417  !std::is_array_v<scalar_type>);
418 
419  public:
420  // Required
421  using reducer = MinLoc<Scalar, Index, Space>;
422  using value_type = ValLocScalar<scalar_type, index_type>;
423 
424  using result_view_type = Kokkos::View<value_type, Space>;
425 
426  private:
427  result_view_type value;
428  bool references_scalar_v;
429 
430  public:
431  KOKKOS_INLINE_FUNCTION
432  MinLoc(value_type& value_) : value(&value_), references_scalar_v(true) {}
433 
434  KOKKOS_INLINE_FUNCTION
435  MinLoc(const result_view_type& value_)
436  : value(value_), references_scalar_v(false) {}
437 
438  // Required
439  KOKKOS_INLINE_FUNCTION
440  void join(value_type& dest, const value_type& src) const {
441  if (src.val < dest.val) dest = src;
442  }
443 
444  KOKKOS_INLINE_FUNCTION
445  void init(value_type& val) const {
446  val.val = reduction_identity<scalar_type>::min();
447  val.loc = reduction_identity<index_type>::min();
448  }
449 
450  KOKKOS_INLINE_FUNCTION
451  value_type& reference() const { return *value.data(); }
452 
453  KOKKOS_INLINE_FUNCTION
454  result_view_type view() const { return value; }
455 
456  KOKKOS_INLINE_FUNCTION
457  bool references_scalar() const { return references_scalar_v; }
458 };
459 
460 template <typename Scalar, typename Index, typename... Properties>
461 MinLoc(View<ValLocScalar<Scalar, Index>, Properties...> const&)
462  ->MinLoc<Scalar, Index,
463  typename View<ValLocScalar<Scalar, Index>,
464  Properties...>::memory_space>;
465 
466 template <class Scalar, class Index, class Space>
467 struct MaxLoc {
468  private:
469  using scalar_type = std::remove_cv_t<Scalar>;
470  using index_type = std::remove_cv_t<Index>;
471  static_assert(!std::is_pointer_v<scalar_type> &&
472  !std::is_array_v<scalar_type>);
473 
474  public:
475  // Required
476  using reducer = MaxLoc<Scalar, Index, Space>;
477  using value_type = ValLocScalar<scalar_type, index_type>;
478 
479  using result_view_type = Kokkos::View<value_type, Space>;
480 
481  private:
482  result_view_type value;
483  bool references_scalar_v;
484 
485  public:
486  KOKKOS_INLINE_FUNCTION
487  MaxLoc(value_type& value_) : value(&value_), references_scalar_v(true) {}
488 
489  KOKKOS_INLINE_FUNCTION
490  MaxLoc(const result_view_type& value_)
491  : value(value_), references_scalar_v(false) {}
492 
493  // Required
494  KOKKOS_INLINE_FUNCTION
495  void join(value_type& dest, const value_type& src) const {
496  if (src.val > dest.val) dest = src;
497  }
498 
499  KOKKOS_INLINE_FUNCTION
500  void init(value_type& val) const {
501  val.val = reduction_identity<scalar_type>::max();
502  val.loc = reduction_identity<index_type>::min();
503  }
504 
505  KOKKOS_INLINE_FUNCTION
506  value_type& reference() const { return *value.data(); }
507 
508  KOKKOS_INLINE_FUNCTION
509  result_view_type view() const { return value; }
510 
511  KOKKOS_INLINE_FUNCTION
512  bool references_scalar() const { return references_scalar_v; }
513 };
514 
515 template <typename Scalar, typename Index, typename... Properties>
516 MaxLoc(View<ValLocScalar<Scalar, Index>, Properties...> const&)
517  ->MaxLoc<Scalar, Index,
518  typename View<ValLocScalar<Scalar, Index>,
519  Properties...>::memory_space>;
520 
521 template <class Scalar>
522 struct MinMaxScalar {
523  Scalar min_val, max_val;
524 };
525 
526 template <class Scalar, class Space>
527 struct MinMax {
528  private:
529  using scalar_type = std::remove_cv_t<Scalar>;
530  static_assert(!std::is_pointer_v<scalar_type> &&
531  !std::is_array_v<scalar_type>);
532 
533  public:
534  // Required
535  using reducer = MinMax<Scalar, Space>;
536  using value_type = MinMaxScalar<scalar_type>;
537 
538  using result_view_type = Kokkos::View<value_type, Space>;
539 
540  private:
541  result_view_type value;
542  bool references_scalar_v;
543 
544  public:
545  KOKKOS_INLINE_FUNCTION
546  MinMax(value_type& value_) : value(&value_), references_scalar_v(true) {}
547 
548  KOKKOS_INLINE_FUNCTION
549  MinMax(const result_view_type& value_)
550  : value(value_), references_scalar_v(false) {}
551 
552  // Required
553  KOKKOS_INLINE_FUNCTION
554  void join(value_type& dest, const value_type& src) const {
555  if (src.min_val < dest.min_val) {
556  dest.min_val = src.min_val;
557  }
558  if (src.max_val > dest.max_val) {
559  dest.max_val = src.max_val;
560  }
561  }
562 
563  KOKKOS_INLINE_FUNCTION
564  void init(value_type& val) const {
565  val.max_val = reduction_identity<scalar_type>::max();
566  val.min_val = reduction_identity<scalar_type>::min();
567  }
568 
569  KOKKOS_INLINE_FUNCTION
570  value_type& reference() const { return *value.data(); }
571 
572  KOKKOS_INLINE_FUNCTION
573  result_view_type view() const { return value; }
574 
575  KOKKOS_INLINE_FUNCTION
576  bool references_scalar() const { return references_scalar_v; }
577 };
578 
579 template <typename Scalar, typename... Properties>
580 MinMax(View<MinMaxScalar<Scalar>, Properties...> const&)
581  ->MinMax<Scalar,
582  typename View<MinMaxScalar<Scalar>, Properties...>::memory_space>;
583 
584 template <class Scalar, class Index>
585 struct MinMaxLocScalar {
586  Scalar min_val, max_val;
587  Index min_loc, max_loc;
588 };
589 
590 template <class Scalar, class Index, class Space>
591 struct MinMaxLoc {
592  private:
593  using scalar_type = std::remove_cv_t<Scalar>;
594  using index_type = std::remove_cv_t<Index>;
595  static_assert(!std::is_pointer_v<scalar_type> &&
596  !std::is_array_v<scalar_type>);
597 
598  public:
599  // Required
600  using reducer = MinMaxLoc<Scalar, Index, Space>;
601  using value_type = MinMaxLocScalar<scalar_type, index_type>;
602 
603  using result_view_type = Kokkos::View<value_type, Space>;
604 
605  private:
606  result_view_type value;
607  bool references_scalar_v;
608 
609  public:
610  KOKKOS_INLINE_FUNCTION
611  MinMaxLoc(value_type& value_) : value(&value_), references_scalar_v(true) {}
612 
613  KOKKOS_INLINE_FUNCTION
614  MinMaxLoc(const result_view_type& value_)
615  : value(value_), references_scalar_v(false) {}
616 
617  // Required
618  KOKKOS_INLINE_FUNCTION
619  void join(value_type& dest, const value_type& src) const {
620  if (src.min_val < dest.min_val) {
621  dest.min_val = src.min_val;
622  dest.min_loc = src.min_loc;
623  }
624  if (src.max_val > dest.max_val) {
625  dest.max_val = src.max_val;
626  dest.max_loc = src.max_loc;
627  }
628  }
629 
630  KOKKOS_INLINE_FUNCTION
631  void init(value_type& val) const {
632  val.max_val = reduction_identity<scalar_type>::max();
633  val.min_val = reduction_identity<scalar_type>::min();
634  val.max_loc = reduction_identity<index_type>::min();
635  val.min_loc = reduction_identity<index_type>::min();
636  }
637 
638  KOKKOS_INLINE_FUNCTION
639  value_type& reference() const { return *value.data(); }
640 
641  KOKKOS_INLINE_FUNCTION
642  result_view_type view() const { return value; }
643 
644  KOKKOS_INLINE_FUNCTION
645  bool references_scalar() const { return references_scalar_v; }
646 };
647 
648 template <typename Scalar, typename Index, typename... Properties>
649 MinMaxLoc(View<MinMaxLocScalar<Scalar, Index>, Properties...> const&)
650  ->MinMaxLoc<Scalar, Index,
651  typename View<MinMaxLocScalar<Scalar, Index>,
652  Properties...>::memory_space>;
653 
654 // --------------------------------------------------
655 // reducers added to support std algorithms
656 // --------------------------------------------------
657 
658 //
659 // MaxFirstLoc
660 //
661 template <class Scalar, class Index, class Space>
662 struct MaxFirstLoc {
663  private:
664  using scalar_type = std::remove_cv_t<Scalar>;
665  using index_type = std::remove_cv_t<Index>;
666  static_assert(!std::is_pointer_v<scalar_type> &&
667  !std::is_array_v<scalar_type>);
668  static_assert(std::is_integral_v<index_type>);
669 
670  public:
671  // Required
672  using reducer = MaxFirstLoc<Scalar, Index, Space>;
673  using value_type = ::Kokkos::ValLocScalar<scalar_type, index_type>;
674 
675  using result_view_type = ::Kokkos::View<value_type, Space>;
676 
677  private:
678  result_view_type value;
679  bool references_scalar_v;
680 
681  public:
682  KOKKOS_INLINE_FUNCTION
683  MaxFirstLoc(value_type& value_) : value(&value_), references_scalar_v(true) {}
684 
685  KOKKOS_INLINE_FUNCTION
686  MaxFirstLoc(const result_view_type& value_)
687  : value(value_), references_scalar_v(false) {}
688 
689  // Required
690  KOKKOS_INLINE_FUNCTION
691  void join(value_type& dest, const value_type& src) const {
692  if (dest.val < src.val) {
693  dest = src;
694  } else if (!(src.val < dest.val)) {
695  dest.loc = (src.loc < dest.loc) ? src.loc : dest.loc;
696  }
697  }
698 
699  KOKKOS_INLINE_FUNCTION
700  void init(value_type& val) const {
701  val.val = reduction_identity<scalar_type>::max();
702  val.loc = reduction_identity<index_type>::min();
703  }
704 
705  KOKKOS_INLINE_FUNCTION
706  value_type& reference() const { return *value.data(); }
707 
708  KOKKOS_INLINE_FUNCTION
709  result_view_type view() const { return value; }
710 
711  KOKKOS_INLINE_FUNCTION
712  bool references_scalar() const { return references_scalar_v; }
713 };
714 
715 template <typename Scalar, typename Index, typename... Properties>
716 MaxFirstLoc(View<ValLocScalar<Scalar, Index>, Properties...> const&)
717  ->MaxFirstLoc<Scalar, Index,
718  typename View<ValLocScalar<Scalar, Index>,
719  Properties...>::memory_space>;
720 
721 //
722 // MaxFirstLocCustomComparator
723 // recall that comp(a,b) returns true is a < b
724 //
725 template <class Scalar, class Index, class ComparatorType, class Space>
726 struct MaxFirstLocCustomComparator {
727  private:
728  using scalar_type = std::remove_cv_t<Scalar>;
729  using index_type = std::remove_cv_t<Index>;
730  static_assert(!std::is_pointer_v<scalar_type> &&
731  !std::is_array_v<scalar_type>);
732  static_assert(std::is_integral_v<index_type>);
733 
734  public:
735  // Required
736  using reducer =
737  MaxFirstLocCustomComparator<Scalar, Index, ComparatorType, Space>;
738  using value_type = ::Kokkos::ValLocScalar<scalar_type, index_type>;
739 
740  using result_view_type = ::Kokkos::View<value_type, Space>;
741 
742  private:
743  result_view_type value;
744  bool references_scalar_v;
745  ComparatorType m_comp;
746 
747  public:
748  KOKKOS_INLINE_FUNCTION
749  MaxFirstLocCustomComparator(value_type& value_, ComparatorType comp_)
750  : value(&value_), references_scalar_v(true), m_comp(comp_) {}
751 
752  KOKKOS_INLINE_FUNCTION
753  MaxFirstLocCustomComparator(const result_view_type& value_,
754  ComparatorType comp_)
755  : value(value_), references_scalar_v(false), m_comp(comp_) {}
756 
757  // Required
758  KOKKOS_INLINE_FUNCTION
759  void join(value_type& dest, const value_type& src) const {
760  if (m_comp(dest.val, src.val)) {
761  dest = src;
762  } else if (!m_comp(src.val, dest.val)) {
763  dest.loc = (src.loc < dest.loc) ? src.loc : dest.loc;
764  }
765  }
766 
767  KOKKOS_INLINE_FUNCTION
768  void init(value_type& val) const {
769  val.val = reduction_identity<scalar_type>::max();
770  val.loc = reduction_identity<index_type>::min();
771  }
772 
773  KOKKOS_INLINE_FUNCTION
774  value_type& reference() const { return *value.data(); }
775 
776  KOKKOS_INLINE_FUNCTION
777  result_view_type view() const { return value; }
778 
779  KOKKOS_INLINE_FUNCTION
780  bool references_scalar() const { return references_scalar_v; }
781 };
782 
783 template <typename Scalar, typename Index, typename ComparatorType,
784  typename... Properties>
785 MaxFirstLocCustomComparator(
786  View<ValLocScalar<Scalar, Index>, Properties...> const&, ComparatorType)
787  ->MaxFirstLocCustomComparator<Scalar, Index, ComparatorType,
788  typename View<ValLocScalar<Scalar, Index>,
789  Properties...>::memory_space>;
790 
791 //
792 // MinFirstLoc
793 //
794 template <class Scalar, class Index, class Space>
795 struct MinFirstLoc {
796  private:
797  using scalar_type = std::remove_cv_t<Scalar>;
798  using index_type = std::remove_cv_t<Index>;
799  static_assert(!std::is_pointer_v<scalar_type> &&
800  !std::is_array_v<scalar_type>);
801  static_assert(std::is_integral_v<index_type>);
802 
803  public:
804  // Required
805  using reducer = MinFirstLoc<Scalar, Index, Space>;
806  using value_type = ::Kokkos::ValLocScalar<scalar_type, index_type>;
807 
808  using result_view_type = ::Kokkos::View<value_type, Space>;
809 
810  private:
811  result_view_type value;
812  bool references_scalar_v;
813 
814  public:
815  KOKKOS_INLINE_FUNCTION
816  MinFirstLoc(value_type& value_) : value(&value_), references_scalar_v(true) {}
817 
818  KOKKOS_INLINE_FUNCTION
819  MinFirstLoc(const result_view_type& value_)
820  : value(value_), references_scalar_v(false) {}
821 
822  // Required
823  KOKKOS_INLINE_FUNCTION
824  void join(value_type& dest, const value_type& src) const {
825  if (src.val < dest.val) {
826  dest = src;
827  } else if (!(dest.val < src.val)) {
828  dest.loc = (src.loc < dest.loc) ? src.loc : dest.loc;
829  }
830  }
831 
832  KOKKOS_INLINE_FUNCTION
833  void init(value_type& val) const {
834  val.val = reduction_identity<scalar_type>::min();
835  val.loc = reduction_identity<index_type>::min();
836  }
837 
838  KOKKOS_INLINE_FUNCTION
839  value_type& reference() const { return *value.data(); }
840 
841  KOKKOS_INLINE_FUNCTION
842  result_view_type view() const { return value; }
843 
844  KOKKOS_INLINE_FUNCTION
845  bool references_scalar() const { return references_scalar_v; }
846 };
847 
848 template <typename Scalar, typename Index, typename... Properties>
849 MinFirstLoc(View<ValLocScalar<Scalar, Index>, Properties...> const&)
850  ->MinFirstLoc<Scalar, Index,
851  typename View<ValLocScalar<Scalar, Index>,
852  Properties...>::memory_space>;
853 
854 //
855 // MinFirstLocCustomComparator
856 // recall that comp(a,b) returns true is a < b
857 //
858 template <class Scalar, class Index, class ComparatorType, class Space>
859 struct MinFirstLocCustomComparator {
860  private:
861  using scalar_type = std::remove_cv_t<Scalar>;
862  using index_type = std::remove_cv_t<Index>;
863  static_assert(!std::is_pointer_v<scalar_type> &&
864  !std::is_array_v<scalar_type>);
865  static_assert(std::is_integral_v<index_type>);
866 
867  public:
868  // Required
869  using reducer =
870  MinFirstLocCustomComparator<Scalar, Index, ComparatorType, Space>;
871  using value_type = ::Kokkos::ValLocScalar<scalar_type, index_type>;
872 
873  using result_view_type = ::Kokkos::View<value_type, Space>;
874 
875  private:
876  result_view_type value;
877  bool references_scalar_v;
878  ComparatorType m_comp;
879 
880  public:
881  KOKKOS_INLINE_FUNCTION
882  MinFirstLocCustomComparator(value_type& value_, ComparatorType comp_)
883  : value(&value_), references_scalar_v(true), m_comp(comp_) {}
884 
885  KOKKOS_INLINE_FUNCTION
886  MinFirstLocCustomComparator(const result_view_type& value_,
887  ComparatorType comp_)
888  : value(value_), references_scalar_v(false), m_comp(comp_) {}
889 
890  // Required
891  KOKKOS_INLINE_FUNCTION
892  void join(value_type& dest, const value_type& src) const {
893  if (m_comp(src.val, dest.val)) {
894  dest = src;
895  } else if (!m_comp(dest.val, src.val)) {
896  dest.loc = (src.loc < dest.loc) ? src.loc : dest.loc;
897  }
898  }
899 
900  KOKKOS_INLINE_FUNCTION
901  void init(value_type& val) const {
902  val.val = reduction_identity<scalar_type>::min();
903  val.loc = reduction_identity<index_type>::min();
904  }
905 
906  KOKKOS_INLINE_FUNCTION
907  value_type& reference() const { return *value.data(); }
908 
909  KOKKOS_INLINE_FUNCTION
910  result_view_type view() const { return value; }
911 
912  KOKKOS_INLINE_FUNCTION
913  bool references_scalar() const { return references_scalar_v; }
914 };
915 
916 template <typename Scalar, typename Index, typename ComparatorType,
917  typename... Properties>
918 MinFirstLocCustomComparator(
919  View<ValLocScalar<Scalar, Index>, Properties...> const&, ComparatorType)
920  ->MinFirstLocCustomComparator<Scalar, Index, ComparatorType,
921  typename View<ValLocScalar<Scalar, Index>,
922  Properties...>::memory_space>;
923 
924 //
925 // MinMaxFirstLastLoc
926 //
927 template <class Scalar, class Index, class Space>
928 struct MinMaxFirstLastLoc {
929  private:
930  using scalar_type = std::remove_cv_t<Scalar>;
931  using index_type = std::remove_cv_t<Index>;
932  static_assert(!std::is_pointer_v<scalar_type> &&
933  !std::is_array_v<scalar_type>);
934  static_assert(std::is_integral_v<index_type>);
935 
936  public:
937  // Required
938  using reducer = MinMaxFirstLastLoc<Scalar, Index, Space>;
939  using value_type = ::Kokkos::MinMaxLocScalar<scalar_type, index_type>;
940 
941  using result_view_type = ::Kokkos::View<value_type, Space>;
942 
943  private:
944  result_view_type value;
945  bool references_scalar_v;
946 
947  public:
948  KOKKOS_INLINE_FUNCTION
949  MinMaxFirstLastLoc(value_type& value_)
950  : value(&value_), references_scalar_v(true) {}
951 
952  KOKKOS_INLINE_FUNCTION
953  MinMaxFirstLastLoc(const result_view_type& value_)
954  : value(value_), references_scalar_v(false) {}
955 
956  // Required
957  KOKKOS_INLINE_FUNCTION
958  void join(value_type& dest, const value_type& src) const {
959  if (src.min_val < dest.min_val) {
960  dest.min_val = src.min_val;
961  dest.min_loc = src.min_loc;
962  } else if (!(dest.min_val < src.min_val)) {
963  dest.min_loc = (src.min_loc < dest.min_loc) ? src.min_loc : dest.min_loc;
964  }
965 
966  if (dest.max_val < src.max_val) {
967  dest.max_val = src.max_val;
968  dest.max_loc = src.max_loc;
969  } else if (!(src.max_val < dest.max_val)) {
970  dest.max_loc = (src.max_loc > dest.max_loc) ? src.max_loc : dest.max_loc;
971  }
972  }
973 
974  KOKKOS_INLINE_FUNCTION
975  void init(value_type& val) const {
976  val.max_val = ::Kokkos::reduction_identity<scalar_type>::max();
977  val.min_val = ::Kokkos::reduction_identity<scalar_type>::min();
978  val.max_loc = ::Kokkos::reduction_identity<index_type>::max();
979  val.min_loc = ::Kokkos::reduction_identity<index_type>::min();
980  }
981 
982  KOKKOS_INLINE_FUNCTION
983  value_type& reference() const { return *value.data(); }
984 
985  KOKKOS_INLINE_FUNCTION
986  result_view_type view() const { return value; }
987 
988  KOKKOS_INLINE_FUNCTION
989  bool references_scalar() const { return references_scalar_v; }
990 };
991 
992 template <typename Scalar, typename Index, typename... Properties>
993 MinMaxFirstLastLoc(View<MinMaxLocScalar<Scalar, Index>, Properties...> const&)
994  ->MinMaxFirstLastLoc<Scalar, Index,
995  typename View<MinMaxLocScalar<Scalar, Index>,
996  Properties...>::memory_space>;
997 
998 //
999 // MinMaxFirstLastLocCustomComparator
1000 // recall that comp(a,b) returns true is a < b
1001 //
1002 template <class Scalar, class Index, class ComparatorType, class Space>
1003 struct MinMaxFirstLastLocCustomComparator {
1004  private:
1005  using scalar_type = std::remove_cv_t<Scalar>;
1006  using index_type = std::remove_cv_t<Index>;
1007  static_assert(!std::is_pointer_v<scalar_type> &&
1008  !std::is_array_v<scalar_type>);
1009  static_assert(std::is_integral_v<index_type>);
1010 
1011  public:
1012  // Required
1013  using reducer =
1014  MinMaxFirstLastLocCustomComparator<Scalar, Index, ComparatorType, Space>;
1015  using value_type = ::Kokkos::MinMaxLocScalar<scalar_type, index_type>;
1016 
1017  using result_view_type = ::Kokkos::View<value_type, Space>;
1018 
1019  private:
1020  result_view_type value;
1021  bool references_scalar_v;
1022  ComparatorType m_comp;
1023 
1024  public:
1025  KOKKOS_INLINE_FUNCTION
1026  MinMaxFirstLastLocCustomComparator(value_type& value_, ComparatorType comp_)
1027  : value(&value_), references_scalar_v(true), m_comp(comp_) {}
1028 
1029  KOKKOS_INLINE_FUNCTION
1030  MinMaxFirstLastLocCustomComparator(const result_view_type& value_,
1031  ComparatorType comp_)
1032  : value(value_), references_scalar_v(false), m_comp(comp_) {}
1033 
1034  // Required
1035  KOKKOS_INLINE_FUNCTION
1036  void join(value_type& dest, const value_type& src) const {
1037  if (m_comp(src.min_val, dest.min_val)) {
1038  dest.min_val = src.min_val;
1039  dest.min_loc = src.min_loc;
1040  } else if (!m_comp(dest.min_val, src.min_val)) {
1041  dest.min_loc = (src.min_loc < dest.min_loc) ? src.min_loc : dest.min_loc;
1042  }
1043 
1044  if (m_comp(dest.max_val, src.max_val)) {
1045  dest.max_val = src.max_val;
1046  dest.max_loc = src.max_loc;
1047  } else if (!m_comp(src.max_val, dest.max_val)) {
1048  dest.max_loc = (src.max_loc > dest.max_loc) ? src.max_loc : dest.max_loc;
1049  }
1050  }
1051 
1052  KOKKOS_INLINE_FUNCTION
1053  void init(value_type& val) const {
1054  val.max_val = ::Kokkos::reduction_identity<scalar_type>::max();
1055  val.min_val = ::Kokkos::reduction_identity<scalar_type>::min();
1056  val.max_loc = ::Kokkos::reduction_identity<index_type>::max();
1057  val.min_loc = ::Kokkos::reduction_identity<index_type>::min();
1058  }
1059 
1060  KOKKOS_INLINE_FUNCTION
1061  value_type& reference() const { return *value.data(); }
1062 
1063  KOKKOS_INLINE_FUNCTION
1064  result_view_type view() const { return value; }
1065 
1066  KOKKOS_INLINE_FUNCTION
1067  bool references_scalar() const { return references_scalar_v; }
1068 };
1069 
1070 template <typename Scalar, typename Index, typename ComparatorType,
1071  typename... Properties>
1072 MinMaxFirstLastLocCustomComparator(
1073  View<MinMaxLocScalar<Scalar, Index>, Properties...> const&, ComparatorType)
1074  ->MinMaxFirstLastLocCustomComparator<
1075  Scalar, Index, ComparatorType,
1076  typename View<MinMaxLocScalar<Scalar, Index>,
1077  Properties...>::memory_space>;
1078 
1079 //
1080 // FirstLoc
1081 //
1082 template <class Index>
1083 struct FirstLocScalar {
1084  Index min_loc_true;
1085 };
1086 
1087 template <class Index, class Space>
1088 struct FirstLoc {
1089  private:
1090  using index_type = std::remove_cv_t<Index>;
1091  static_assert(std::is_integral_v<index_type>);
1092 
1093  public:
1094  // Required
1095  using reducer = FirstLoc<Index, Space>;
1096  using value_type = FirstLocScalar<index_type>;
1097 
1098  using result_view_type = ::Kokkos::View<value_type, Space>;
1099 
1100  private:
1101  result_view_type value;
1102  bool references_scalar_v;
1103 
1104  public:
1105  KOKKOS_INLINE_FUNCTION
1106  FirstLoc(value_type& value_) : value(&value_), references_scalar_v(true) {}
1107 
1108  KOKKOS_INLINE_FUNCTION
1109  FirstLoc(const result_view_type& value_)
1110  : value(value_), references_scalar_v(false) {}
1111 
1112  // Required
1113  KOKKOS_INLINE_FUNCTION
1114  void join(value_type& dest, const value_type& src) const {
1115  dest.min_loc_true = (src.min_loc_true < dest.min_loc_true)
1116  ? src.min_loc_true
1117  : dest.min_loc_true;
1118  }
1119 
1120  KOKKOS_INLINE_FUNCTION
1121  void init(value_type& val) const {
1122  val.min_loc_true = ::Kokkos::reduction_identity<index_type>::min();
1123  }
1124 
1125  KOKKOS_INLINE_FUNCTION
1126  value_type& reference() const { return *value.data(); }
1127 
1128  KOKKOS_INLINE_FUNCTION
1129  result_view_type view() const { return value; }
1130 
1131  KOKKOS_INLINE_FUNCTION
1132  bool references_scalar() const { return references_scalar_v; }
1133 };
1134 
1135 template <typename Index, typename... Properties>
1136 FirstLoc(View<FirstLocScalar<Index>, Properties...> const&)
1137  ->FirstLoc<Index, typename View<FirstLocScalar<Index>,
1138  Properties...>::memory_space>;
1139 
1140 //
1141 // LastLoc
1142 //
1143 template <class Index>
1144 struct LastLocScalar {
1145  Index max_loc_true;
1146 };
1147 
1148 template <class Index, class Space>
1149 struct LastLoc {
1150  private:
1151  using index_type = std::remove_cv_t<Index>;
1152  static_assert(std::is_integral_v<index_type>);
1153 
1154  public:
1155  // Required
1156  using reducer = LastLoc<Index, Space>;
1157  using value_type = LastLocScalar<index_type>;
1158 
1159  using result_view_type = ::Kokkos::View<value_type, Space>;
1160 
1161  private:
1162  result_view_type value;
1163  bool references_scalar_v;
1164 
1165  public:
1166  KOKKOS_INLINE_FUNCTION
1167  LastLoc(value_type& value_) : value(&value_), references_scalar_v(true) {}
1168 
1169  KOKKOS_INLINE_FUNCTION
1170  LastLoc(const result_view_type& value_)
1171  : value(value_), references_scalar_v(false) {}
1172 
1173  // Required
1174  KOKKOS_INLINE_FUNCTION
1175  void join(value_type& dest, const value_type& src) const {
1176  dest.max_loc_true = (src.max_loc_true > dest.max_loc_true)
1177  ? src.max_loc_true
1178  : dest.max_loc_true;
1179  }
1180 
1181  KOKKOS_INLINE_FUNCTION
1182  void init(value_type& val) const {
1183  val.max_loc_true = ::Kokkos::reduction_identity<index_type>::max();
1184  }
1185 
1186  KOKKOS_INLINE_FUNCTION
1187  value_type& reference() const { return *value.data(); }
1188 
1189  KOKKOS_INLINE_FUNCTION
1190  result_view_type view() const { return value; }
1191 
1192  KOKKOS_INLINE_FUNCTION
1193  bool references_scalar() const { return references_scalar_v; }
1194 };
1195 
1196 template <typename Index, typename... Properties>
1197 LastLoc(View<LastLocScalar<Index>, Properties...> const&)
1198  ->LastLoc<Index,
1199  typename View<LastLocScalar<Index>, Properties...>::memory_space>;
1200 
1201 template <class Index>
1202 struct StdIsPartScalar {
1203  Index max_loc_true, min_loc_false;
1204 };
1205 
1206 //
1207 // StdIsPartitioned
1208 //
1209 template <class Index, class Space>
1210 struct StdIsPartitioned {
1211  private:
1212  using index_type = std::remove_cv_t<Index>;
1213  static_assert(std::is_integral_v<index_type>);
1214 
1215  public:
1216  // Required
1217  using reducer = StdIsPartitioned<Index, Space>;
1218  using value_type = StdIsPartScalar<index_type>;
1219 
1220  using result_view_type = ::Kokkos::View<value_type, Space>;
1221 
1222  private:
1223  result_view_type value;
1224  bool references_scalar_v;
1225 
1226  public:
1227  KOKKOS_INLINE_FUNCTION
1228  StdIsPartitioned(value_type& value_)
1229  : value(&value_), references_scalar_v(true) {}
1230 
1231  KOKKOS_INLINE_FUNCTION
1232  StdIsPartitioned(const result_view_type& value_)
1233  : value(value_), references_scalar_v(false) {}
1234 
1235  // Required
1236  KOKKOS_INLINE_FUNCTION
1237  void join(value_type& dest, const value_type& src) const {
1238  dest.max_loc_true = (dest.max_loc_true < src.max_loc_true)
1239  ? src.max_loc_true
1240  : dest.max_loc_true;
1241 
1242  dest.min_loc_false = (dest.min_loc_false < src.min_loc_false)
1243  ? dest.min_loc_false
1244  : src.min_loc_false;
1245  }
1246 
1247  KOKKOS_INLINE_FUNCTION
1248  void init(value_type& val) const {
1249  val.max_loc_true = ::Kokkos::reduction_identity<index_type>::max();
1250  val.min_loc_false = ::Kokkos::reduction_identity<index_type>::min();
1251  }
1252 
1253  KOKKOS_INLINE_FUNCTION
1254  value_type& reference() const { return *value.data(); }
1255 
1256  KOKKOS_INLINE_FUNCTION
1257  result_view_type view() const { return value; }
1258 
1259  KOKKOS_INLINE_FUNCTION
1260  bool references_scalar() const { return references_scalar_v; }
1261 };
1262 
1263 template <typename Index, typename... Properties>
1264 StdIsPartitioned(View<StdIsPartScalar<Index>, Properties...> const&)
1265  ->StdIsPartitioned<Index, typename View<StdIsPartScalar<Index>,
1266  Properties...>::memory_space>;
1267 
1268 template <class Index>
1269 struct StdPartPointScalar {
1270  Index min_loc_false;
1271 };
1272 
1273 //
1274 // StdPartitionPoint
1275 //
1276 template <class Index, class Space>
1277 struct StdPartitionPoint {
1278  private:
1279  using index_type = std::remove_cv_t<Index>;
1280  static_assert(std::is_integral_v<index_type>);
1281 
1282  public:
1283  // Required
1284  using reducer = StdPartitionPoint<Index, Space>;
1285  using value_type = StdPartPointScalar<index_type>;
1286 
1287  using result_view_type = ::Kokkos::View<value_type, Space>;
1288 
1289  private:
1290  result_view_type value;
1291  bool references_scalar_v;
1292 
1293  public:
1294  KOKKOS_INLINE_FUNCTION
1295  StdPartitionPoint(value_type& value_)
1296  : value(&value_), references_scalar_v(true) {}
1297 
1298  KOKKOS_INLINE_FUNCTION
1299  StdPartitionPoint(const result_view_type& value_)
1300  : value(value_), references_scalar_v(false) {}
1301 
1302  // Required
1303  KOKKOS_INLINE_FUNCTION
1304  void join(value_type& dest, const value_type& src) const {
1305  dest.min_loc_false = (dest.min_loc_false < src.min_loc_false)
1306  ? dest.min_loc_false
1307  : src.min_loc_false;
1308  }
1309 
1310  KOKKOS_INLINE_FUNCTION
1311  void init(value_type& val) const {
1312  val.min_loc_false = ::Kokkos::reduction_identity<index_type>::min();
1313  }
1314 
1315  KOKKOS_INLINE_FUNCTION
1316  value_type& reference() const { return *value.data(); }
1317 
1318  KOKKOS_INLINE_FUNCTION
1319  result_view_type view() const { return value; }
1320 
1321  KOKKOS_INLINE_FUNCTION
1322  bool references_scalar() const { return references_scalar_v; }
1323 };
1324 
1325 template <typename Index, typename... Properties>
1326 StdPartitionPoint(View<StdPartPointScalar<Index>, Properties...> const&)
1327  ->StdPartitionPoint<Index, typename View<StdPartPointScalar<Index>,
1328  Properties...>::memory_space>;
1329 
1330 } // namespace Kokkos
1331 namespace Kokkos {
1332 namespace Impl {
1333 
1334 template <typename FunctorType, typename FunctorAnalysisReducerType,
1335  typename Enable>
1336 class CombinedFunctorReducer {
1337  public:
1338  using functor_type = FunctorType;
1339  using reducer_type = FunctorAnalysisReducerType;
1340  CombinedFunctorReducer(const FunctorType& functor,
1341  const FunctorAnalysisReducerType& reducer)
1342  : m_functor(functor), m_reducer(reducer) {}
1343  KOKKOS_FUNCTION const FunctorType& get_functor() const { return m_functor; }
1344  KOKKOS_FUNCTION const FunctorAnalysisReducerType& get_reducer() const {
1345  return m_reducer;
1346  }
1347 
1348  private:
1349  FunctorType m_functor;
1350  FunctorAnalysisReducerType m_reducer;
1351 };
1352 template <typename FunctorType, typename FunctorAnalysisReducerType>
1353 class CombinedFunctorReducer<
1354  FunctorType, FunctorAnalysisReducerType,
1355  std::enable_if_t<std::is_same_v<
1356  FunctorType, typename FunctorAnalysisReducerType::functor_type>>> {
1357  public:
1358  using functor_type = FunctorType;
1359  using reducer_type = FunctorAnalysisReducerType;
1360  CombinedFunctorReducer(const FunctorType& functor,
1361  const FunctorAnalysisReducerType&)
1362  : m_reducer(functor) {}
1363  KOKKOS_FUNCTION const FunctorType& get_functor() const {
1364  return m_reducer.get_functor();
1365  }
1366  KOKKOS_FUNCTION const FunctorAnalysisReducerType& get_reducer() const {
1367  return m_reducer;
1368  }
1369 
1370  private:
1371  FunctorAnalysisReducerType m_reducer;
1372 };
1373 
1374 template <class T, class ReturnType, class ValueTraits>
1375 struct ParallelReduceReturnValue;
1376 
1377 template <class ReturnType, class FunctorType>
1378 struct ParallelReduceReturnValue<
1379  std::enable_if_t<Kokkos::is_view<ReturnType>::value>, ReturnType,
1380  FunctorType> {
1381  using return_type = ReturnType;
1382  using reducer_type = InvalidType;
1383 
1384  using value_type_scalar = typename return_type::value_type;
1385  using value_type_array = typename return_type::value_type* const;
1386 
1387  using value_type = std::conditional_t<return_type::rank == 0,
1388  value_type_scalar, value_type_array>;
1389 
1390  static return_type& return_value(ReturnType& return_val, const FunctorType&) {
1391  return return_val;
1392  }
1393 };
1394 
1395 template <class ReturnType, class FunctorType>
1396 struct ParallelReduceReturnValue<
1397  std::enable_if_t<!Kokkos::is_view<ReturnType>::value &&
1398  (!std::is_array<ReturnType>::value &&
1399  !std::is_pointer<ReturnType>::value) &&
1400  !Kokkos::is_reducer<ReturnType>::value>,
1401  ReturnType, FunctorType> {
1402  using return_type =
1404 
1405  using reducer_type = InvalidType;
1406 
1407  using value_type = typename return_type::value_type;
1408 
1409  static return_type return_value(ReturnType& return_val, const FunctorType&) {
1410  return return_type(&return_val);
1411  }
1412 };
1413 
1414 template <class ReturnType, class FunctorType>
1415 struct ParallelReduceReturnValue<
1416  std::enable_if_t<(std::is_array<ReturnType>::value ||
1417  std::is_pointer<ReturnType>::value)>,
1418  ReturnType, FunctorType> {
1420  Kokkos::HostSpace, Kokkos::MemoryUnmanaged>;
1421 
1422  using reducer_type = InvalidType;
1423 
1424  using value_type = typename return_type::value_type[];
1425 
1426  static return_type return_value(ReturnType& return_val,
1427  const FunctorType& functor) {
1428  if (std::is_array<ReturnType>::value)
1429  return return_type(return_val);
1430  else
1431  return return_type(return_val, functor.value_count);
1432  }
1433 };
1434 
1435 template <class ReturnType, class FunctorType>
1436 struct ParallelReduceReturnValue<
1437  std::enable_if_t<Kokkos::is_reducer<ReturnType>::value>, ReturnType,
1438  FunctorType> {
1439  using return_type = typename ReturnType::result_view_type;
1440  using reducer_type = ReturnType;
1441  using value_type = typename return_type::value_type;
1442 
1443  static auto return_value(ReturnType& return_val, const FunctorType&) {
1444  return return_val.view();
1445  }
1446 };
1447 
1448 template <class T, class ReturnType, class FunctorType>
1449 struct ParallelReducePolicyType;
1450 
1451 template <class PolicyType, class FunctorType>
1452 struct ParallelReducePolicyType<
1453  std::enable_if_t<Kokkos::is_execution_policy<PolicyType>::value>,
1454  PolicyType, FunctorType> {
1455  using policy_type = PolicyType;
1456  static PolicyType policy(const PolicyType& policy_) { return policy_; }
1457 };
1458 
1459 template <class PolicyType, class FunctorType>
1460 struct ParallelReducePolicyType<
1461  std::enable_if_t<std::is_integral<PolicyType>::value>, PolicyType,
1462  FunctorType> {
1463  using execution_space =
1464  typename Impl::FunctorPolicyExecutionSpace<FunctorType,
1465  void>::execution_space;
1466 
1467  using policy_type = Kokkos::RangePolicy<execution_space>;
1468 
1469  static policy_type policy(const PolicyType& policy_) {
1470  return policy_type(0, policy_);
1471  }
1472 };
1473 
1474 template <class FunctorType, class ExecPolicy, class ValueType,
1475  class ExecutionSpace>
1476 struct ParallelReduceFunctorType {
1477  using functor_type = FunctorType;
1478  static const functor_type& functor(const functor_type& functor) {
1479  return functor;
1480  }
1481 };
1482 
1483 template <class PolicyType, class FunctorType, class ReturnType>
1484 struct ParallelReduceAdaptor {
1485  using return_value_adapter =
1486  Impl::ParallelReduceReturnValue<void, ReturnType, FunctorType>;
1487 
1488  static inline void execute_impl(const std::string& label,
1489  const PolicyType& policy,
1490  const FunctorType& functor,
1491  ReturnType& return_value) {
1492  using PassedReducerType = typename return_value_adapter::reducer_type;
1493  uint64_t kpID = 0;
1494 
1495  PolicyType inner_policy = policy;
1496  Kokkos::Tools::Impl::begin_parallel_reduce<PassedReducerType>(
1497  inner_policy, functor, label, kpID);
1498 
1499  using ReducerSelector =
1500  Kokkos::Impl::if_c<std::is_same<InvalidType, PassedReducerType>::value,
1501  FunctorType, PassedReducerType>;
1502  using Analysis = FunctorAnalysis<FunctorPatternInterface::REDUCE,
1503  PolicyType, typename ReducerSelector::type,
1504  typename return_value_adapter::value_type>;
1505  Kokkos::Impl::shared_allocation_tracking_disable();
1506  CombinedFunctorReducer functor_reducer(
1507  functor, typename Analysis::Reducer(
1508  ReducerSelector::select(functor, return_value)));
1509 
1510  // FIXME Remove "Wrapper" once all backends implement the new interface
1511  Impl::ParallelReduce<decltype(functor_reducer), PolicyType,
1512  typename Impl::FunctorPolicyExecutionSpace<
1513  FunctorType, PolicyType>::execution_space>
1514  closure(functor_reducer, inner_policy,
1515  return_value_adapter::return_value(return_value, functor));
1516  Kokkos::Impl::shared_allocation_tracking_enable();
1517  closure.execute();
1518 
1519  Kokkos::Tools::Impl::end_parallel_reduce<PassedReducerType>(
1520  inner_policy, functor, label, kpID);
1521  }
1522 
1523  static constexpr bool is_array_reduction =
1524  Impl::FunctorAnalysis<
1525  Impl::FunctorPatternInterface::REDUCE, PolicyType, FunctorType,
1526  typename return_value_adapter::value_type>::StaticValueSize == 0;
1527 
1528  template <typename Dummy = ReturnType>
1529  static inline std::enable_if_t<!(is_array_reduction &&
1530  std::is_pointer<Dummy>::value)>
1531  execute(const std::string& label, const PolicyType& policy,
1532  const FunctorType& functor, ReturnType& return_value) {
1533  execute_impl(label, policy, functor, return_value);
1534  }
1535 };
1536 } // namespace Impl
1537 
1538 //----------------------------------------------------------------------------
1539 
1551 // Parallel Reduce Blocking behavior
1552 
1553 namespace Impl {
1554 template <typename T>
1555 struct ReducerHasTestReferenceFunction {
1556  template <typename E>
1557  static std::true_type test_func(decltype(&E::references_scalar));
1558  template <typename E>
1559  static std::false_type test_func(...);
1560 
1561  enum {
1562  value = std::is_same<std::true_type, decltype(test_func<T>(nullptr))>::value
1563  };
1564 };
1565 
1566 template <class ExecutionSpace, class Arg>
1567 constexpr std::enable_if_t<
1568  // constraints only necessary because SFINAE lacks subsumption
1569  !ReducerHasTestReferenceFunction<Arg>::value &&
1570  !Kokkos::is_view<Arg>::value,
1571  // return type:
1572  bool>
1573 parallel_reduce_needs_fence(ExecutionSpace const&, Arg const&) {
1574  return true;
1575 }
1576 
1577 template <class ExecutionSpace, class Reducer>
1578 constexpr std::enable_if_t<
1579  // equivalent to:
1580  // (requires (Reducer const& r) {
1581  // { reducer.references_scalar() } -> std::convertible_to<bool>;
1582  // })
1583  ReducerHasTestReferenceFunction<Reducer>::value,
1584  // return type:
1585  bool>
1586 parallel_reduce_needs_fence(ExecutionSpace const&, Reducer const& reducer) {
1587  return reducer.references_scalar();
1588 }
1589 
1590 template <class ExecutionSpace, class ViewLike>
1591 constexpr std::enable_if_t<
1592  // requires Kokkos::ViewLike<ViewLike>
1593  Kokkos::is_view<ViewLike>::value,
1594  // return type:
1595  bool>
1596 parallel_reduce_needs_fence(ExecutionSpace const&, ViewLike const&) {
1597  return false;
1598 }
1599 
1600 template <class ExecutionSpace, class... Args>
1601 struct ParallelReduceFence {
1602  template <class... ArgsDeduced>
1603  static void fence(const ExecutionSpace& ex, const std::string& name,
1604  ArgsDeduced&&... args) {
1605  if (Impl::parallel_reduce_needs_fence(ex, (ArgsDeduced &&) args...)) {
1606  ex.fence(name);
1607  }
1608  }
1609 };
1610 
1611 } // namespace Impl
1612 
1651 // ReturnValue is scalar or array: take by reference
1652 
1653 template <class PolicyType, class FunctorType, class ReturnType>
1654 inline std::enable_if_t<Kokkos::is_execution_policy<PolicyType>::value &&
1655  !(Kokkos::is_view<ReturnType>::value ||
1656  Kokkos::is_reducer<ReturnType>::value ||
1657  std::is_pointer<ReturnType>::value)>
1658 parallel_reduce(const std::string& label, const PolicyType& policy,
1659  const FunctorType& functor, ReturnType& return_value) {
1660  static_assert(
1661  !std::is_const<ReturnType>::value,
1662  "A const reduction result type is only allowed for a View, pointer or "
1663  "reducer return type!");
1664 
1665  Impl::ParallelReduceAdaptor<PolicyType, FunctorType, ReturnType>::execute(
1666  label, policy, functor, return_value);
1667  Impl::ParallelReduceFence<typename PolicyType::execution_space, ReturnType>::
1668  fence(
1669  policy.space(),
1670  "Kokkos::parallel_reduce: fence due to result being value, not view",
1671  return_value);
1672 }
1673 
1674 template <class PolicyType, class FunctorType, class ReturnType>
1675 inline std::enable_if_t<Kokkos::is_execution_policy<PolicyType>::value &&
1676  !(Kokkos::is_view<ReturnType>::value ||
1677  Kokkos::is_reducer<ReturnType>::value ||
1678  std::is_pointer<ReturnType>::value)>
1679 parallel_reduce(const PolicyType& policy, const FunctorType& functor,
1680  ReturnType& return_value) {
1681  static_assert(
1682  !std::is_const<ReturnType>::value,
1683  "A const reduction result type is only allowed for a View, pointer or "
1684  "reducer return type!");
1685 
1686  Impl::ParallelReduceAdaptor<PolicyType, FunctorType, ReturnType>::execute(
1687  "", policy, functor, return_value);
1688  Impl::ParallelReduceFence<typename PolicyType::execution_space, ReturnType>::
1689  fence(
1690  policy.space(),
1691  "Kokkos::parallel_reduce: fence due to result being value, not view",
1692  return_value);
1693 }
1694 
1695 template <class FunctorType, class ReturnType>
1696 inline std::enable_if_t<!(Kokkos::is_view<ReturnType>::value ||
1697  Kokkos::is_reducer<ReturnType>::value ||
1698  std::is_pointer<ReturnType>::value)>
1699 parallel_reduce(const size_t& policy, const FunctorType& functor,
1700  ReturnType& return_value) {
1701  static_assert(
1702  !std::is_const<ReturnType>::value,
1703  "A const reduction result type is only allowed for a View, pointer or "
1704  "reducer return type!");
1705 
1706  using policy_type =
1707  typename Impl::ParallelReducePolicyType<void, size_t,
1708  FunctorType>::policy_type;
1709 
1710  Impl::ParallelReduceAdaptor<policy_type, FunctorType, ReturnType>::execute(
1711  "", policy_type(0, policy), functor, return_value);
1712  Impl::ParallelReduceFence<typename policy_type::execution_space, ReturnType>::
1713  fence(
1714  typename policy_type::execution_space(),
1715  "Kokkos::parallel_reduce: fence due to result being value, not view",
1716  return_value);
1717 }
1718 
1719 template <class FunctorType, class ReturnType>
1720 inline std::enable_if_t<!(Kokkos::is_view<ReturnType>::value ||
1721  Kokkos::is_reducer<ReturnType>::value ||
1722  std::is_pointer<ReturnType>::value)>
1723 parallel_reduce(const std::string& label, const size_t& policy,
1724  const FunctorType& functor, ReturnType& return_value) {
1725  static_assert(
1726  !std::is_const<ReturnType>::value,
1727  "A const reduction result type is only allowed for a View, pointer or "
1728  "reducer return type!");
1729 
1730  using policy_type =
1731  typename Impl::ParallelReducePolicyType<void, size_t,
1732  FunctorType>::policy_type;
1733  Impl::ParallelReduceAdaptor<policy_type, FunctorType, ReturnType>::execute(
1734  label, policy_type(0, policy), functor, return_value);
1735  Impl::ParallelReduceFence<typename policy_type::execution_space, ReturnType>::
1736  fence(
1737  typename policy_type::execution_space(),
1738  "Kokkos::parallel_reduce: fence due to result being value, not view",
1739  return_value);
1740 }
1741 
1742 // ReturnValue as View or Reducer: take by copy to allow for inline construction
1743 
1744 template <class PolicyType, class FunctorType, class ReturnType>
1745 inline std::enable_if_t<Kokkos::is_execution_policy<PolicyType>::value &&
1746  (Kokkos::is_view<ReturnType>::value ||
1747  Kokkos::is_reducer<ReturnType>::value ||
1748  std::is_pointer<ReturnType>::value)>
1749 parallel_reduce(const std::string& label, const PolicyType& policy,
1750  const FunctorType& functor, const ReturnType& return_value) {
1751  ReturnType return_value_impl = return_value;
1752  Impl::ParallelReduceAdaptor<PolicyType, FunctorType, ReturnType>::execute(
1753  label, policy, functor, return_value_impl);
1754  Impl::ParallelReduceFence<typename PolicyType::execution_space, ReturnType>::
1755  fence(
1756  policy.space(),
1757  "Kokkos::parallel_reduce: fence due to result being value, not view",
1758  return_value);
1759 }
1760 
1761 template <class PolicyType, class FunctorType, class ReturnType>
1762 inline std::enable_if_t<Kokkos::is_execution_policy<PolicyType>::value &&
1763  (Kokkos::is_view<ReturnType>::value ||
1764  Kokkos::is_reducer<ReturnType>::value ||
1765  std::is_pointer<ReturnType>::value)>
1766 parallel_reduce(const PolicyType& policy, const FunctorType& functor,
1767  const ReturnType& return_value) {
1768  ReturnType return_value_impl = return_value;
1769  Impl::ParallelReduceAdaptor<PolicyType, FunctorType, ReturnType>::execute(
1770  "", policy, functor, return_value_impl);
1771  Impl::ParallelReduceFence<typename PolicyType::execution_space, ReturnType>::
1772  fence(
1773  policy.space(),
1774  "Kokkos::parallel_reduce: fence due to result being value, not view",
1775  return_value);
1776 }
1777 
1778 template <class FunctorType, class ReturnType>
1779 inline std::enable_if_t<Kokkos::is_view<ReturnType>::value ||
1780  Kokkos::is_reducer<ReturnType>::value ||
1781  std::is_pointer<ReturnType>::value>
1782 parallel_reduce(const size_t& policy, const FunctorType& functor,
1783  const ReturnType& return_value) {
1784  using policy_type =
1785  typename Impl::ParallelReducePolicyType<void, size_t,
1786  FunctorType>::policy_type;
1787  ReturnType return_value_impl = return_value;
1788  Impl::ParallelReduceAdaptor<policy_type, FunctorType, ReturnType>::execute(
1789  "", policy_type(0, policy), functor, return_value_impl);
1790  Impl::ParallelReduceFence<typename policy_type::execution_space, ReturnType>::
1791  fence(
1792  typename policy_type::execution_space(),
1793  "Kokkos::parallel_reduce: fence due to result being value, not view",
1794  return_value);
1795 }
1796 
1797 template <class FunctorType, class ReturnType>
1798 inline std::enable_if_t<Kokkos::is_view<ReturnType>::value ||
1799  Kokkos::is_reducer<ReturnType>::value ||
1800  std::is_pointer<ReturnType>::value>
1801 parallel_reduce(const std::string& label, const size_t& policy,
1802  const FunctorType& functor, const ReturnType& return_value) {
1803  using policy_type =
1804  typename Impl::ParallelReducePolicyType<void, size_t,
1805  FunctorType>::policy_type;
1806  ReturnType return_value_impl = return_value;
1807  Impl::ParallelReduceAdaptor<policy_type, FunctorType, ReturnType>::execute(
1808  label, policy_type(0, policy), functor, return_value_impl);
1809  Impl::ParallelReduceFence<typename policy_type::execution_space, ReturnType>::
1810  fence(
1811  typename policy_type::execution_space(),
1812  "Kokkos::parallel_reduce: fence due to result being value, not view",
1813  return_value);
1814 }
1815 
1816 // No Return Argument
1817 
1818 template <class PolicyType, class FunctorType>
1819 inline void parallel_reduce(
1820  const std::string& label, const PolicyType& policy,
1821  const FunctorType& functor,
1822  std::enable_if_t<Kokkos::is_execution_policy<PolicyType>::value>* =
1823  nullptr) {
1824  using FunctorAnalysis =
1825  Impl::FunctorAnalysis<Impl::FunctorPatternInterface::REDUCE, PolicyType,
1826  FunctorType, void>;
1827  using value_type = std::conditional_t<(FunctorAnalysis::StaticValueSize != 0),
1828  typename FunctorAnalysis::value_type,
1829  typename FunctorAnalysis::pointer_type>;
1830 
1831  static_assert(
1832  FunctorAnalysis::has_final_member_function,
1833  "Calling parallel_reduce without either return value or final function.");
1834 
1835  using result_view_type =
1837  result_view_type result_view;
1838 
1839  Impl::ParallelReduceAdaptor<PolicyType, FunctorType,
1840  result_view_type>::execute(label, policy, functor,
1841  result_view);
1842 }
1843 
1844 template <class PolicyType, class FunctorType>
1845 inline void parallel_reduce(
1846  const PolicyType& policy, const FunctorType& functor,
1847  std::enable_if_t<Kokkos::is_execution_policy<PolicyType>::value>* =
1848  nullptr) {
1849  using FunctorAnalysis =
1850  Impl::FunctorAnalysis<Impl::FunctorPatternInterface::REDUCE, PolicyType,
1851  FunctorType, void>;
1852  using value_type = std::conditional_t<(FunctorAnalysis::StaticValueSize != 0),
1853  typename FunctorAnalysis::value_type,
1854  typename FunctorAnalysis::pointer_type>;
1855 
1856  static_assert(
1857  FunctorAnalysis::has_final_member_function,
1858  "Calling parallel_reduce without either return value or final function.");
1859 
1860  using result_view_type =
1862  result_view_type result_view;
1863 
1864  Impl::ParallelReduceAdaptor<PolicyType, FunctorType,
1865  result_view_type>::execute("", policy, functor,
1866  result_view);
1867 }
1868 
1869 template <class FunctorType>
1870 inline void parallel_reduce(const size_t& policy, const FunctorType& functor) {
1871  using policy_type =
1872  typename Impl::ParallelReducePolicyType<void, size_t,
1873  FunctorType>::policy_type;
1874  using FunctorAnalysis =
1875  Impl::FunctorAnalysis<Impl::FunctorPatternInterface::REDUCE, policy_type,
1876  FunctorType, void>;
1877  using value_type = std::conditional_t<(FunctorAnalysis::StaticValueSize != 0),
1878  typename FunctorAnalysis::value_type,
1879  typename FunctorAnalysis::pointer_type>;
1880 
1881  static_assert(
1882  FunctorAnalysis::has_final_member_function,
1883  "Calling parallel_reduce without either return value or final function.");
1884 
1885  using result_view_type =
1887  result_view_type result_view;
1888 
1889  Impl::ParallelReduceAdaptor<policy_type, FunctorType,
1890  result_view_type>::execute("",
1891  policy_type(0, policy),
1892  functor, result_view);
1893 }
1894 
1895 template <class FunctorType>
1896 inline void parallel_reduce(const std::string& label, const size_t& policy,
1897  const FunctorType& functor) {
1898  using policy_type =
1899  typename Impl::ParallelReducePolicyType<void, size_t,
1900  FunctorType>::policy_type;
1901  using FunctorAnalysis =
1902  Impl::FunctorAnalysis<Impl::FunctorPatternInterface::REDUCE, policy_type,
1903  FunctorType, void>;
1904  using value_type = std::conditional_t<(FunctorAnalysis::StaticValueSize != 0),
1905  typename FunctorAnalysis::value_type,
1906  typename FunctorAnalysis::pointer_type>;
1907 
1908  static_assert(
1909  FunctorAnalysis::has_final_member_function,
1910  "Calling parallel_reduce without either return value or final function.");
1911 
1912  using result_view_type =
1914  result_view_type result_view;
1915 
1916  Impl::ParallelReduceAdaptor<policy_type, FunctorType,
1917  result_view_type>::execute(label,
1918  policy_type(0, policy),
1919  functor, result_view);
1920 }
1921 
1922 } // namespace Kokkos
1923 
1924 #endif // KOKKOS_PARALLEL_REDUCE_HPP
Memory management for host memory.
ReturnType
Execution policy for work over a range of an integral type.