Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_Util.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Tpetra: Templated Linear Algebra Services Package
4//
5// Copyright 2008 NTESS and the Tpetra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef TPETRA_UTIL_HPP
11#define TPETRA_UTIL_HPP
12
21
22#include "Tpetra_ConfigDefs.hpp"
23#include "Kokkos_DualView.hpp"
24#include "KokkosCompat_View.hpp"
25#include "Teuchos_Assert.hpp"
26#include "Teuchos_CommHelpers.hpp"
27#include "Teuchos_OrdinalTraits.hpp"
28#include "Teuchos_TypeNameTraits.hpp"
29#include "Teuchos_Utils.hpp"
30#include <numeric>
31#include <algorithm>
32#include <iterator>
33#include <memory>
34#include <ostream>
35#include <sstream>
36
37#if defined(HAVE_TPETRA_PRINT_EFFICIENCY_WARNINGS)
62#define TPETRA_EFFICIENCY_WARNING(throw_exception_test,msg) \
63{ \
64 const bool tpetraEfficiencyWarningTest = (throw_exception_test); \
65 if (tpetraEfficiencyWarningTest) { \
66 std::ostringstream errStream; \
67 errStream << Teuchos::typeName(*this) << ":" << std::endl; \
68 errStream << "Efficiency warning: " << #throw_exception_test << std::endl; \
69 errStream << msg; \
70 std::string err = errStream.str(); \
71 if (TPETRA_PRINTS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest) { \
72 std::cerr << err << std::endl; \
73 } \
74 } \
75}
76#else
101#define TPETRA_EFFICIENCY_WARNING(throw_exception_test,msg)
102#endif
103
104// handle an abuse warning, according to HAVE_TPETRA_THROW_ABUSE_WARNINGS and HAVE_TPETRA_PRINT_ABUSE_WARNINGS
105#if defined(HAVE_TPETRA_THROW_ABUSE_WARNINGS) || defined(HAVE_TPETRA_PRINT_ABUSE_WARNINGS)
107#define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg) \
108{ \
109 std::ostringstream errStream; \
110 errStream << Teuchos::typeName(*this) << msg; \
111 std::string err = errStream.str(); \
112 if (TPETRA_PRINTS_ABUSE_WARNINGS && (throw_exception_test)) { \
113 std::cerr << err << std::endl; \
114 } \
115 TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_ABUSE_WARNINGS && (throw_exception_test), Exception, err); \
116}
117#else
119#define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg)
120#endif
121
151#define SHARED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
152{ \
153 using Teuchos::outArg; \
154 const int lcl_throw_exception = (throw_exception_test) ? Teuchos::rank(comm)+1 : 0; \
155 int gbl_throw; \
156 Teuchos::reduceAll(comm,Teuchos::REDUCE_MAX,lcl_throw_exception,outArg(gbl_throw)); \
157 TEUCHOS_TEST_FOR_EXCEPTION(gbl_throw,Exception, \
158 msg << " Failure on at least one process, including process " << gbl_throw-1 << "." << std::endl); \
159}
160
161namespace Tpetra {
162
174 template<typename MapType, typename KeyArgType, typename ValueArgType>
175 typename MapType::iterator efficientAddOrUpdate(MapType& m,
176 const KeyArgType & k,
177 const ValueArgType & v)
178 {
179 typename MapType::iterator lb = m.lower_bound(k);
180 if(lb != m.end() && !(m.key_comp()(k, lb->first))) {
181 lb->second = v;
182 return(lb);
183 }
184 else {
185 typedef typename MapType::value_type MVT;
186 return(m.insert(lb, MVT(k, v)));
187 }
188 }
189
197 namespace SortDetails {
198
207 template<class IT1>
208 bool isAlreadySorted(const IT1& first, const IT1& last){
209 typedef typename std::iterator_traits<IT1>::difference_type DT;
210 DT myit = Teuchos::OrdinalTraits<DT>::one();
211 const DT sz = last - first;
212 for(;myit < sz; ++myit){
213 if(first[myit] < first[myit-1]){
214 return false;
215 }
216 }
217 return true;
218 }
219
229 template<class IT>
230 IT getPivot(const IT& first, const IT& last){
231 IT pivot(first+(last-first)/2);
232 if(*first<=*pivot && *(last-1)<=*first) pivot=first;
233 else if(*(last-1)<=*pivot && *first<= *(last-1)) pivot = last-1;
234 return pivot;
235 }
236
251 template<class IT1, class IT2>
253 const IT1& first1,
254 const IT1& last1,
255 const IT2& first2,
256 const IT2& last2,
257 const IT1& pivot)
258 {
259 typename std::iterator_traits<IT1>::value_type piv(*pivot);
260 std::swap(*pivot, *(last1-1));
261 std::swap(first2[(pivot-first1)], *(last2-1));
262 IT1 store1=first1;
263 for(IT1 it=first1; it!=last1-1; ++it){
264 if(*it<=piv){
265 std::swap(*store1, *it);
266 std::swap(first2[(store1-first1)], first2[(it-first1)]);
267 ++store1;
268 }
269 }
270 std::swap(*(last1-1), *store1);
271 std::swap(*(last2-1), first2[store1-first1]);
272 return store1;
273 }
274
291 template<class IT1, class IT2, class IT3>
293 const IT1& first1,
294 const IT1& last1,
295 const IT2& first2,
296 const IT2& last2,
297 const IT3& first3,
298 const IT3& last3,
299 const IT1& pivot)
300 {
301 typename std::iterator_traits<IT1>::value_type piv(*pivot);
302 std::swap(*pivot, *(last1-1));
303 std::swap(first2[(pivot-first1)], *(last2-1));
304 std::swap(first3[(pivot-first1)], *(last3-1));
305 IT1 store1=first1;
306 for(IT1 it=first1; it!=last1-1; ++it){
307 if(*it<=piv){
308 std::swap(*store1, *it);
309 std::swap(first2[(store1-first1)], first2[(it-first1)]);
310 std::swap(first3[(store1-first1)], first3[(it-first1)]);
311 ++store1;
312 }
313 }
314 std::swap(*(last1-1), *store1);
315 std::swap(*(last2-1), first2[store1-first1]);
316 std::swap(*(last3-1), first3[store1-first1]);
317 return store1;
318 }
319
330 template<class IT1, class IT2>
332 const IT1& first1,
333 const IT1& last1,
334 const IT2& first2,
335 const IT2& last2)
336 {
337 typedef typename std::iterator_traits<IT1>::difference_type DT;
338 DT DT1 = Teuchos::OrdinalTraits<DT>::one();
339 if(last1-first1 > DT1){
340 IT1 pivot = getPivot(first1, last1);
341 pivot = partition2(first1, last1, first2, last2, pivot);
342 quicksort2(first1, pivot, first2, first2+(pivot-first1));
343 quicksort2(pivot+1, last1, first2+(pivot-first1)+1, last2);
344 }
345 }
346
359 template<class IT1, class IT2, class IT3>
361 const IT1& first1,
362 const IT1& last1,
363 const IT2& first2,
364 const IT2& last2,
365 const IT3& first3,
366 const IT3& last3)
367 {
368 typedef typename std::iterator_traits<IT1>::difference_type DT;
369 DT DT1 = Teuchos::OrdinalTraits<DT>::one();
370 if(last1-first1 > DT1){
371 IT1 pivot = getPivot(first1, last1);
372 pivot = partition3(first1, last1, first2, last2, first3, last3, pivot);
373 quicksort3(first1, pivot, first2, first2+(pivot-first1), first3, first3+(pivot-first1));
374 quicksort3(pivot+1, last1, first2+(pivot-first1)+1, last2, first3+(pivot-first1)+1, last3);
375 }
376 }
377
384 template<class IT1, class IT2, class IT3>
386 const IT1& first1,
387 const IT1& last1,
388 const IT2& first2,
389 const IT2& /* last2 */,
390 const IT3& first3,
391 const IT3& /* last3 */)
392 {
393 typedef typename std::iterator_traits<IT1>::difference_type DT;
394 DT n = last1 - first1;
395 DT m = n / 2;
396 DT z = Teuchos::OrdinalTraits<DT>::zero();
397 while (m > z)
398 {
399 DT max = n - m;
400 for (DT j = 0; j < max; j++)
401 {
402 for (DT k = j; k >= 0; k-=m)
403 {
404 if (first1[k+m] >= first1[k])
405 break;
406 std::swap(first1[k+m], first1[k]);
407 std::swap(first2[k+m], first2[k]);
408 std::swap(first3[k+m], first3[k]);
409 }
410 }
411 m = m/2;
412 }
413 }
414
421 template<class IT1, class IT2>
423 const IT1& first1,
424 const IT1& last1,
425 const IT2& first2,
426 const IT2& /* last2 */)
427 {
428 typedef typename std::iterator_traits<IT1>::difference_type DT;
429 DT n = last1 - first1;
430 DT m = n / 2;
431 DT z = Teuchos::OrdinalTraits<DT>::zero();
432 while (m > z)
433 {
434 DT max = n - m;
435 for (DT j = 0; j < max; j++)
436 {
437 for (DT k = j; k >= 0; k-=m)
438 {
439 if (first1[k+m] >= first1[k])
440 break;
441 std::swap(first1[k+m], first1[k]);
442 std::swap(first2[k+m], first2[k]);
443 }
444 }
445 m = m/2;
446 }
447 }
448
453 template<typename IT1>
454 std::vector<typename std::iterator_traits<IT1>::difference_type> sort_indexes(IT1 first, IT1 last) {
455
456 typedef typename std::iterator_traits<IT1>::difference_type DT;
457
458 DT length = last - first;
459 std::vector<DT> idx(length);
460 std::iota(idx.begin(), idx.end(), 0);
461
462 std::stable_sort(idx.begin(), idx.end(),
463 [&first](size_t i1, size_t i2) {return first[i1] < first[i2];});
464
465 return idx;
466 }
467
471 template<typename IT1, typename IT2>
472 void
474 IT1 first,
475 IT1 last,
476 IT2 indices)
477 {
478 typedef typename std::iterator_traits<IT1>::difference_type DT;
479 typedef typename std::iterator_traits<IT1>::value_type T;
480
481 DT n = last - first;
482
483 Kokkos::View<T*, Kokkos::HostSpace> tmp(Kokkos::view_alloc(Kokkos::WithoutInitializing, "tmp"), n);
484
485 Kokkos::parallel_for("apply_permutation_1",
486 Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(0, n),
487 [=](const int j) {
488 tmp(j) = first[indices[j]];
489 });
490 Kokkos::parallel_for("apply_permutation_2",
491 Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(0, n),
492 [=](const int j) {
493 first[j] = tmp(j);
494 });
495 }
496
503 template<class IT1, class IT2>
504 void std_sort2(const IT1& first1,
505 const IT1& last1,
506 const IT2& first2,
507 const IT2& last2)
508 {
509 auto indices = sort_indexes(first1, last1);
510 apply_permutation(first1, last1, indices);
511 apply_permutation(first2, last2, indices);
512 }
513
520 template<class IT1, class IT2, class IT3>
522 const IT1& first1,
523 const IT1& last1,
524 const IT2& first2,
525 const IT2& last2,
526 const IT3& first3,
527 const IT3& last3)
528 {
529 auto indices = sort_indexes(first1, last1);
530 apply_permutation(first1, last1, indices);
531 apply_permutation(first2, last2, indices);
532 apply_permutation(first3, last3, indices);
533 }
534
535 } //end namespace SortDetails
536
537
556 template<class IT1, class IT2>
557 void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const bool stableSort=false) {
558 // Quicksort uses best-case N log N time whether or not the input
559 // data is sorted. However, the common case in Tpetra is that the
560 // input data are sorted, so we first check whether this is the
561 // case before reverting to Quicksort.
562 if(SortDetails::isAlreadySorted(first1, last1)){
563 return;
564 }
565 if(stableSort)
566 SortDetails::std_sort2(first1, last1, first2, first2+(last1-first1));
567 else
568 SortDetails::sh_sort2(first1, last1, first2, first2+(last1-first1));
569#ifdef HAVE_TPETRA_DEBUG
570 if(!SortDetails::isAlreadySorted(first1, last1)){
571 std::cout << "Trouble: sort() did not sort !!" << std::endl;
572 return;
573 }
574#endif
575 }
576
577
594 template<class View1, class View2>
595 void sort2(View1 &view1, const size_t &size, View2 &view2) {
596 // NOTE: This assumes the view is host-accessible.
597
598 // Wrap the views as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
599 Teuchos::ArrayRCP<typename View1::non_const_value_type> view1_rcp = Kokkos::Compat::persistingView(view1, 0, size);
600 Teuchos::ArrayRCP<typename View2::non_const_value_type> view2_rcp = Kokkos::Compat::persistingView(view2, 0, size);
601
602 sort2(view1_rcp.begin(),view1_rcp.end(),view2_rcp.begin());
603 }
604
613 template<class View>
614 void sort(View &view, const size_t &size) {
615 // NOTE: This assumes the view is host-accessible.
616
617 // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
618 Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
619
620 std::sort(view_rcp.begin(),view_rcp.end());
621 }
622
631 template<class View>
632 void reverse_sort(View &view, const size_t &size) {
633 // NOTE: This assumes the view is host-accessible.
634 // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
635 Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
636
637 std::sort(view_rcp.rbegin(),view_rcp.rend());
638 }
639
640
641
642
658 template<class IT1, class IT2, class IT3>
659 void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2,
660 const IT3 &first3, const bool stableSort=false)
661 {
662 // Quicksort uses best-case N log N time whether or not the input
663 // data is sorted. However, the common case in Tpetra is that the
664 // input data are sorted, so we first check whether this is the
665 // case before reverting to Quicksort.
666 if(SortDetails::isAlreadySorted(first1, last1)){
667 return;
668 }
669 if(stableSort)
670 SortDetails::std_sort3(first1, last1, first2, first2+(last1-first1), first3,
671 first3+(last1-first1));
672 else
673 SortDetails::sh_sort3(first1, last1, first2, first2+(last1-first1), first3,
674 first3+(last1-first1));
675#ifdef HAVE_TPETRA_DEBUG
676 if(!SortDetails::isAlreadySorted(first1, last1)){
677 std::cout << " Trouble sort did not actually sort... !!!!!!" <<
678 std::endl;
679 return;
680 }
681#endif
682 }
683
727 template<class IT1, class IT2>
728 void
729 merge2 (IT1& indResultOut, IT2& valResultOut,
730 IT1 indBeg, IT1 indEnd,
731 IT2 valBeg, IT2 /* valEnd */)
732 {
733 if (indBeg == indEnd) {
734 indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
735 valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
736 }
737 else {
738 IT1 indResult = indBeg;
739 IT2 valResult = valBeg;
740 if (indBeg != indEnd) {
741 ++indBeg;
742 ++valBeg;
743 while (indBeg != indEnd) {
744 if (*indResult == *indBeg) { // adjacent column indices equal
745 *valResult += *valBeg; // merge entries by adding their values together
746 } else { // adjacent column indices not equal
747 *(++indResult) = *indBeg; // shift over the index
748 *(++valResult) = *valBeg; // shift over the value
749 }
750 ++indBeg;
751 ++valBeg;
752 }
753 ++indResult; // exclusive end of merged result
754 ++valResult; // exclusive end of merged result
755
756 // mfh 24 Feb 2014: Setting these is technically correct, but
757 // since the resulting variables aren't used after this point,
758 // it may result in a build error.
759 //
760 // indEnd = indResult;
761 // valEnd = valResult;
762 }
763 indResultOut = indResult;
764 valResultOut = valResult;
765 }
766 }
767
816 template<class IT1, class IT2, class BinaryFunction>
817 void
818 merge2 (IT1& indResultOut, IT2& valResultOut,
819 IT1 indBeg, IT1 indEnd,
820 IT2 valBeg, IT2 valEnd,
821 BinaryFunction f)
822 {
823 if (indBeg == indEnd) {
824 indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
825 valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
826 }
827 else {
828 IT1 indResult = indBeg;
829 IT2 valResult = valBeg;
830 if (indBeg != indEnd) {
831 ++indBeg;
832 ++valBeg;
833 while (indBeg != indEnd) {
834 if (*indResult == *indBeg) { // adjacent column indices equal
835 *valResult = f (*valResult, *valBeg); // merge entries via values
836 } else { // adjacent column indices not equal
837 *(++indResult) = *indBeg; // shift over the index
838 *(++valResult) = *valBeg; // shift over the value
839 }
840 ++indBeg;
841 ++valBeg;
842 }
843 ++indResult; // exclusive end of merged result
844 ++valResult; // exclusive end of merged result
845 indEnd = indResult;
846 valEnd = valResult;
847 }
848 indResultOut = indResult;
849 valResultOut = valResult;
850 }
851 }
852
853
882 template<class KeyInputIterType, class ValueInputIterType,
883 class KeyOutputIterType, class ValueOutputIterType,
884 class BinaryFunction>
885 void
886 keyValueMerge (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
887 ValueInputIterType valBeg1, ValueInputIterType valEnd1,
888 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2,
889 ValueInputIterType valBeg2, ValueInputIterType valEnd2,
890 KeyOutputIterType keyOut, ValueOutputIterType valOut,
891 BinaryFunction f)
892 {
893 while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
894 if (*keyBeg1 < *keyBeg2) {
895 *keyOut++ = *keyBeg1++;
896 *valOut++ = *valBeg1++;
897 } else if (*keyBeg1 > *keyBeg2) {
898 *keyOut++ = *keyBeg2++;
899 *valOut++ = *valBeg2++;
900 } else { // *keyBeg1 == *keyBeg2
901 *keyOut++ = *keyBeg1;
902 *valOut++ = f (*valBeg1, *valBeg2);
903 ++keyBeg1;
904 ++valBeg1;
905 ++keyBeg2;
906 ++valBeg2;
907 }
908 }
909 // At most one of the two sequences will be nonempty.
910 std::copy (keyBeg1, keyEnd1, keyOut);
911 std::copy (valBeg1, valEnd1, valOut);
912 std::copy (keyBeg2, keyEnd2, keyOut);
913 std::copy (valBeg2, valEnd2, valOut);
914 }
915
916 template<class KeyInputIterType>
917 size_t
918 keyMergeCount (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
919 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2)
920 {
921 size_t count = 0;
922 while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
923 if (*keyBeg1 < *keyBeg2) {
924 ++keyBeg1;
925 } else if (*keyBeg1 > *keyBeg2) {
926 ++keyBeg2;
927 } else { // *keyBeg1 == *keyBeg2
928 ++keyBeg1;
929 ++keyBeg2;
930 }
931 ++count;
932 }
933 // At most one of the two sequences will be nonempty.
934 count += static_cast<size_t> (keyEnd1 - keyBeg1) +
935 static_cast<size_t> (keyEnd2 - keyBeg2);
936 return count;
937 }
938
939 namespace Details {
959 bool
960 congruent (const Teuchos::Comm<int>& comm1,
961 const Teuchos::Comm<int>& comm2);
962
972 template<class DualViewType>
973 Teuchos::ArrayView<typename DualViewType::t_dev::value_type>
974 getArrayViewFromDualView (const DualViewType& x)
975 {
976 static_assert (static_cast<int> (DualViewType::t_dev::rank) == 1,
977 "The input DualView must have rank 1.");
978 TEUCHOS_TEST_FOR_EXCEPTION
979 (x.need_sync_host (), std::logic_error, "The "
980 "input Kokkos::DualView was most recently modified on device, but this "
981 "function needs the host view of the data to be the most recently "
982 "modified.");
983
984 auto x_host = x.view_host ();
985 typedef typename DualViewType::t_dev::value_type value_type;
986 // mfh 15 Jan 2019: In debug mode, Teuchos::ArrayView's
987 // constructor throws if the pointer is nonnull but the length
988 // is nonpositive.
989 const auto len = x_host.extent (0);
990 return Teuchos::ArrayView<value_type> (len != 0 ? x_host.data () : nullptr,
991 len);
992 }
993
1010 template<class T, class DT>
1011 Kokkos::DualView<T*, DT>
1012 getDualViewCopyFromArrayView (const Teuchos::ArrayView<const T>& x_av,
1013 const char label[],
1014 const bool leaveOnHost)
1015 {
1016 using Kokkos::MemoryUnmanaged;
1017 typedef typename DT::memory_space DMS;
1018 typedef typename DT::execution_space execution_space;
1019 typedef Kokkos::HostSpace HMS;
1020
1021 const size_t len = static_cast<size_t> (x_av.size ());
1022 Kokkos::View<const T*, HMS, MemoryUnmanaged> x_in (x_av.getRawPtr (), len);
1023 Kokkos::DualView<T*, DT> x_out (label, len);
1024 if (leaveOnHost) {
1025 x_out.modify_host ();
1026 // DEEP_COPY REVIEW - NOT TESTED FOR CUDA BUILD
1027 Kokkos::deep_copy (x_out.view_host (), x_in);
1028 }
1029 else {
1030 x_out.template modify<DMS> ();
1031 // DEEP_COPY REVIEW - HOST-TO-DEVICE
1032 Kokkos::deep_copy (execution_space(), x_out.template view<DMS> (), x_in);
1033 }
1034 return x_out;
1035 }
1036
1044 template<class DualViewType>
1045 std::string dualViewStatusToString (const DualViewType& dv, const char name[])
1046 {
1047 const auto host = dv.need_sync_device();
1048 const auto dev = dv.need_sync_host();
1049
1050 std::ostringstream os;
1051 os << name << ": {size: " << dv.extent (0)
1052 << ", sync: {host: " << host << ", dev: " << dev << "}";
1053 return os.str ();
1054 }
1055
1060 template<class ArrayType>
1061 void
1062 verbosePrintArray(std::ostream& out,
1063 const ArrayType& x,
1064 const char name[],
1065 const size_t maxNumToPrint)
1066 {
1067 out << name << ": [";
1068
1069 const size_t numEnt(x.size());
1070 if (maxNumToPrint == 0) {
1071 if (numEnt != 0) {
1072 out << "...";
1073 }
1074 }
1075 else {
1076 const size_t numToPrint = numEnt > maxNumToPrint ?
1077 maxNumToPrint : numEnt;
1078 size_t k = 0;
1079 for ( ; k < numToPrint; ++k) {
1080 out << x[k];
1081 if (k + size_t(1) < numToPrint) {
1082 out << ", ";
1083 }
1084 }
1085 if (k < numEnt) {
1086 out << ", ...";
1087 }
1088 }
1089 out << "]";
1090 }
1091
1095 std::unique_ptr<std::string>
1096 createPrefix(const int myRank,
1097 const char prefix[]);
1098
1106 std::unique_ptr<std::string>
1107 createPrefix(const Teuchos::Comm<int>* comm,
1108 const char functionName[]);
1109
1116 std::unique_ptr<std::string>
1117 createPrefix(const Teuchos::Comm<int>*,
1118 const char className[],
1119 const char methodName[]);
1120
1121 } // namespace Details
1122} // namespace Tpetra
1123
1124#endif // TPETRA_UTIL_HPP
void std_sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT2 &last2, const IT3 &first3, const IT3 &last3)
Sort the first array using std sort, and apply the resulting permutation to the second and third arra...
void sh_sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT2 &, const IT3 &first3, const IT3 &)
Sort the first array using shell sort, and apply the resulting permutation to the second and third ar...
void std_sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT2 &last2)
Sort the first array using std sort, and apply the resulting permutation to the second array.
IT1 partition2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT2 &last2, const IT1 &pivot)
Partition operation for quicksort2().
void quicksort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT2 &last2)
Sort the first array using Quicksort, and apply the resulting permutation to the second array.
void apply_permutation(IT1 first, IT1 last, IT2 indices)
Apply a permutation of the ordering of an array in place.
IT getPivot(const IT &first, const IT &last)
Determines the pivot point as part of the quicksort routine.
std::vector< typename std::iterator_traits< IT1 >::difference_type > sort_indexes(IT1 first, IT1 last)
Compute the permutation of the ordering that sorts the array using a stable sort.
IT1 partition3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT2 &last2, const IT3 &first3, const IT3 &last3, const IT1 &pivot)
Partition operation for quicksort3().
void sh_sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT2 &)
Sort the first array using shell sort, and apply the resulting permutation to the second array.
bool isAlreadySorted(const IT1 &first, const IT1 &last)
Determines whether or not a random access sequence is already sorted.
void quicksort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT2 &last2, const IT3 &first3, const IT3 &last3)
Sort the first array using Quicksort, and apply the resulting permutation to the second and third arr...
Implementation details of sort routines used by Tpetra.
Nonmember function that computes a residual Computes R = B - A * X.
void verbosePrintArray(std::ostream &out, const ArrayType &x, const char name[], const size_t maxNumToPrint)
Print min(x.size(), maxNumToPrint) entries of x.
Teuchos::ArrayView< typename DualViewType::t_dev::value_type > getArrayViewFromDualView(const DualViewType &x)
Get a Teuchos::ArrayView which views the host Kokkos::View of the input 1-D Kokkos::DualView.
std::unique_ptr< std::string > createPrefix(const int myRank, const char prefix[])
Create string prefix for each line of verbose output.
bool congruent(const Teuchos::Comm< int > &comm1, const Teuchos::Comm< int > &comm2)
Whether the two communicators are congruent.
Kokkos::DualView< T *, DT > getDualViewCopyFromArrayView(const Teuchos::ArrayView< const T > &x_av, const char label[], const bool leaveOnHost)
Get a 1-D Kokkos::DualView which is a deep copy of the input Teuchos::ArrayView (which views host mem...
std::string dualViewStatusToString(const DualViewType &dv, const char name[])
Return the status of the given Kokkos::DualView, as a human-readable string.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void sort(View &view, const size_t &size)
Convenience wrapper for std::sort for host-accessible views.
void reverse_sort(View &view, const size_t &size)
Convenience wrapper for a reversed std::sort for host-accessible views.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const bool stableSort=false)
Sort the first array, and apply the resulting permutation to the second array.
MapType::iterator efficientAddOrUpdate(MapType &m, const KeyArgType &k, const ValueArgType &v)
Efficiently insert or replace an entry in an std::map.
void merge2(IT1 &indResultOut, IT2 &valResultOut, IT1 indBeg, IT1 indEnd, IT2 valBeg, IT2)
Merge values in place, additively, with the same index.
void keyValueMerge(KeyInputIterType keyBeg1, KeyInputIterType keyEnd1, ValueInputIterType valBeg1, ValueInputIterType valEnd1, KeyInputIterType keyBeg2, KeyInputIterType keyEnd2, ValueInputIterType valBeg2, ValueInputIterType valEnd2, KeyOutputIterType keyOut, ValueOutputIterType valOut, BinaryFunction f)
Merge two sorted (by keys) sequences of unique (key,value) pairs by combining pairs with equal keys.
void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT3 &first3, const bool stableSort=false)
Sort the first array, and apply the same permutation to the second and third arrays.