|
Zoltan2
|
00001 // @HEADER 00002 // 00003 // *********************************************************************** 00004 // 00005 // Zoltan2: A package of combinatorial algorithms for scientific computing 00006 // Copyright 2012 Sandia Corporation 00007 // 00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00009 // the U.S. Government retains certain rights in this software. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Karen Devine (kddevin@sandia.gov) 00039 // Erik Boman (egboman@sandia.gov) 00040 // Siva Rajamanickam (srajama@sandia.gov) 00041 // 00042 // *********************************************************************** 00043 // 00044 // @HEADER 00045 // @HEADER 00046 // *********************************************************************** 00047 // copyright 00048 // 00049 // *********************************************************************** 00050 // @HEADER 00051 00056 #ifndef _ZOLTAN2_IDENTIFIERTRAITS 00057 #define _ZOLTAN2_IDENTIFIERTRAITS 00058 00059 #include <Zoltan2_Standards.hpp> 00060 #include <Zoltan2_AlltoAll.hpp> 00061 00062 #include <Teuchos_SerializationTraits.hpp> 00063 #include <Teuchos_HashUtils.hpp> 00064 #include <Teuchos_ReductionOp.hpp> 00065 00066 #include <utility> 00067 #include <iostream> 00068 #include <sstream> 00069 #include <string> 00070 #include <limits> 00071 #include <cstdlib> 00072 00073 using Teuchos::SerializationTraits; 00074 00075 namespace Zoltan2 00076 { 00077 extern int getHashCode(const unsigned char *a, size_t len); 00078 00081 template <typename T> 00082 std::pair<T, T> z2LocalMinMax(const T *val, size_t n) 00083 { 00084 T max = std::numeric_limits<T>::min(); 00085 T min = std::numeric_limits<T>::max(); 00086 00087 for (size_t i=0; i < n; i++){ 00088 if (val[i] < min) min = val[i]; 00089 if (val[i] > max) max = val[i]; 00090 } 00091 return std::pair<T,T>(min,max); 00092 } 00093 00094 00100 template <typename T> class Zoltan2_MinMaxOperation : 00101 public ::Teuchos::ValueTypeReductionOp<int, char> 00102 { 00103 public: 00104 void reduce( 00105 const int count, const char inBuffer[], char inoutBuffer[]) const 00106 { 00107 const T *in = reinterpret_cast<const T*>(inBuffer); 00108 T *inout = reinterpret_cast<T*>(inoutBuffer); 00109 00110 if (in[0] < inout[0]) inout[0] = in[0]; 00111 if (in[1] > inout[1]) inout[1] = in[1]; 00112 } 00113 }; 00114 00117 template <typename T> 00118 void z2GlobalMinMax(const Comm<int> &comm, bool noLocalValues, 00119 T localMin, T localMax, T &globalMin, T &globalMax) 00120 { 00121 if (noLocalValues){ 00122 localMin = std::numeric_limits<T>::max(); 00123 localMax = std::numeric_limits<T>::min(); 00124 } 00125 00126 if (comm.getSize() == 1){ 00127 globalMin = localMin; 00128 globalMax = localMax; 00129 return; 00130 } 00131 00132 T localValues[2] = {localMin, localMax}; 00133 T globalValues[2]; 00134 00135 char *lv = reinterpret_cast<char *>(&localValues[0]); 00136 char *gv = reinterpret_cast<char *>(&globalValues[0]); 00137 00138 Zoltan2_MinMaxOperation<T> reductionOp; 00139 ::Teuchos::reduceAll<int, char>(comm, reductionOp, 2*sizeof(T), lv, gv); 00140 00141 globalMin = globalValues[0]; 00142 globalMax = globalValues[1]; 00143 } 00144 00147 template <typename T> 00148 bool z2AreConsecutive(const T *val, size_t n) 00149 { 00150 if (n == 0) return true; 00151 00152 if (val[n-1] - val[0] + 1 != T(n)) 00153 return false; 00154 00155 T nextval = val[0]+1; 00156 for (size_t i=1; i < n; i++){ 00157 if (val[i] != nextval) 00158 return false; 00159 nextval++; 00160 } 00161 return true; 00162 } 00163 00166 template <typename T> 00167 std::string stringifyOrdinal(T ordinal) 00168 { 00169 std::ostringstream oss; 00170 oss << ordinal; 00171 return oss.str(); 00172 } 00173 00176 template<typename T> 00177 struct UndefIdTraits 00178 { 00179 static inline void noop() { 00180 T::UsingInvalidGlobalIdentifierDataType(); 00181 } 00182 static inline T invalid() { 00183 return T::UsingInvalidGlobalIdentifierDataType(); 00184 } 00185 }; 00186 00187 00239 template<typename T> 00240 struct IdentifierTraits { 00241 00247 static int hashCode(const T id) { 00248 return UndefIdTraits<int>::invalid(); 00249 } 00250 00255 static inline bool hasUniqueKey(){ 00256 return UndefIdTraits<bool>::invalid();} 00257 00265 static inline double key(const T c){return static_cast<double>(c); } 00266 00271 static inline std::string name() { 00272 return UndefIdTraits<std::string>::invalid(); 00273 } 00274 00280 static std::string stringify(T val) { 00281 return UndefIdTraits<std::string>::invalid(); 00282 } 00283 00290 static inline bool isGlobalOrdinal() { 00291 return UndefIdTraits<bool>::invalid(); 00292 } 00293 00303 static inline T difference(const T a, const T b) { 00304 return UndefIdTraits<bool>::invalid(); 00305 } 00306 00312 static inline bool is_valid_id_type() { return false; } 00313 00323 static void minMax(const T *values, size_t numValues, T &min, T&max) { 00324 UndefIdTraits<T>::noop(); 00325 } 00326 00340 static void globalMinMax(const Comm<int> &comm, bool flag, 00341 T localMin, T localMax, T &globalMin, T &globalMax){ 00342 UndefIdTraits<T>::noop(); 00343 } 00344 00355 static bool areConsecutive(const T *val, size_t n){ 00356 return UndefIdTraits<bool>::invalid(); 00357 } 00358 00359 }; 00360 00361 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00362 00363 /* The specializations of the hashCode is not a true hash. 00364 * For types that can fit in an int it is just a typecast to int. 00365 * This can be used with a modulo capacity of table/array to find the basic 00366 * hash. For types larger than that can fit in an int, it tries to be a 00367 * little smarter by adding all the bytes into an int. It also ensures it is 00368 * positive so you can use it as an index. 00369 * */ 00370 00371 template<> 00372 struct IdentifierTraits<char> { 00373 typedef char T; 00374 static inline int hashCode(const T c) {return static_cast<int>(c);} 00375 static inline bool hasUniqueKey() { return true;} 00376 static inline double key(const T c){return static_cast<double>(c); } 00377 static inline std::string name() {return("char");} 00378 static std::string stringify(T val) {return stringifyOrdinal(val);} 00379 static inline bool isGlobalOrdinal() {return true; } 00380 00381 static inline T difference(const T a, const T b) { return (b-a); } 00382 static inline bool is_valid_id_type() {return true; } 00383 static void minMax(const T *values, size_t n, T &min, T &max) { 00384 std::pair<T, T> ext = z2LocalMinMax(values, n); 00385 min = ext.first; 00386 max = ext.second; 00387 } 00388 static void globalMinMax(const Comm<int> &comm, bool flag, 00389 T localMin, T localMax, T &globalMin, T &globalMax){ 00390 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00391 static bool areConsecutive(const T *val, size_t n){ 00392 return z2AreConsecutive(val, n); } 00393 }; 00394 00395 template<> 00396 struct IdentifierTraits<unsigned char> { 00397 typedef unsigned char T; 00398 static inline int hashCode(const T c) {return static_cast<int>(c);} 00399 static inline bool hasUniqueKey() { return true;} 00400 static inline double key(const T c){return static_cast<double>(c); } 00401 static inline std::string name() {return("unsigned char");} 00402 static std::string stringify(T val) {return stringifyOrdinal(val);} 00403 static inline bool isGlobalOrdinal() {return true; } 00404 00405 static inline T difference(const T a, const T b) { return (b-a); } 00406 static inline bool is_valid_id_type() {return true; } 00407 static void minMax(const T *values, size_t n, T &min, T &max) { 00408 std::pair<T, T> ext = z2LocalMinMax(values, n); 00409 min = ext.first; 00410 max = ext.second; 00411 } 00412 static void globalMinMax(const Comm<int> &comm, bool flag, 00413 T localMin, T localMax, T &globalMin, T &globalMax){ 00414 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00415 static bool areConsecutive(const T *val, size_t n){ 00416 return z2AreConsecutive(val, n); } 00417 }; 00418 00419 template<> 00420 struct IdentifierTraits<short> { 00421 typedef short T; 00422 static inline int hashCode(const T a) {return static_cast<int>(a);} 00423 static inline bool hasUniqueKey() { return true;} 00424 static inline double key(const T a){return static_cast<double>(a); } 00425 static inline std::string name() {return("short");} 00426 static std::string stringify(T val) {return stringifyOrdinal(val);} 00427 static inline bool isGlobalOrdinal() {return true; } 00428 00429 static inline T difference(const T a, const T b) { return (b-a); } 00430 static inline bool is_valid_id_type() {return true; } 00431 static void minMax(const T *values, size_t n, T &min, T &max) { 00432 std::pair<T, T> ext = z2LocalMinMax(values, n); 00433 min = ext.first; 00434 max = ext.second; 00435 } 00436 static void globalMinMax(const Comm<int> &comm, bool flag, 00437 T localMin, T localMax, T &globalMin, T &globalMax){ 00438 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00439 static bool areConsecutive(const T *val, size_t n){ 00440 return z2AreConsecutive(val, n); } 00441 }; 00442 00443 template<> 00444 struct IdentifierTraits<unsigned short> { 00445 typedef unsigned short T; 00446 static inline int hashCode(const T a) {return static_cast<int>(a);} 00447 static inline bool hasUniqueKey() { return true;} 00448 static inline double key(const T a){return static_cast<double>(a); } 00449 static inline std::string name() {return("unsigned short");} 00450 static std::string stringify(T val) {return stringifyOrdinal(val);} 00451 static inline bool isGlobalOrdinal() {return true; } 00452 00453 static inline T difference(const T a, const T b) { return (b-a); } 00454 static inline bool is_valid_id_type() {return true; } 00455 static void minMax(const T *values, size_t n, T &min, T &max) { 00456 std::pair<T, T> ext = z2LocalMinMax(values, n); 00457 min = ext.first; 00458 max = ext.second; 00459 } 00460 static void globalMinMax(const Comm<int> &comm, bool flag, 00461 T localMin, T localMax, T &globalMin, T &globalMax){ 00462 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00463 static bool areConsecutive(const T *val, size_t n){ 00464 return z2AreConsecutive(val, n); } 00465 }; 00466 00467 template<> 00468 struct IdentifierTraits<int> { 00469 typedef int T; 00470 static inline int hashCode(const T a) {return static_cast<int>(a);} 00471 static inline bool hasUniqueKey() { return true;} 00472 static inline double key(const T a){return static_cast<double>(a); } 00473 static inline std::string name() {return("int");} 00474 static std::string stringify(T val) {return stringifyOrdinal(val);} 00475 static inline bool isGlobalOrdinal() {return true; } 00476 00477 static inline T difference(const T a, const T b) { return (b-a); } 00478 static inline bool is_valid_id_type() {return true; } 00479 static void minMax(const T *values, size_t n, T &min, T &max) { 00480 std::pair<T, T> ext = z2LocalMinMax(values, n); 00481 min = ext.first; 00482 max = ext.second; 00483 } 00484 static void globalMinMax(const Comm<int> &comm, bool flag, 00485 T localMin, T localMax, T &globalMin, T &globalMax){ 00486 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00487 static bool areConsecutive(const T *val, size_t n){ 00488 return z2AreConsecutive(val, n); } 00489 }; 00490 00491 template<> 00492 struct IdentifierTraits<unsigned int> { 00493 typedef unsigned int T; 00494 static inline int hashCode(const T a) { 00495 return getHashCode( 00496 reinterpret_cast<const unsigned char *>(&a), sizeof(T));} 00497 static inline bool hasUniqueKey() { return true;} 00498 static inline double key(const T a){return static_cast<double>(a); } 00499 static inline std::string name() {return("unsigned int");} 00500 static std::string stringify(T val) {return stringifyOrdinal(val);} 00501 static inline bool isGlobalOrdinal() {return true; } 00502 00503 static inline T difference(const T a, const T b) { return (b-a); } 00504 static inline bool is_valid_id_type() {return true; } 00505 static void minMax(const T *values, size_t n, T &min, T &max) { 00506 std::pair<T, T> ext = z2LocalMinMax(values, n); 00507 min = ext.first; 00508 max = ext.second; 00509 } 00510 static void globalMinMax(const Comm<int> &comm, bool flag, 00511 T localMin, T localMax, T &globalMin, T &globalMax){ 00512 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00513 static bool areConsecutive(const T *val, size_t n){ 00514 return z2AreConsecutive(val, n); } 00515 }; 00516 00517 00518 template<> 00519 struct IdentifierTraits<long> { 00520 typedef long T; 00521 static inline int hashCode(const T a) { 00522 return getHashCode( 00523 reinterpret_cast<const unsigned char *>(&a), sizeof(T));} 00524 static inline bool hasUniqueKey() { return true;} 00525 static inline double key(const T a){return static_cast<double>(a); } 00526 static inline std::string name() {return("long");} 00527 static std::string stringify(T val) {return stringifyOrdinal(val);} 00528 static inline bool isGlobalOrdinal() {return true; } 00529 static inline T difference(const T a, const T b) { return (b-a); } 00530 static inline bool is_valid_id_type() {return true; } 00531 static void minMax(const T *values, size_t n, T &min, T &max) { 00532 std::pair<T, T> ext = z2LocalMinMax(values, n); 00533 min = ext.first; 00534 max = ext.second; 00535 } 00536 static void globalMinMax(const Comm<int> &comm, bool flag, 00537 T localMin, T localMax, T &globalMin, T &globalMax){ 00538 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00539 static bool areConsecutive(const T *val, size_t n){ 00540 return z2AreConsecutive(val, n); } 00541 }; 00542 00543 template<> 00544 struct IdentifierTraits<unsigned long> { 00545 typedef unsigned long T; 00546 static inline int hashCode(const T a) { 00547 return getHashCode( 00548 reinterpret_cast<const unsigned char *>(&a), sizeof(T));} 00549 static inline bool hasUniqueKey() { return true;} 00550 static inline double key(const T a){return static_cast<double>(a);} 00551 static inline std::string name() {return("unsigned long");} 00552 static std::string stringify(T val) {return stringifyOrdinal(val);} 00553 static inline bool isGlobalOrdinal() {return true; } 00554 static inline T difference(const T a, const T b) { return (b-a); } 00555 static inline bool is_valid_id_type() {return true; } 00556 static void minMax(const T *values, size_t n, T &min, T &max) { 00557 std::pair<T, T> ext = z2LocalMinMax(values, n); 00558 min = ext.first; 00559 max = ext.second; 00560 } 00561 static void globalMinMax(const Comm<int> &comm, bool flag, 00562 T localMin, T localMax, T &globalMin, T &globalMax){ 00563 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00564 static bool areConsecutive(const T *val, size_t n){ 00565 return z2AreConsecutive(val, n); } 00566 }; 00567 00568 #ifdef HAVE_ZOLTAN2_LONG_LONG 00569 00570 template<> 00571 struct IdentifierTraits<long long> { 00572 typedef long long T; 00573 static inline int hashCode(const T a) { 00574 return getHashCode( 00575 reinterpret_cast<const unsigned char *>(&a), sizeof(T));} 00576 static inline bool hasUniqueKey() { return true;} 00577 static inline double key(const T a){return static_cast<double>(a); } 00578 static inline std::string name() {return("long long");} 00579 static std::string stringify(T val) {return stringifyOrdinal(val);} 00580 static inline bool isGlobalOrdinal() {return true; } 00581 static inline T difference(const T a, const T b) { return (b-a); } 00582 static inline bool is_valid_id_type() {return true; } 00583 static void minMax(const T *values, size_t n, T &min, T &max) { 00584 std::pair<T, T> ext = z2LocalMinMax(values, n); 00585 min = ext.first; 00586 max = ext.second; 00587 } 00588 static void globalMinMax(const Comm<int> &comm, bool flag, 00589 T localMin, T localMax, T &globalMin, T &globalMax){ 00590 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00591 static bool areConsecutive(const T *val, size_t n){ 00592 return z2AreConsecutive(val, n); } 00593 }; 00594 00595 template<> 00596 struct IdentifierTraits<unsigned long long> { 00597 typedef unsigned long long T; 00598 static inline int hashCode(const T a) { 00599 return getHashCode( 00600 reinterpret_cast<const unsigned char *>(&a), sizeof(T));} 00601 static inline bool hasUniqueKey() { return true;} 00602 static inline double key(const T a){return static_cast<double>(a);} 00603 static inline std::string name() {return("unsigned long long");} 00604 static std::string stringify(T val) {return stringifyOrdinal(val);} 00605 static inline bool isGlobalOrdinal() {return true; } 00606 static inline T difference(const T a, const T b) { return (b-a); } 00607 static inline bool is_valid_id_type() {return true; } 00608 static void minMax(const T *values, size_t n, T &min, T &max) { 00609 std::pair<T, T> ext = z2LocalMinMax(values, n); 00610 min = ext.first; 00611 max = ext.second; 00612 } 00613 static void globalMinMax(const Comm<int> &comm, bool flag, 00614 T localMin, T localMax, T &globalMin, T &globalMax){ 00615 z2GlobalMinMax(comm, flag, localMin, localMax, globalMin, globalMax);} 00616 static bool areConsecutive(const T *val, size_t n){ 00617 return z2AreConsecutive(val, n); } 00618 }; 00619 00620 #endif 00621 00622 template<> 00623 struct IdentifierTraits<std::string> { 00624 typedef std::string T; 00625 static inline int hashCode(const T a) { 00626 return getHashCode( 00627 reinterpret_cast<const unsigned char *>(a.c_str()), a.size());} 00628 static inline bool hasUniqueKey() { return false;} 00629 static inline double key(const T a){ throw std::logic_error("invalid call");} 00630 static inline std::string name() {return("string");} 00631 static std::string stringify(T val) {return val;} 00632 static inline bool isGlobalOrdinal() {return false; } 00633 static inline T difference(const T a, const T b) { 00634 throw std::logic_error("invalid call");} 00635 static inline bool is_valid_id_type() {return true; } 00636 static void minMax(const T *values, size_t n, T &min, T &max) { 00637 throw std::logic_error("invalid call");} 00638 static void globalMinMax(const Comm<int> &comm, bool flag, 00639 T localMin, T localMax, T &globalMin, T &globalMax){ 00640 throw std::logic_error("invalid call");} 00641 static bool areConsecutive(const T *val, size_t n){ 00642 throw std::logic_error("invalid call");} 00643 }; 00644 00645 template<typename T1, typename T2> 00646 struct IdentifierTraits<std::pair<T1, T2> > { 00647 typedef std::pair<T1, T2> pair_t; 00648 typedef typename std::pair<pair_t, pair_t> pairPair_t; 00649 00650 static inline int hashCode(const pair_t p) { 00651 int total = IdentifierTraits<T1>::hashCode(p.first) + 00652 IdentifierTraits<T2>::hashCode(p.second); 00653 if (total < 0) 00654 { 00655 /* Convert the largest -ve int to zero and -1 to 00656 * std::numeric_limits<int>::max() 00657 * */ 00658 size_t maxIntBeforeWrap = std::numeric_limits<int>::max(); 00659 maxIntBeforeWrap ++; 00660 total += maxIntBeforeWrap; 00661 } 00662 return total; 00663 } 00664 00665 static inline bool hasUniqueKey() { 00666 if ((sizeof(T1)*2 <= sizeof(double))&&(sizeof(T2)*2 <= sizeof(double))) 00667 return true; 00668 else 00669 return false; 00670 } 00671 00672 static inline double key(const pair_t p) { 00673 size_t nbytes = sizeof(double) / 2; 00674 if ((sizeof(T1) > nbytes)||(sizeof(T2) > nbytes)) 00675 throw std::logic_error("invalid call"); 00676 else{ 00677 double keyVal=0; 00678 char *cx = reinterpret_cast<char *>(&keyVal); 00679 char *cy = cx + nbytes; 00680 T1 *xpos = reinterpret_cast<T1 *>(cx + nbytes-sizeof(T1)); 00681 T2 *ypos = reinterpret_cast<T2 *>(cy + nbytes-sizeof(T2)); 00682 // mfh 17 Apr 2014: Must do a memcpy here rather than an 00683 // assignment, in order to avoid breaking strict ANSI aliasing 00684 // rules (which compilers expect in order to optimize 00685 // correctly). 00686 memcpy (xpos, &(p.first), sizeof (T1)); // *xpos = p.first; 00687 memcpy (ypos, &(p.second), sizeof (T2)); // *ypos = p.second; 00688 return keyVal; 00689 } 00690 } 00691 00692 static inline std::string name() { 00693 std::string s("std::pair<"); 00694 s += IdentifierTraits<T1>::name(); 00695 s += std::string(", "); 00696 s += IdentifierTraits<T2>::name(); 00697 s += std::string(">"); 00698 return s; 00699 } 00700 00701 static std::string stringify(pair_t val) { 00702 std::ostringstream oss; 00703 oss << "pair<" << IdentifierTraits<T1>::name(); 00704 oss << "," << IdentifierTraits<T2>::name(); 00705 oss << ">(" << val.first << "," << val.second << ")"; 00706 return oss.str(); 00707 } 00708 00709 static inline bool isGlobalOrdinal() {return false; } 00710 00711 static inline pair_t difference( const pair_t a, const pair_t b) { 00712 throw std::logic_error("invalid call"); 00713 return pair_t();} 00714 00715 static inline bool is_valid_id_type() { 00716 return (sizeof(T1)+sizeof(T2) <= sizeof(double)); } 00717 00718 static void minMax(const pair_t *values, size_t n, pair_t &min, pair_t &max) { 00719 throw std::logic_error("invalid call");} 00720 00721 static void globalMinMax(const Comm<int> &comm, bool flag, 00722 pair_t localMin, pair_t localMax, 00723 pair_t &globalMin, pair_t &globalMax){ 00724 throw std::logic_error("invalid call");} 00725 00726 static bool areConsecutive(const pair_t *val, size_t n){ 00727 throw std::logic_error("invalid call"); 00728 return false; } 00729 }; 00730 00732 // A helper function. If T is an ordinal, are the values 00733 // globally consecutive? If so return true, otherwise 00734 // return false. 00735 // 00736 // On return, globalLen is set to the sum of the local lengths. 00737 // 00738 // If T is an ordinal, but the list is not globally consecutive, 00739 // on return dist[0] is set to the global minimum of 00740 // the values and dist[1] to the global maximum. 00741 // 00742 // If T is an ordinal and the list is globally consecutive, 00743 // on return dist[p] is set to val[0] on process p. dist[nprocs] 00744 // is set to one past the global maximum value. 00746 00747 template <typename T> 00748 bool globallyConsecutiveOrdinals( 00749 const Comm<int> &comm, const Environment &env, 00750 const T* val, size_t len, 00751 ArrayRCP<T> &dist, size_t &globalLen) 00752 { 00753 // Non-ordinals can not be consecutive. 00754 00755 if (!IdentifierTraits<T>::isGlobalOrdinal()) 00756 return false; 00757 00758 // return values 00759 00760 T *distBuf= NULL; 00761 T *minMaxBuf= NULL; 00762 globalLen = 0; 00763 00764 // Locally consecutive? 00765 00766 int nprocs = comm.getSize(); 00767 bool locallyConsecutive = IdentifierTraits<T>::areConsecutive(val, len); 00768 bool globallyConsecutive = false; 00769 00770 if (nprocs == 1){ 00771 if (locallyConsecutive){ 00772 distBuf = new T [2]; 00773 if (len > 0){ 00774 distBuf[0] = val[0]; 00775 distBuf[1] = val[len-1] + 1; 00776 } 00777 else{ 00778 distBuf[0] = 0; 00779 distBuf[1] = 0; 00780 } 00781 } 00782 else{ 00783 std::pair<T, T> extrema = z2LocalMinMax(val, len); 00784 minMaxBuf = new T [2]; 00785 minMaxBuf[0] = extrema.first; 00786 minMaxBuf[1] = extrema.second; 00787 } 00788 00789 globalLen = len; 00790 globallyConsecutive = locallyConsecutive; 00791 } 00792 else{ // nprocs > 1 00793 try{ 00794 reduceAll<int, size_t>(comm, ::Teuchos::REDUCE_SUM, 1, &len, &globalLen); 00795 } 00796 Z2_THROW_OUTSIDE_ERROR(env); 00797 00798 T v0, v1, gMin, gMax; 00799 00800 if (len > 0){ 00801 v0 = val[0]; 00802 v1 = val[len-1]; 00803 } 00804 else { 00805 v0 = std::numeric_limits<T>::max(); 00806 v1 = std::numeric_limits<T>::min(); 00807 } 00808 00809 try{ 00810 IdentifierTraits<T>::globalMinMax(comm, len==0, v0, v1, gMin, gMax); 00811 } 00812 Z2_FORWARD_EXCEPTIONS; 00813 00814 int lFlag = (locallyConsecutive ? 1 : 0); 00815 int gFlag = 0; 00816 00817 try{ 00818 reduceAll<int, int>(comm, ::Teuchos::REDUCE_MIN, 1, &lFlag, &gFlag); 00819 } 00820 Z2_THROW_OUTSIDE_ERROR(env); 00821 00822 if (gFlag == 1){ // all processes have consecutive values 00823 00824 size_t g0 = static_cast<size_t>(gMin); 00825 size_t g1 = static_cast<size_t>(gMax); 00826 00827 if (g1 - g0 + 1 == globalLen){ 00828 size_t sentinel = g1 + 1; // invalid id 00829 size_t sendVal = sentinel; 00830 if (len > 0) 00831 sendVal = static_cast<size_t>(v0); 00832 00833 size_t *recvBuf = new size_t[nprocs]; 00834 00835 try { 00836 ::Teuchos::gatherAll<int, size_t>(comm, 1, &sendVal, nprocs, recvBuf); 00837 } 00838 Z2_THROW_OUTSIDE_ERROR(env); 00839 00840 int numNoIds = 0; // number of procs with no ids 00841 for (int i=0; i < nprocs; i++) 00842 if (recvBuf[i] == sentinel) 00843 numNoIds++; 00844 00845 globallyConsecutive = true; 00846 00847 if (numNoIds == 0){ 00848 for (int i=1; globallyConsecutive && i < nprocs; i++) 00849 if (recvBuf[i] < recvBuf[i-1]) 00850 globallyConsecutive = false; 00851 00852 if (globallyConsecutive){ 00853 distBuf = new T [nprocs+1]; 00854 for (int i=0; i < nprocs; i++) 00855 distBuf[i] = static_cast<T>(recvBuf[i]); 00856 distBuf[nprocs] = static_cast<T>(sentinel); 00857 } 00858 } 00859 else{ 00860 Array<int> index; 00861 for (int i=0; i < nprocs; i++) 00862 if (recvBuf[i] != sentinel) 00863 index.push_back(i); 00864 00865 for (int i=1; i < index.size(); i++){ 00866 if (recvBuf[index[i]] < recvBuf[index[i-1]]) 00867 globallyConsecutive = false; 00868 } 00869 00870 if (globallyConsecutive){ 00871 distBuf = new T [nprocs+1]; 00872 for (int i=0; i < nprocs+1; i++) 00873 distBuf[i] = static_cast<T>(sentinel); 00874 00875 for (int i=0; i < index.size(); i++) 00876 distBuf[index[i]] = static_cast<T>(recvBuf[index[i]]); 00877 00878 T useValue = static_cast<T>(sentinel); 00879 for (int i = nprocs-1; i >= 0; i--){ 00880 if (distBuf[i] == static_cast<T>(sentinel)) 00881 distBuf[i] = useValue; 00882 else 00883 useValue = distBuf[i]; 00884 } 00885 } 00886 } 00887 delete [] recvBuf; 00888 } 00889 } // all processes have locally consecutive values 00890 00891 if (!globallyConsecutive){ 00892 minMaxBuf = new T [2]; 00893 minMaxBuf[0] = gMin; 00894 minMaxBuf[1] = gMax; 00895 } 00896 } // nprocs > 1 00897 00898 if (minMaxBuf) 00899 dist = arcp(minMaxBuf, 0, 2, true); 00900 else if (distBuf) 00901 dist = arcp(distBuf, 0, nprocs+1, true); 00902 else 00903 throw std::logic_error("no buffer"); // should never get here 00904 00905 return globallyConsecutive; 00906 } 00907 00908 #endif // DOXYGEN_SHOULD_SKIP_THIS 00909 00910 } // namespace Z2 00911 00912 #endif // _ZOLTAN2_IDENTIFIERTRAITS
1.7.6.1