Tpetra parallel linear algebra Version of the Day
Tpetra_Util.hpp
Go to the documentation of this file.
1// @HEADER
2// ***********************************************************************
3//
4// Tpetra: Templated Linear Algebra Services Package
5// Copyright (2008) Sandia Corporation
6//
7// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8// the U.S. Government retains certain rights in this software.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// ************************************************************************
38// @HEADER
39
40#ifndef TPETRA_UTIL_HPP
41#define TPETRA_UTIL_HPP
42
52#include "Tpetra_ConfigDefs.hpp"
53#include "Kokkos_DualView.hpp"
54#include "KokkosCompat_View.hpp"
55#include "Teuchos_Assert.hpp"
56#include "Teuchos_CommHelpers.hpp"
57#include "Teuchos_OrdinalTraits.hpp"
58#include "Teuchos_TypeNameTraits.hpp"
59#include "Teuchos_Utils.hpp"
60#include <algorithm>
61#include <iterator>
62#include <memory>
63#include <ostream>
64#include <sstream>
65
66#if defined(HAVE_TPETRA_THROW_EFFICIENCY_WARNINGS) || defined(HAVE_TPETRA_PRINT_EFFICIENCY_WARNINGS)
100#define TPETRA_EFFICIENCY_WARNING(throw_exception_test,Exception,msg) \
101{ \
102 const bool tpetraEfficiencyWarningTest = (throw_exception_test); \
103 if (tpetraEfficiencyWarningTest) { \
104 std::ostringstream errStream; \
105 errStream << Teuchos::typeName(*this) << ":" << std::endl; \
106 errStream << "Efficiency warning: " << #throw_exception_test << std::endl; \
107 errStream << msg; \
108 std::string err = errStream.str(); \
109 if (TPETRA_PRINTS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest) { \
110 std::cerr << err << std::endl; \
111 } \
112 TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest, Exception, err); \
113 } \
114}
115#else
149#define TPETRA_EFFICIENCY_WARNING(throw_exception_test,Exception,msg)
150#endif
151
152// handle an abuse warning, according to HAVE_TPETRA_THROW_ABUSE_WARNINGS and HAVE_TPETRA_PRINT_ABUSE_WARNINGS
153#if defined(HAVE_TPETRA_THROW_ABUSE_WARNINGS) || defined(HAVE_TPETRA_PRINT_ABUSE_WARNINGS)
155#define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg) \
156{ \
157 std::ostringstream errStream; \
158 errStream << Teuchos::typeName(*this) << msg; \
159 std::string err = errStream.str(); \
160 if (TPETRA_PRINTS_ABUSE_WARNINGS && (throw_exception_test)) { \
161 std::cerr << err << std::endl; \
162 } \
163 TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_ABUSE_WARNINGS && (throw_exception_test), Exception, err); \
164}
165#else
167#define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg)
168#endif
169
199#define SHARED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
200{ \
201 using Teuchos::outArg; \
202 const int lcl_throw_exception = (throw_exception_test) ? Teuchos::rank(comm)+1 : 0; \
203 int gbl_throw; \
204 Teuchos::reduceAll(comm,Teuchos::REDUCE_MAX,lcl_throw_exception,outArg(gbl_throw)); \
205 TEUCHOS_TEST_FOR_EXCEPTION(gbl_throw,Exception, \
206 msg << " Failure on at least one process, including process " << gbl_throw-1 << "." << std::endl); \
207}
208
209#ifdef HAVE_TEUCHOS_DEBUG
211#define SWITCHED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
212{ \
213 SHARED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm); \
214}
215#else
217#define SWITCHED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
218{ \
219 TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg); \
220}
221#endif
222
223namespace Tpetra {
224
236 template<typename MapType, typename KeyArgType, typename ValueArgType>
237 typename MapType::iterator efficientAddOrUpdate(MapType& m,
238 const KeyArgType & k,
239 const ValueArgType & v)
240 {
241 typename MapType::iterator lb = m.lower_bound(k);
242 if(lb != m.end() && !(m.key_comp()(k, lb->first))) {
243 lb->second = v;
244 return(lb);
245 }
246 else {
247 typedef typename MapType::value_type MVT;
248 return(m.insert(lb, MVT(k, v)));
249 }
250 }
251
259 namespace SortDetails {
260
269 template<class IT1>
270 bool isAlreadySorted(const IT1& first, const IT1& last){
271 typedef typename std::iterator_traits<IT1>::difference_type DT;
272 DT myit = Teuchos::OrdinalTraits<DT>::one();
273 const DT sz = last - first;
274 for(;myit < sz; ++myit){
275 if(first[myit] < first[myit-1]){
276 return false;
277 }
278 }
279 return true;
280 }
281
291 template<class IT>
292 IT getPivot(const IT& first, const IT& last){
293 IT pivot(first+(last-first)/2);
294 if(*first<=*pivot && *(last-1)<=*first) pivot=first;
295 else if(*(last-1)<=*pivot && *first<= *(last-1)) pivot = last-1;
296 return pivot;
297 }
298
313 template<class IT1, class IT2>
315 const IT1& first1,
316 const IT1& last1,
317 const IT2& first2,
318 const IT2& last2,
319 const IT1& pivot)
320 {
321 typename std::iterator_traits<IT1>::value_type piv(*pivot);
322 std::swap(*pivot, *(last1-1));
323 std::swap(first2[(pivot-first1)], *(last2-1));
324 IT1 store1=first1;
325 for(IT1 it=first1; it!=last1-1; ++it){
326 if(*it<=piv){
327 std::swap(*store1, *it);
328 std::swap(first2[(store1-first1)], first2[(it-first1)]);
329 ++store1;
330 }
331 }
332 std::swap(*(last1-1), *store1);
333 std::swap(*(last2-1), first2[store1-first1]);
334 return store1;
335 }
336
353 template<class IT1, class IT2, class IT3>
355 const IT1& first1,
356 const IT1& last1,
357 const IT2& first2,
358 const IT2& last2,
359 const IT3& first3,
360 const IT3& last3,
361 const IT1& pivot)
362 {
363 typename std::iterator_traits<IT1>::value_type piv(*pivot);
364 std::swap(*pivot, *(last1-1));
365 std::swap(first2[(pivot-first1)], *(last2-1));
366 std::swap(first3[(pivot-first1)], *(last3-1));
367 IT1 store1=first1;
368 for(IT1 it=first1; it!=last1-1; ++it){
369 if(*it<=piv){
370 std::swap(*store1, *it);
371 std::swap(first2[(store1-first1)], first2[(it-first1)]);
372 std::swap(first3[(store1-first1)], first3[(it-first1)]);
373 ++store1;
374 }
375 }
376 std::swap(*(last1-1), *store1);
377 std::swap(*(last2-1), first2[store1-first1]);
378 std::swap(*(last3-1), first3[store1-first1]);
379 return store1;
380 }
381
392 template<class IT1, class IT2>
394 const IT1& first1,
395 const IT1& last1,
396 const IT2& first2,
397 const IT2& last2)
398 {
399 typedef typename std::iterator_traits<IT1>::difference_type DT;
400 DT DT1 = Teuchos::OrdinalTraits<DT>::one();
401 if(last1-first1 > DT1){
402 IT1 pivot = getPivot(first1, last1);
403 pivot = partition2(first1, last1, first2, last2, pivot);
404 quicksort2(first1, pivot, first2, first2+(pivot-first1));
405 quicksort2(pivot+1, last1, first2+(pivot-first1)+1, last2);
406 }
407 }
408
421 template<class IT1, class IT2, class IT3>
423 const IT1& first1,
424 const IT1& last1,
425 const IT2& first2,
426 const IT2& last2,
427 const IT3& first3,
428 const IT3& last3)
429 {
430 typedef typename std::iterator_traits<IT1>::difference_type DT;
431 DT DT1 = Teuchos::OrdinalTraits<DT>::one();
432 if(last1-first1 > DT1){
433 IT1 pivot = getPivot(first1, last1);
434 pivot = partition3(first1, last1, first2, last2, first3, last3, pivot);
435 quicksort3(first1, pivot, first2, first2+(pivot-first1), first3, first3+(pivot-first1));
436 quicksort3(pivot+1, last1, first2+(pivot-first1)+1, last2, first3+(pivot-first1)+1, last3);
437 }
438 }
439
446 template<class IT1, class IT2, class IT3>
448 const IT1& first1,
449 const IT1& last1,
450 const IT2& first2,
451 const IT2& /* last2 */,
452 const IT3& first3,
453 const IT3& /* last3 */)
454 {
455 typedef typename std::iterator_traits<IT1>::difference_type DT;
456 DT n = last1 - first1;
457 DT m = n / 2;
458 DT z = Teuchos::OrdinalTraits<DT>::zero();
459 while (m > z)
460 {
461 DT max = n - m;
462 for (DT j = 0; j < max; j++)
463 {
464 for (DT k = j; k >= 0; k-=m)
465 {
466 if (first1[k+m] >= first1[k])
467 break;
468 std::swap(first1[k+m], first1[k]);
469 std::swap(first2[k+m], first2[k]);
470 std::swap(first3[k+m], first3[k]);
471 }
472 }
473 m = m/2;
474 }
475 }
476
483 template<class IT1, class IT2>
485 const IT1& first1,
486 const IT1& last1,
487 const IT2& first2,
488 const IT2& /* last2 */)
489 {
490 typedef typename std::iterator_traits<IT1>::difference_type DT;
491 DT n = last1 - first1;
492 DT m = n / 2;
493 DT z = Teuchos::OrdinalTraits<DT>::zero();
494 while (m > z)
495 {
496 DT max = n - m;
497 for (DT j = 0; j < max; j++)
498 {
499 for (DT k = j; k >= 0; k-=m)
500 {
501 if (first1[k+m] >= first1[k])
502 break;
503 std::swap(first1[k+m], first1[k]);
504 std::swap(first2[k+m], first2[k]);
505 }
506 }
507 m = m/2;
508 }
509 }
510
511 } //end namespace SortDetails
512
513
532 template<class IT1, class IT2>
533 void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2) {
534 // Quicksort uses best-case N log N time whether or not the input
535 // data is sorted. However, the common case in Tpetra is that the
536 // input data are sorted, so we first check whether this is the
537 // case before reverting to Quicksort.
538 if(SortDetails::isAlreadySorted(first1, last1)){
539 return;
540 }
541 SortDetails::sh_sort2(first1, last1, first2, first2+(last1-first1));
542#ifdef HAVE_TPETRA_DEBUG
543 if(!SortDetails::isAlreadySorted(first1, last1)){
544 std::cout << "Trouble: sort() did not sort !!" << std::endl;
545 return;
546 }
547#endif
548 }
549
550
567 template<class View1, class View2>
568 void sort2(View1 &view1, const size_t &size, View2 &view2) {
569 // NOTE: This assumes the view is host-accessible.
570
571 // Wrap the views as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
572 Teuchos::ArrayRCP<typename View1::non_const_value_type> view1_rcp = Kokkos::Compat::persistingView(view1, 0, size);
573 Teuchos::ArrayRCP<typename View2::non_const_value_type> view2_rcp = Kokkos::Compat::persistingView(view2, 0, size);
574
575 sort2(view1_rcp.begin(),view1_rcp.end(),view2_rcp.begin());
576 }
577
586 template<class View>
587 void sort(View &view, const size_t &size) {
588 // NOTE: This assumes the view is host-accessible.
589
590 // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
591 Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
592
593 std::sort(view_rcp.begin(),view_rcp.end());
594 }
595
604 template<class View>
605 void reverse_sort(View &view, const size_t &size) {
606 // NOTE: This assumes the view is host-accessible.
607 // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
608 Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
609
610 std::sort(view_rcp.rbegin(),view_rcp.rend());
611 }
612
613
614
615
631 template<class IT1, class IT2, class IT3>
632 void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2,
633 const IT3 &first3)
634 {
635 // Quicksort uses best-case N log N time whether or not the input
636 // data is sorted. However, the common case in Tpetra is that the
637 // input data are sorted, so we first check whether this is the
638 // case before reverting to Quicksort.
639 if(SortDetails::isAlreadySorted(first1, last1)){
640 return;
641 }
642 SortDetails::sh_sort3(first1, last1, first2, first2+(last1-first1), first3,
643 first3+(last1-first1));
644
645#ifdef HAVE_TPETRA_DEBUG
646 if(!SortDetails::isAlreadySorted(first1, last1)){
647 std::cout << " Trouble sort did not actually sort... !!!!!!" <<
648 std::endl;
649 return;
650 }
651#endif
652 }
653
697 template<class IT1, class IT2>
698 void
699 merge2 (IT1& indResultOut, IT2& valResultOut,
700 IT1 indBeg, IT1 indEnd,
701 IT2 valBeg, IT2 /* valEnd */)
702 {
703 if (indBeg == indEnd) {
704 indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
705 valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
706 }
707 else {
708 IT1 indResult = indBeg;
709 IT2 valResult = valBeg;
710 if (indBeg != indEnd) {
711 ++indBeg;
712 ++valBeg;
713 while (indBeg != indEnd) {
714 if (*indResult == *indBeg) { // adjacent column indices equal
715 *valResult += *valBeg; // merge entries by adding their values together
716 } else { // adjacent column indices not equal
717 *(++indResult) = *indBeg; // shift over the index
718 *(++valResult) = *valBeg; // shift over the value
719 }
720 ++indBeg;
721 ++valBeg;
722 }
723 ++indResult; // exclusive end of merged result
724 ++valResult; // exclusive end of merged result
725
726 // mfh 24 Feb 2014: Setting these is technically correct, but
727 // since the resulting variables aren't used after this point,
728 // it may result in a build error.
729 //
730 // indEnd = indResult;
731 // valEnd = valResult;
732 }
733 indResultOut = indResult;
734 valResultOut = valResult;
735 }
736 }
737
786 template<class IT1, class IT2, class BinaryFunction>
787 void
788 merge2 (IT1& indResultOut, IT2& valResultOut,
789 IT1 indBeg, IT1 indEnd,
790 IT2 valBeg, IT2 valEnd,
791 BinaryFunction f)
792 {
793 if (indBeg == indEnd) {
794 indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
795 valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
796 }
797 else {
798 IT1 indResult = indBeg;
799 IT2 valResult = valBeg;
800 if (indBeg != indEnd) {
801 ++indBeg;
802 ++valBeg;
803 while (indBeg != indEnd) {
804 if (*indResult == *indBeg) { // adjacent column indices equal
805 *valResult = f (*valResult, *valBeg); // merge entries via values
806 } else { // adjacent column indices not equal
807 *(++indResult) = *indBeg; // shift over the index
808 *(++valResult) = *valBeg; // shift over the value
809 }
810 ++indBeg;
811 ++valBeg;
812 }
813 ++indResult; // exclusive end of merged result
814 ++valResult; // exclusive end of merged result
815 indEnd = indResult;
816 valEnd = valResult;
817 }
818 indResultOut = indResult;
819 valResultOut = valResult;
820 }
821 }
822
823
852 template<class KeyInputIterType, class ValueInputIterType,
853 class KeyOutputIterType, class ValueOutputIterType,
854 class BinaryFunction>
855 void
856 keyValueMerge (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
857 ValueInputIterType valBeg1, ValueInputIterType valEnd1,
858 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2,
859 ValueInputIterType valBeg2, ValueInputIterType valEnd2,
860 KeyOutputIterType keyOut, ValueOutputIterType valOut,
861 BinaryFunction f)
862 {
863 while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
864 if (*keyBeg1 < *keyBeg2) {
865 *keyOut++ = *keyBeg1++;
866 *valOut++ = *valBeg1++;
867 } else if (*keyBeg1 > *keyBeg2) {
868 *keyOut++ = *keyBeg2++;
869 *valOut++ = *valBeg2++;
870 } else { // *keyBeg1 == *keyBeg2
871 *keyOut++ = *keyBeg1;
872 *valOut++ = f (*valBeg1, *valBeg2);
873 ++keyBeg1;
874 ++valBeg1;
875 ++keyBeg2;
876 ++valBeg2;
877 }
878 }
879 // At most one of the two sequences will be nonempty.
880 std::copy (keyBeg1, keyEnd1, keyOut);
881 std::copy (valBeg1, valEnd1, valOut);
882 std::copy (keyBeg2, keyEnd2, keyOut);
883 std::copy (valBeg2, valEnd2, valOut);
884 }
885
886 template<class KeyInputIterType>
887 size_t
888 keyMergeCount (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
889 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2)
890 {
891 size_t count = 0;
892 while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
893 if (*keyBeg1 < *keyBeg2) {
894 ++keyBeg1;
895 } else if (*keyBeg1 > *keyBeg2) {
896 ++keyBeg2;
897 } else { // *keyBeg1 == *keyBeg2
898 ++keyBeg1;
899 ++keyBeg2;
900 }
901 ++count;
902 }
903 // At most one of the two sequences will be nonempty.
904 count += static_cast<size_t> (keyEnd1 - keyBeg1) +
905 static_cast<size_t> (keyEnd2 - keyBeg2);
906 return count;
907 }
908
909 namespace Details {
929 bool
930 congruent (const Teuchos::Comm<int>& comm1,
931 const Teuchos::Comm<int>& comm2);
932
942 template<class DualViewType>
943 Teuchos::ArrayView<typename DualViewType::t_dev::value_type>
944 getArrayViewFromDualView (const DualViewType& x)
945 {
946 static_assert (static_cast<int> (DualViewType::t_dev::rank) == 1,
947 "The input DualView must have rank 1.");
948 TEUCHOS_TEST_FOR_EXCEPTION
949 (x.need_sync_host (), std::logic_error, "The "
950 "input Kokkos::DualView was most recently modified on device, but this "
951 "function needs the host view of the data to be the most recently "
952 "modified.");
953
954 auto x_host = x.view_host ();
955 typedef typename DualViewType::t_dev::value_type value_type;
956 // mfh 15 Jan 2019: In debug mode, Teuchos::ArrayView's
957 // constructor throws if the pointer is nonnull but the length
958 // is nonpositive.
959 const auto len = x_host.extent (0);
960 return Teuchos::ArrayView<value_type> (len != 0 ? x_host.data () : nullptr,
961 len);
962 }
963
980 template<class T, class DT>
981 Kokkos::DualView<T*, DT>
982 getDualViewCopyFromArrayView (const Teuchos::ArrayView<const T>& x_av,
983 const char label[],
984 const bool leaveOnHost)
985 {
986 using Kokkos::MemoryUnmanaged;
987 typedef typename DT::memory_space DMS;
988 typedef Kokkos::HostSpace HMS;
989
990 const size_t len = static_cast<size_t> (x_av.size ());
991 Kokkos::View<const T*, HMS, MemoryUnmanaged> x_in (x_av.getRawPtr (), len);
992 Kokkos::DualView<T*, DT> x_out (label, len);
993 if (leaveOnHost) {
994 x_out.modify_host ();
995 Kokkos::deep_copy (x_out.view_host (), x_in);
996 }
997 else {
998 x_out.template modify<DMS> ();
999 Kokkos::deep_copy (x_out.template view<DMS> (), x_in);
1000 }
1001 return x_out;
1002 }
1003
1011 template<class DualViewType>
1012 std::string dualViewStatusToString (const DualViewType& dv, const char name[])
1013 {
1014 const auto host = dv.need_sync_device();
1015 const auto dev = dv.need_sync_host();
1016
1017 std::ostringstream os;
1018 os << name << ": {size: " << dv.extent (0)
1019 << ", sync: {host: " << host << ", dev: " << dev << "}";
1020 return os.str ();
1021 }
1022
1027 template<class ArrayType>
1028 void
1029 verbosePrintArray(std::ostream& out,
1030 const ArrayType& x,
1031 const char name[],
1032 const size_t maxNumToPrint)
1033 {
1034 out << name << ": [";
1035
1036 const size_t numEnt(x.size());
1037 if (maxNumToPrint == 0) {
1038 if (numEnt != 0) {
1039 out << "...";
1040 }
1041 }
1042 else {
1043 const size_t numToPrint = numEnt > maxNumToPrint ?
1044 maxNumToPrint : numEnt;
1045 size_t k = 0;
1046 for ( ; k < numToPrint; ++k) {
1047 out << x[k];
1048 if (k + size_t(1) < numToPrint) {
1049 out << ", ";
1050 }
1051 }
1052 if (k < numEnt) {
1053 out << ", ...";
1054 }
1055 }
1056 out << "]";
1057 }
1058
1062 std::unique_ptr<std::string>
1063 createPrefix(const int myRank,
1064 const char prefix[]);
1065
1073 std::unique_ptr<std::string>
1074 createPrefix(const Teuchos::Comm<int>* comm,
1075 const char functionName[]);
1076
1083 std::unique_ptr<std::string>
1084 createPrefix(const Teuchos::Comm<int>*,
1085 const char className[],
1086 const char methodName[]);
1087
1088 } // namespace Details
1089} // namespace Tpetra
1090
1091#endif // TPETRA_UTIL_HPP
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...
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.
IT getPivot(const IT &first, const IT &last)
Determines the pivot point as part of the quicksort routine.
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 Tpetra.
Implementation details of sort routines used by Tpetra.
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.
Definition: Tpetra_Util.cpp:64
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 deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT3 &first3)
Sort the first array, and apply the same permutation to the second and third arrays.
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)
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.