40#ifndef TPETRA_UTIL_HPP
41#define TPETRA_UTIL_HPP
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"
66#if defined(HAVE_TPETRA_THROW_EFFICIENCY_WARNINGS) || defined(HAVE_TPETRA_PRINT_EFFICIENCY_WARNINGS)
100#define TPETRA_EFFICIENCY_WARNING(throw_exception_test,Exception,msg) \
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; \
108 std::string err = errStream.str(); \
109 if (TPETRA_PRINTS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest) { \
110 std::cerr << err << std::endl; \
112 TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest, Exception, err); \
149#define TPETRA_EFFICIENCY_WARNING(throw_exception_test,Exception,msg)
153#if defined(HAVE_TPETRA_THROW_ABUSE_WARNINGS) || defined(HAVE_TPETRA_PRINT_ABUSE_WARNINGS)
155#define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg) \
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; \
163 TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_ABUSE_WARNINGS && (throw_exception_test), Exception, err); \
167#define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg)
199#define SHARED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
201 using Teuchos::outArg; \
202 const int lcl_throw_exception = (throw_exception_test) ? Teuchos::rank(comm)+1 : 0; \
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); \
209#ifdef HAVE_TEUCHOS_DEBUG
211#define SWITCHED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
213 SHARED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm); \
217#define SWITCHED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
219 TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg); \
236 template<
typename MapType,
typename KeyArgType,
typename ValueArgType>
238 const KeyArgType & k,
239 const ValueArgType & v)
241 typename MapType::iterator lb = m.lower_bound(k);
242 if(lb != m.end() && !(m.key_comp()(k, lb->first))) {
247 typedef typename MapType::value_type MVT;
248 return(m.insert(lb, MVT(k, v)));
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]){
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;
313 template<
class IT1,
class IT2>
321 typename std::iterator_traits<IT1>::value_type piv(*pivot);
322 std::swap(*pivot, *(last1-1));
323 std::swap(first2[(pivot-first1)], *(last2-1));
325 for(IT1 it=first1; it!=last1-1; ++it){
327 std::swap(*store1, *it);
328 std::swap(first2[(store1-first1)], first2[(it-first1)]);
332 std::swap(*(last1-1), *store1);
333 std::swap(*(last2-1), first2[store1-first1]);
353 template<
class IT1,
class IT2,
class IT3>
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));
368 for(IT1 it=first1; it!=last1-1; ++it){
370 std::swap(*store1, *it);
371 std::swap(first2[(store1-first1)], first2[(it-first1)]);
372 std::swap(first3[(store1-first1)], first3[(it-first1)]);
376 std::swap(*(last1-1), *store1);
377 std::swap(*(last2-1), first2[store1-first1]);
378 std::swap(*(last3-1), first3[store1-first1]);
392 template<
class IT1,
class IT2>
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);
421 template<
class IT1,
class IT2,
class IT3>
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);
446 template<
class IT1,
class IT2,
class IT3>
455 typedef typename std::iterator_traits<IT1>::difference_type DT;
456 DT n = last1 - first1;
458 DT z = Teuchos::OrdinalTraits<DT>::zero();
462 for (DT j = 0; j < max; j++)
464 for (DT k = j; k >= 0; k-=m)
466 if (first1[k+m] >= first1[k])
468 std::swap(first1[k+m], first1[k]);
469 std::swap(first2[k+m], first2[k]);
470 std::swap(first3[k+m], first3[k]);
483 template<
class IT1,
class IT2>
490 typedef typename std::iterator_traits<IT1>::difference_type DT;
491 DT n = last1 - first1;
493 DT z = Teuchos::OrdinalTraits<DT>::zero();
497 for (DT j = 0; j < max; j++)
499 for (DT k = j; k >= 0; k-=m)
501 if (first1[k+m] >= first1[k])
503 std::swap(first1[k+m], first1[k]);
504 std::swap(first2[k+m], first2[k]);
532 template<
class IT1,
class IT2>
533 void sort2(
const IT1 &first1,
const IT1 &last1,
const IT2 &first2) {
538 if(SortDetails::isAlreadySorted(first1, last1)){
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;
567 template<
class View1,
class View2>
568 void sort2(View1 &view1,
const size_t &size, View2 &view2) {
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);
575 sort2(view1_rcp.begin(),view1_rcp.end(),view2_rcp.begin());
587 void sort(View &view,
const size_t &size) {
591 Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
593 std::sort(view_rcp.begin(),view_rcp.end());
608 Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
610 std::sort(view_rcp.rbegin(),view_rcp.rend());
631 template<
class IT1,
class IT2,
class IT3>
632 void sort3(
const IT1 &first1,
const IT1 &last1,
const IT2 &first2,
639 if(SortDetails::isAlreadySorted(first1, last1)){
642 SortDetails::sh_sort3(first1, last1, first2, first2+(last1-first1), first3,
643 first3+(last1-first1));
645#ifdef HAVE_TPETRA_DEBUG
646 if(!SortDetails::isAlreadySorted(first1, last1)){
647 std::cout <<
" Trouble sort did not actually sort... !!!!!!" <<
697 template<
class IT1,
class IT2>
699 merge2 (IT1& indResultOut, IT2& valResultOut,
700 IT1 indBeg, IT1 indEnd,
703 if (indBeg == indEnd) {
704 indResultOut = indBeg;
705 valResultOut = valBeg;
708 IT1 indResult = indBeg;
709 IT2 valResult = valBeg;
710 if (indBeg != indEnd) {
713 while (indBeg != indEnd) {
714 if (*indResult == *indBeg) {
715 *valResult += *valBeg;
717 *(++indResult) = *indBeg;
718 *(++valResult) = *valBeg;
733 indResultOut = indResult;
734 valResultOut = valResult;
786 template<
class IT1,
class IT2,
class BinaryFunction>
788 merge2 (IT1& indResultOut, IT2& valResultOut,
789 IT1 indBeg, IT1 indEnd,
790 IT2 valBeg, IT2 valEnd,
793 if (indBeg == indEnd) {
794 indResultOut = indBeg;
795 valResultOut = valBeg;
798 IT1 indResult = indBeg;
799 IT2 valResult = valBeg;
800 if (indBeg != indEnd) {
803 while (indBeg != indEnd) {
804 if (*indResult == *indBeg) {
805 *valResult = f (*valResult, *valBeg);
807 *(++indResult) = *indBeg;
808 *(++valResult) = *valBeg;
818 indResultOut = indResult;
819 valResultOut = valResult;
852 template<
class KeyInputIterType,
class ValueInputIterType,
853 class KeyOutputIterType,
class ValueOutputIterType,
854 class BinaryFunction>
857 ValueInputIterType valBeg1, ValueInputIterType valEnd1,
858 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2,
859 ValueInputIterType valBeg2, ValueInputIterType valEnd2,
860 KeyOutputIterType keyOut, ValueOutputIterType valOut,
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++;
871 *keyOut++ = *keyBeg1;
872 *valOut++ = f (*valBeg1, *valBeg2);
880 std::copy (keyBeg1, keyEnd1, keyOut);
881 std::copy (valBeg1, valEnd1, valOut);
882 std::copy (keyBeg2, keyEnd2, keyOut);
883 std::copy (valBeg2, valEnd2, valOut);
886 template<
class KeyInputIterType>
888 keyMergeCount (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
889 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2)
892 while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
893 if (*keyBeg1 < *keyBeg2) {
895 }
else if (*keyBeg1 > *keyBeg2) {
904 count +=
static_cast<size_t> (keyEnd1 - keyBeg1) +
905 static_cast<size_t> (keyEnd2 - keyBeg2);
930 congruent (
const Teuchos::Comm<int>& comm1,
931 const Teuchos::Comm<int>& comm2);
942 template<
class DualViewType>
943 Teuchos::ArrayView<typename DualViewType::t_dev::value_type>
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 "
954 auto x_host = x.view_host ();
955 typedef typename DualViewType::t_dev::value_type value_type;
959 const auto len = x_host.extent (0);
960 return Teuchos::ArrayView<value_type> (len != 0 ? x_host.data () :
nullptr,
980 template<
class T,
class DT>
981 Kokkos::DualView<T*, DT>
984 const bool leaveOnHost)
986 using Kokkos::MemoryUnmanaged;
987 typedef typename DT::memory_space DMS;
988 typedef Kokkos::HostSpace HMS;
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);
994 x_out.modify_host ();
998 x_out.template modify<DMS> ();
1011 template<
class DualViewType>
1014 const auto host = dv.need_sync_device();
1015 const auto dev = dv.need_sync_host();
1017 std::ostringstream os;
1018 os << name <<
": {size: " << dv.extent (0)
1019 <<
", sync: {host: " << host <<
", dev: " << dev <<
"}";
1027 template<
class ArrayType>
1032 const size_t maxNumToPrint)
1034 out << name <<
": [";
1036 const size_t numEnt(x.size());
1037 if (maxNumToPrint == 0) {
1043 const size_t numToPrint = numEnt > maxNumToPrint ?
1044 maxNumToPrint : numEnt;
1046 for ( ; k < numToPrint; ++k) {
1048 if (k +
size_t(1) < numToPrint) {
1062 std::unique_ptr<std::string>
1064 const char prefix[]);
1073 std::unique_ptr<std::string>
1075 const char functionName[]);
1083 std::unique_ptr<std::string>
1085 const char className[],
1086 const char methodName[]);
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.
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.