Teuchos - Trilinos Tools Package Version of the Day
Teuchos_CommHelpers.cpp
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include "Teuchos_CommHelpers.hpp"
00043 #ifdef HAVE_MPI
00044 #  include "Teuchos_Details_MpiCommRequest.hpp"
00045 #endif // HAVE_MPI
00046 
00047 namespace Teuchos {
00048 namespace { // (anonymous)
00049 
00050 #ifdef HAVE_MPI
00051 
00052 MPI_Op getMpiOpForEReductionType (const enum EReductionType reductionType) {
00053   switch (reductionType) {
00054   case REDUCE_SUM: return MPI_SUM;
00055   case REDUCE_MIN: return MPI_MIN;
00056   case REDUCE_MAX: return MPI_MAX;
00057   case REDUCE_AND: return MPI_LAND; // logical AND, not bitwise AND
00058   default:
00059     TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
00060       "The given EReductionType value is invalid.");
00061   }
00062 }
00063 
00067 std::string getMpiErrorString (const int errCode) {
00068   // Space for storing the error string returned by MPI.
00069   // Leave room for null termination, since I don't know if MPI does this.
00070   char errString [MPI_MAX_ERROR_STRING+1];
00071   int errStringLen = MPI_MAX_ERROR_STRING; // output argument
00072   (void) MPI_Error_string (errCode, errString, &errStringLen);
00073   // errStringLen on output is the number of characters written.
00074   // I'm not sure (the MPI 3.0 Standard doesn't say) if this
00075   // includes the '\0', so I'll make sure.  We reserved space for
00076   // the extra '\0' if needed.
00077   if (errString[errStringLen-1] != '\0') {
00078     errString[errStringLen] = '\0';
00079   }
00080   return std::string (errString); // This copies the original string.
00081 }
00082 
00090 template<class T>
00091 class MpiTypeTraits {
00092 public:
00098   static MPI_Datatype getType (const T&);
00099 };
00100 
00101 #ifdef TEUCHOS_HAVE_COMPLEX
00102 template<>
00103 class MpiTypeTraits<std::complex<double> > {
00104 public:
00105   static MPI_Datatype getType (const T&) {
00106     return MPI_C_DOUBLE_COMPLEX;
00107   }
00108 };
00109 
00110 template<>
00111 class MpiTypeTraits<std::complex<float> > {
00112 public:
00113   static MPI_Datatype getType (const T&) {
00114     return MPI_C_FLOAT_COMPLEX;
00115   }
00116 };
00117 #endif // TEUCHOS_HAVE_COMPLEX
00118 
00119 template<>
00120 class MpiTypeTraits<double> {
00121 public:
00122   static MPI_Datatype getType (const double&) {
00123     return MPI_DOUBLE;
00124   }
00125 };
00126 
00127 template<>
00128 class MpiTypeTraits<float> {
00129 public:
00130   static MPI_Datatype getType (const float&) {
00131     return MPI_FLOAT;
00132   }
00133 };
00134 
00135 #ifdef TEUCHOS_HAVE_LONG_LONG_INT
00136 template<>
00137 class MpiTypeTraits<long long> {
00138 public:
00139   static MPI_Datatype getType (const long long&) {
00140     return MPI_LONG_LONG;
00141   }
00142 };
00143 
00144 template<>
00145 class MpiTypeTraits<unsigned long long> {
00146 public:
00147   static MPI_Datatype getType (const unsigned long long&) {
00148     return MPI_UNSIGNED_LONG_LONG;
00149   }
00150 };
00151 #endif // TEUCHOS_HAVE_LONG_LONG_INT
00152 
00153 template<>
00154 class MpiTypeTraits<long> {
00155 public:
00156   static MPI_Datatype getType (const long&) {
00157     return MPI_LONG;
00158   }
00159 };
00160 
00161 template<>
00162 class MpiTypeTraits<unsigned long> {
00163 public:
00164   static MPI_Datatype getType (const unsigned long&) {
00165     return MPI_UNSIGNED_LONG;
00166   }
00167 };
00168 
00169 template<>
00170 class MpiTypeTraits<int> {
00171 public:
00172   static MPI_Datatype getType (const int&) {
00173     return MPI_INT;
00174   }
00175 };
00176 
00177 template<>
00178 class MpiTypeTraits<unsigned int> {
00179 public:
00180   static MPI_Datatype getType (const unsigned int&) {
00181     return MPI_UNSIGNED;
00182   }
00183 };
00184 
00185 template<>
00186 class MpiTypeTraits<short> {
00187 public:
00188   static MPI_Datatype getType (const short&) {
00189     return MPI_SHORT;
00190   }
00191 };
00192 
00193 template<>
00194 class MpiTypeTraits<unsigned short> {
00195 public:
00196   static MPI_Datatype getType (const unsigned short&) {
00197     return MPI_UNSIGNED_SHORT;
00198   }
00199 };
00200 #endif // HAVE_MPI
00201 
00202 
00210 template<class T>
00211 void
00212 reduceAllImpl (const Comm<int>& comm,
00213                const EReductionType reductType,
00214                const int count,
00215                const T sendBuffer[],
00216                T globalReducts[])
00217 {
00218 #ifdef HAVE_MPI
00219   // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
00220   // SerialComm or an MpiComm.  If it's something else, we fall back
00221   // to the most general implementation.
00222   const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
00223   if (mpiComm == NULL) {
00224     // Is it a SerialComm?
00225     const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
00226     if (serialComm == NULL) {
00227       // We don't know what kind of Comm we have, so fall back to the
00228       // most general implementation.
00229       std::auto_ptr<ValueTypeReductionOp<int, T> > reductOp (createOp<int, T> (reductType));
00230       reduceAll (comm, *reductOp, count, sendBuffer, globalReducts);
00231     }
00232     else { // It's a SerialComm; there is only 1 process, so just copy.
00233       std::copy (sendBuffer, sendBuffer + count, globalReducts);
00234     }
00235   } else { // It's an MpiComm.  Invoke MPI directly.
00236     MPI_Op rawMpiOp = getMpiOpForEReductionType (reductType);
00237     MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
00238     T t;
00239     MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
00240     const int err = MPI_Allreduce (const_cast<T*> (sendBuffer),
00241       globalReducts, count, rawMpiType, rawMpiOp, rawMpiComm);
00242     TEUCHOS_TEST_FOR_EXCEPTION(
00243       err != MPI_SUCCESS,
00244       std::runtime_error,
00245       "MPI_Allreduce failed with the following error: "
00246       << getMpiErrorString (err));
00247   }
00248 #else
00249   // We've built without MPI, so just assume it's a SerialComm and copy the data.
00250   std::copy (sendBuffer, sendBuffer + count, globalReducts);
00251 #endif // HAVE_MPI
00252 }
00253 
00254 
00262 template<class T>
00263 void
00264 gatherImpl (const T sendBuf[],
00265             const int sendCount,
00266             T recvBuf[],
00267             const int recvCount,
00268             const int root,
00269             const Comm<int>& comm)
00270 {
00271 #ifdef HAVE_MPI
00272   // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
00273   // SerialComm or an MpiComm.  If it's something else, we fall back
00274   // to the most general implementation.
00275   const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
00276   if (mpiComm == NULL) {
00277     // Is it a SerialComm?
00278     const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
00279     if (serialComm == NULL) {
00280       // We don't know what kind of Comm we have, so fall back to the
00281       // most general implementation.
00282       gather<int, T> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
00283     }
00284     else { // It's a SerialComm; there is only 1 process, so just copy.
00285       std::copy (sendBuf, sendBuf + sendCount, recvBuf);
00286     }
00287   } else { // It's an MpiComm.  Invoke MPI directly.
00288     MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
00289     T t;
00290     MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
00291     const int err = MPI_Gather (const_cast<T*> (sendBuf), sendCount, rawMpiType,
00292                                 recvBuf, recvCount, rawMpiType,
00293                                 root, rawMpiComm);
00294     TEUCHOS_TEST_FOR_EXCEPTION(
00295       err != MPI_SUCCESS,
00296       std::runtime_error,
00297       "MPI_Gather failed with the following error: "
00298       << getMpiErrorString (err));
00299   }
00300 #else
00301   // We've built without MPI, so just assume it's a SerialComm and copy the data.
00302   std::copy (sendBuf, sendBuf + sendCount, recvBuf);
00303 #endif // HAVE_MPI
00304 }
00305 
00306 
00314 template<class T>
00315 void
00316 gathervImpl (const T sendBuf[],
00317              const int sendCount,
00318              T recvBuf[],
00319              const int recvCounts[],
00320              const int displs[],
00321              const int root,
00322              const Comm<int>& comm)
00323 {
00324 #ifdef HAVE_MPI
00325   // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
00326   // SerialComm or an MpiComm.  If it's something else, we fall back
00327   // to the most general implementation.
00328   const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
00329   if (mpiComm == NULL) {
00330     // Is it a SerialComm?
00331     const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
00332     if (serialComm == NULL) {
00333       // We don't know what kind of Comm we have, so fall back to the
00334       // most general implementation.
00335       gatherv<int, T> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
00336     }
00337     else { // It's a SerialComm; there is only 1 process, so just copy.
00338       TEUCHOS_TEST_FOR_EXCEPTION(
00339         recvCounts[0] > sendCount, std::invalid_argument,
00340         "Teuchos::gatherv: If the input communicator contains only one "
00341         "process, then you cannot receive more entries than you send.  "
00342         "You aim to receive " << recvCounts[0] << " entries, but to send "
00343         << sendCount << " entries.");
00344       // Serial communicator case: just copy.  recvCounts[0] is the
00345       // amount to receive, so it's the amount to copy.  Start writing
00346       // to recvbuf at the offset displs[0].
00347       std::copy (sendBuf, sendBuf + recvCounts[0], recvBuf + displs[0]);
00348     }
00349   } else { // It's an MpiComm.  Invoke MPI directly.
00350     MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
00351     T t;
00352     MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
00353     const int err = MPI_Gatherv (const_cast<T*> (sendBuf),
00354                                  sendCount,
00355                                  rawMpiType,
00356                                  recvBuf,
00357                                  const_cast<int*> (recvCounts),
00358                                  const_cast<int*> (displs),
00359                                  rawMpiType,
00360                                  root,
00361                                  rawMpiComm);
00362     TEUCHOS_TEST_FOR_EXCEPTION(
00363       err != MPI_SUCCESS,
00364       std::runtime_error,
00365       "MPI_Gatherv failed with the following error: "
00366       << getMpiErrorString (err));
00367   }
00368 #else
00369   // We've built without MPI, so just assume it's a SerialComm and copy the data.
00370   TEUCHOS_TEST_FOR_EXCEPTION(
00371     recvCounts[0] > sendCount, std::invalid_argument,
00372     "Teuchos::gatherv: If the input communicator contains only one "
00373     "process, then you cannot receive more entries than you send.  "
00374     "You aim to receive " << recvCounts[0] << " entries, but to send "
00375     << sendCount << " entries.");
00376   // Serial communicator case: just copy.  recvCounts[0] is the
00377   // amount to receive, so it's the amount to copy.  Start writing
00378   // to recvbuf at the offset displs[0].
00379   std::copy (sendBuf, sendBuf + recvCounts[0], recvBuf + displs[0]);
00380 #endif // HAVE_MPI
00381 }
00382 
00383 
00391 template<class T>
00392 void
00393 reduceAllAndScatterImpl (const Comm<int>& comm,
00394                          const EReductionType reductType,
00395                          const int sendCount,
00396                          const T sendBuffer[],
00397                          const int recvCounts[],
00398                          T myGlobalReducts[])
00399 {
00400 #ifdef HAVE_MPI
00401   // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
00402   // SerialComm or an MpiComm.  If it's something else, we fall back
00403   // to the most general implementation.
00404   const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
00405   if (mpiComm == NULL) {
00406     // Is it a SerialComm?
00407     const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
00408     if (serialComm == NULL) {
00409       TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "reduceAllAndScatter: "
00410         "Not implemented for Comm not MpiComm or SerialComm.");
00411     }
00412     else { // It's a SerialComm; there is only 1 process, so just copy.
00413       //
00414       // FIXME (mfh 09 Apr 2013) Is this right?  This is what
00415       // SerialComm does.
00416       //
00417       std::copy (sendBuffer, sendBuffer + sendCount, myGlobalReducts);
00418     }
00419   } else { // It's an MpiComm.  Invoke MPI directly.
00420     MPI_Op rawMpiOp = getMpiOpForEReductionType (reductType);
00421     MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
00422     T t;
00423     MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
00424     const int err = MPI_Reduce_scatter (const_cast<T*> (sendBuffer),
00425                                         myGlobalReducts,
00426                                         const_cast<int*> (recvCounts),
00427                                         rawMpiType,
00428                                         rawMpiOp,
00429                                         rawMpiComm);
00430     TEUCHOS_TEST_FOR_EXCEPTION(
00431       err != MPI_SUCCESS,
00432       std::runtime_error,
00433       "MPI_Reduce_scatter failed with the following error: "
00434       << getMpiErrorString (err));
00435   }
00436 #else
00437   // We've built without MPI, so just assume it's a SerialComm and copy the data.
00438   //
00439   // FIXME (mfh 09 Apr 2013) Is this right?  This is what SerialComm does.
00440   //
00441   std::copy (sendBuffer, sendBuffer + sendCount, myGlobalReducts);
00442 #endif // HAVE_MPI
00443 }
00444 
00445 
00451 template<typename Packet>
00452 RCP<Teuchos::CommRequest<int> >
00453 ireceiveGeneral(const Comm<int>& comm,
00454                 const ArrayRCP<Packet> &recvBuffer,
00455                 const int sourceRank)
00456 {
00457   TEUCHOS_COMM_TIME_MONITOR(
00458     "Teuchos::ireceive<int, " << "," << TypeNameTraits<Packet>::name ()
00459     << "> ( value type )"
00460     );
00461   ValueTypeSerializationBuffer<int, Packet>
00462     charRecvBuffer (recvBuffer.size (), recvBuffer.getRawPtr ());
00463   RCP<CommRequest<int> > commRequest =
00464     comm.ireceive (charRecvBuffer.getCharBufferView (), sourceRank);
00465   set_extra_data (recvBuffer, "buffer", inOutArg (commRequest));
00466   return commRequest;
00467 }
00468 
00471 template<typename Packet>
00472 RCP<Teuchos::CommRequest<int> >
00473 ireceiveGeneral (const ArrayRCP<Packet> &recvBuffer,
00474                  const int sourceRank,
00475                  const int tag,
00476                  const Comm<int>& comm)
00477 {
00478   TEUCHOS_COMM_TIME_MONITOR(
00479     "Teuchos::ireceive<int, " << "," << TypeNameTraits<Packet>::name ()
00480     << "> ( value type )"
00481     );
00482   ValueTypeSerializationBuffer<int, Packet>
00483     charRecvBuffer (recvBuffer.size (), recvBuffer.getRawPtr ());
00484   RCP<CommRequest<int> > commRequest =
00485     comm.ireceive (charRecvBuffer.getCharBufferView (), sourceRank, tag);
00486   set_extra_data (recvBuffer, "buffer", inOutArg (commRequest));
00487   return commRequest;
00488 }
00489 
00502 template<class T>
00503 RCP<CommRequest<int> >
00504 ireceiveImpl (const Comm<int>& comm,
00505               const ArrayRCP<T>& recvBuffer,
00506               const int sourceRank)
00507 {
00508 #ifdef HAVE_MPI
00509   // Even in an MPI build, Comm might be either a SerialComm or an
00510   // MpiComm.  If it's something else, we fall back to the most
00511   // general implementation.
00512   const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
00513   if (mpiComm == NULL) {
00514     // Is it a SerialComm?
00515     const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
00516     if (serialComm == NULL) {
00517       // We don't know what kind of Comm we have, so fall back to the
00518       // most general implementation.
00519       return ireceiveGeneral<T> (comm, recvBuffer, sourceRank);
00520     }
00521     else { // SerialComm doesn't implement ireceive anyway.
00522       TEUCHOS_TEST_FOR_EXCEPTION(
00523         true,
00524         std::logic_error,
00525         "ireceiveImpl: Not implemented for a serial communicator.");
00526     }
00527   }
00528   else { // It's an MpiComm.  Invoke MPI directly.
00529     MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
00530     T t;
00531     MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
00532     T* rawRecvBuf = recvBuffer.getRawPtr ();
00533     const int count = as<int> (recvBuffer.size ());
00534     const int tag = mpiComm->getTag ();
00535     MPI_Request rawRequest = MPI_REQUEST_NULL;
00536     const int err = MPI_Irecv (rawRecvBuf, count, rawType, sourceRank, tag,
00537                                rawComm, &rawRequest);
00538     TEUCHOS_TEST_FOR_EXCEPTION(
00539       err != MPI_SUCCESS, std::runtime_error,
00540       "MPI_Irecv failed with the following error: "
00541       << getMpiErrorString (err));
00542 
00543     ArrayRCP<const char> buf =
00544       arcp_const_cast<const char> (arcp_reinterpret_cast<char> (recvBuffer));
00545     RCP<Details::MpiCommRequest> req (new Details::MpiCommRequest (rawRequest, buf));
00546     return rcp_implicit_cast<CommRequest<int> > (req);
00547   }
00548 #else
00549   TEUCHOS_TEST_FOR_EXCEPTION(
00550     true,
00551     std::logic_error,
00552     "ireceiveImpl: Not implemented for a serial communicator.");
00553 
00554   return null; // Guard to avoid compiler warning about not returning a value.
00555 #endif // HAVE_MPI
00556 }
00557 
00560 template<class T>
00561 RCP<CommRequest<int> >
00562 ireceiveImpl (const ArrayRCP<T>& recvBuffer,
00563               const int sourceRank,
00564               const int tag,
00565               const Comm<int>& comm)
00566 {
00567 #ifdef HAVE_MPI
00568   // Even in an MPI build, Comm might be either a SerialComm or an
00569   // MpiComm.  If it's something else, we fall back to the most
00570   // general implementation.
00571   const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
00572   if (mpiComm == NULL) {
00573     // Is it a SerialComm?
00574     const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
00575     if (serialComm == NULL) {
00576       // We don't know what kind of Comm we have, so fall back to the
00577       // most general implementation.
00578       return ireceiveGeneral<T> (recvBuffer, sourceRank, tag, comm);
00579     }
00580     else { // SerialComm doesn't implement ireceive anyway.
00581       TEUCHOS_TEST_FOR_EXCEPTION(
00582         true,
00583         std::logic_error,
00584         "ireceiveImpl: Not implemented for a serial communicator.");
00585     }
00586   }
00587   else { // It's an MpiComm.  Invoke MPI directly.
00588     MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
00589     T t;
00590     MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
00591     T* rawRecvBuf = recvBuffer.getRawPtr ();
00592     const int count = as<int> (recvBuffer.size ());
00593     MPI_Request rawRequest = MPI_REQUEST_NULL;
00594     const int err = MPI_Irecv (rawRecvBuf, count, rawType, sourceRank, tag,
00595                                rawComm, &rawRequest);
00596     TEUCHOS_TEST_FOR_EXCEPTION(
00597       err != MPI_SUCCESS, std::runtime_error,
00598       "MPI_Irecv failed with the following error: "
00599       << getMpiErrorString (err));
00600 
00601     ArrayRCP<const char> buf =
00602       arcp_const_cast<const char> (arcp_reinterpret_cast<char> (recvBuffer));
00603     RCP<Details::MpiCommRequest> req (new Details::MpiCommRequest (rawRequest, buf));
00604     return rcp_implicit_cast<CommRequest<int> > (req);
00605   }
00606 #else
00607   TEUCHOS_TEST_FOR_EXCEPTION(
00608     true,
00609     std::logic_error,
00610     "ireceiveImpl: Not implemented for a serial communicator.");
00611 
00612   return null; // Guard to avoid compiler warning about not returning a value.
00613 #endif // HAVE_MPI
00614 }
00615 
00621 template<class T>
00622 void
00623 sendGeneral (const Comm<int>& comm,
00624              const int count,
00625              const T sendBuffer[],
00626              const int destRank)
00627 {
00628   TEUCHOS_COMM_TIME_MONITOR(
00629     "Teuchos::send<int, " << TypeNameTraits<T>::name () << ">");
00630   ConstValueTypeSerializationBuffer<int,T> charSendBuffer (count, sendBuffer);
00631   comm.send (charSendBuffer.getBytes (),
00632              charSendBuffer.getCharBuffer (),
00633              destRank);
00634 }
00635 
00638 template<class T>
00639 void
00640 sendGeneral (const T sendBuffer[],
00641              const int count,
00642              const int destRank,
00643              const int tag,
00644              const Comm<int>& comm)
00645 {
00646   TEUCHOS_COMM_TIME_MONITOR(
00647     "Teuchos::send<int, " << TypeNameTraits<T>::name () << ">");
00648   ConstValueTypeSerializationBuffer<int,T> charSendBuffer (count, sendBuffer);
00649   comm.send (charSendBuffer.getBytes (),
00650              charSendBuffer.getCharBuffer (),
00651              destRank, tag);
00652 }
00653 
00666 template<class T>
00667 void
00668 sendImpl (const Comm<int>& comm,
00669           const int count,
00670           const T sendBuffer[],
00671           const int destRank)
00672 {
00673 #ifdef HAVE_MPI
00674   // Even in an MPI build, Comm might be either a SerialComm or an
00675   // MpiComm.  If it's something else, we fall back to the most
00676   // general implementation.
00677   const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
00678   if (mpiComm == NULL) {
00679     // Is it a SerialComm?
00680     const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
00681     if (serialComm == NULL) {
00682       // We don't know what kind of Comm we have, so fall back to the
00683       // most general implementation.
00684       sendGeneral<T> (comm, count, sendBuffer, destRank);
00685     }
00686     else { // SerialComm doesn't implement send correctly anyway.
00687       TEUCHOS_TEST_FOR_EXCEPTION(
00688         true,
00689         std::logic_error,
00690         "sendImpl: Not implemented for a serial communicator.");
00691     }
00692   }
00693   else { // It's an MpiComm.  Invoke MPI directly.
00694     MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
00695     T t;
00696     MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
00697     T* rawBuf = const_cast<T*> (sendBuffer);
00698     const int tag = mpiComm->getTag ();
00699     const int err = MPI_Send (rawBuf, count, rawType, destRank, tag, rawComm);
00700     TEUCHOS_TEST_FOR_EXCEPTION(
00701       err != MPI_SUCCESS,
00702       std::runtime_error,
00703       "MPI_Send failed with the following error: "
00704       << getMpiErrorString (err));
00705   }
00706 #else
00707   TEUCHOS_TEST_FOR_EXCEPTION(
00708     true,
00709     std::logic_error,
00710     "sendImpl: Not implemented for a serial communicator.");
00711 #endif // HAVE_MPI
00712 }
00713 
00716 template<class T>
00717 void
00718 sendImpl (const T sendBuffer[],
00719           const int count,
00720           const int destRank,
00721           const int tag,
00722           const Comm<int>& comm)
00723 {
00724 #ifdef HAVE_MPI
00725   // Even in an MPI build, Comm might be either a SerialComm or an
00726   // MpiComm.  If it's something else, we fall back to the most
00727   // general implementation.
00728   const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
00729   if (mpiComm == NULL) {
00730     // Is it a SerialComm?
00731     const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
00732     if (serialComm == NULL) {
00733       // We don't know what kind of Comm we have, so fall back to the
00734       // most general implementation.
00735       sendGeneral<T> (sendBuffer, count, destRank, tag, comm);
00736     }
00737     else { // SerialComm doesn't implement send correctly anyway.
00738       TEUCHOS_TEST_FOR_EXCEPTION(
00739         true,
00740         std::logic_error,
00741         "sendImpl: Not implemented for a serial communicator.");
00742     }
00743   }
00744   else { // It's an MpiComm.  Invoke MPI directly.
00745     MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
00746     T t;
00747     MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
00748     T* rawBuf = const_cast<T*> (sendBuffer);
00749     const int err = MPI_Send (rawBuf, count, rawType, destRank, tag, rawComm);
00750     TEUCHOS_TEST_FOR_EXCEPTION(
00751       err != MPI_SUCCESS,
00752       std::runtime_error,
00753       "MPI_Send failed with the following error: "
00754       << getMpiErrorString (err));
00755   }
00756 #else
00757   TEUCHOS_TEST_FOR_EXCEPTION(
00758     true,
00759     std::logic_error,
00760     "sendImpl: Not implemented for a serial communicator.");
00761 #endif // HAVE_MPI
00762 }
00763 
00769 template<class T>
00770 RCP<CommRequest<int> >
00771 isendGeneral (const Comm<int>& comm,
00772               const ArrayRCP<const T>& sendBuffer,
00773               const int destRank)
00774 {
00775   TEUCHOS_COMM_TIME_MONITOR(
00776     "Teuchos::isend<int," << TypeNameTraits<T>::name () << ">");
00777   ConstValueTypeSerializationBuffer<int, T>
00778     charSendBuffer (sendBuffer.size (), sendBuffer.getRawPtr ());
00779   RCP<CommRequest<int> > commRequest =
00780     comm.isend (charSendBuffer.getCharBufferView (), destRank);
00781   set_extra_data (sendBuffer, "buffer", inOutArg (commRequest));
00782   return commRequest;
00783 }
00784 
00791 template<class T>
00792 RCP<CommRequest<int> >
00793 isendGeneral (const ArrayRCP<const T>& sendBuffer,
00794               const int destRank,
00795               const int tag,
00796               const Comm<int>& comm)
00797 {
00798   TEUCHOS_COMM_TIME_MONITOR(
00799     "Teuchos::isend<int," << TypeNameTraits<T>::name () << ">");
00800   ConstValueTypeSerializationBuffer<int, T>
00801     charSendBuffer (sendBuffer.size (), sendBuffer.getRawPtr ());
00802   RCP<CommRequest<int> > commRequest =
00803     comm.isend (charSendBuffer.getCharBufferView (), destRank, tag);
00804   set_extra_data (sendBuffer, "buffer", inOutArg (commRequest));
00805   return commRequest;
00806 }
00807 
00810 template<class T>
00811 RCP<Teuchos::CommRequest<int> >
00812 isendImpl (const ArrayRCP<const T>& sendBuffer,
00813            const int destRank,
00814            const int tag,
00815            const Comm<int>& comm)
00816 {
00817 #ifdef HAVE_MPI
00818   // Even in an MPI build, Comm might be either a SerialComm or an
00819   // MpiComm.  If it's something else, we fall back to the most
00820   // general implementation.
00821   const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
00822   if (mpiComm == NULL) {
00823     // Is it a SerialComm?
00824     const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
00825     if (serialComm == NULL) {
00826       // We don't know what kind of Comm we have, so fall back to the
00827       // most general implementation.
00828       return isendGeneral<T> (sendBuffer, destRank, tag, comm);
00829     }
00830     else { // SerialComm doesn't implement send correctly anyway.
00831       TEUCHOS_TEST_FOR_EXCEPTION(
00832         true, std::logic_error,
00833         "isendImpl: Not implemented for a serial communicator.");
00834     }
00835   }
00836   else { // It's an MpiComm.  Invoke MPI directly.
00837     MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
00838     T t;
00839     MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
00840     // MPI promises not to modify the send buffer; the const_cast
00841     // merely ensures compatibilty with C89, which does not have a
00842     // "const" keyword.
00843     T* rawSendBuf = const_cast<T*> (sendBuffer.getRawPtr ());
00844     const int count = as<int> (sendBuffer.size ());
00845     MPI_Request rawRequest = MPI_REQUEST_NULL;
00846     const int err = MPI_Isend (rawSendBuf, count, rawType, destRank, tag,
00847                                rawComm, &rawRequest);
00848     TEUCHOS_TEST_FOR_EXCEPTION(
00849       err != MPI_SUCCESS,
00850       std::runtime_error,
00851       "MPI_Isend failed with the following error: "
00852       << getMpiErrorString (err));
00853 
00854     ArrayRCP<const char> buf = arcp_reinterpret_cast<const char> (sendBuffer);
00855     RCP<Details::MpiCommRequest> req (new Details::MpiCommRequest (rawRequest, buf));
00856     return rcp_implicit_cast<CommRequest<int> > (req);
00857   }
00858 #else
00859   TEUCHOS_TEST_FOR_EXCEPTION(
00860     true,
00861     std::logic_error,
00862     "isendImpl: Not implemented for a serial communicator.");
00863 #endif // HAVE_MPI
00864 }
00865 
00866 } // namespace (anonymous)
00867 
00868 
00869 const char*
00870 toString (const EReductionType reductType)
00871 {
00872   switch (reductType) {
00873   case REDUCE_SUM: return "REDUCE_SUM";
00874   case REDUCE_MIN: return "REDUCE_MIN";
00875   case REDUCE_MAX: return "REDUCE_MAX";
00876   case REDUCE_AND: return "REDUCE_AND";
00877   default:
00878     TEUCHOS_TEST_FOR_EXCEPTION(
00879       true, std::invalid_argument, "Teuchos::toString(EReductionType): "
00880       "Invalid EReductionType value " << reductType << ".  Valid values "
00881       "include REDUCE_SUM = " << REDUCE_SUM << ", REDUCE_MIN = " << REDUCE_MIN
00882       << ", REDUCE_MAX = " << REDUCE_MIN << ", and REDUCE_AND = " << REDUCE_AND
00883       << ".");
00884   }
00885 }
00886 
00887 
00888 // mfh 18 Oct 2012: Note on full template specializations
00889 //
00890 // To make Windows builds happy, declarations of full template
00891 // specializations (as found in Teuchos_CommHelpers.hpp) must use the
00892 // TEUCHOSCOMM_LIB_DLL_EXPORT macro.  However, _definitions_ of the
00893 // specializations (as found in this file) must _not_ use the macro.
00894 // That's why we don't use that macro here.
00895 
00896 #ifdef TEUCHOS_HAVE_COMPLEX
00897 // Specialization for Ordinal=int and Packet=std::complex<double>.
00898 template<>
00899 void
00900 reduceAll<int, std::complex<double> > (const Comm<int>& comm,
00901                                        const EReductionType reductType,
00902                                        const int count,
00903                                        const std::complex<double> sendBuffer[],
00904                                        std::complex<double> globalReducts[])
00905 {
00906   TEUCHOS_COMM_TIME_MONITOR(
00907     "Teuchos::reduceAll<int, std::complex<double> > (" << count << ", "
00908     << toString (reductType) << ")"
00909     );
00910   reduceAllImpl<std::complex<double> > (comm, reductType, count, sendBuffer, globalReducts);
00911 }
00912 
00913 template<>
00914 RCP<Teuchos::CommRequest<int> >
00915 ireceive<int, std::complex<double> > (const Comm<int>& comm,
00916                                       const ArrayRCP<std::complex<double> >& recvBuffer,
00917                                       const int sourceRank)
00918 {
00919   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<double> >");
00920   return ireceiveImpl<std::complex<double> > (comm, recvBuffer, sourceRank);
00921 }
00922 
00923 template<>
00924 RCP<Teuchos::CommRequest<int> >
00925 ireceive<int, std::complex<double> > (const ArrayRCP<std::complex<double> >& recvBuffer,
00926                                       const int sourceRank,
00927                                       const int tag,
00928                                       const Comm<int>& comm)
00929 {
00930   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<double> >");
00931   return ireceiveImpl<std::complex<double> > (recvBuffer, sourceRank, tag, comm);
00932 }
00933 
00934 template<>
00935 void
00936 send<int, std::complex<double> > (const Comm<int>& comm,
00937                                   const int count,
00938                                   const std::complex<double> sendBuffer[],
00939                                   const int destRank)
00940 {
00941   sendImpl<std::complex<double> > (comm, count, sendBuffer, destRank);
00942 }
00943 
00944 template<>
00945 void
00946 send<int, std::complex<double> > (const std::complex<double> sendBuffer[],
00947                                   const int count,
00948                                   const int destRank,
00949                                   const int tag,
00950                                   const Comm<int>& comm)
00951 {
00952   sendImpl<std::complex<double> > (sendBuffer, count, destRank, tag, comm);
00953 }
00954 
00955 template<>
00956 RCP<Teuchos::CommRequest<int> >
00957 isend (const ArrayRCP<const std::complex<double> >& sendBuffer,
00958        const int destRank,
00959        const int tag,
00960        const Comm<int>& comm)
00961 {
00962   return isendImpl<std::complex<double> > (sendBuffer, destRank, tag, comm);
00963 }
00964 
00965 // Specialization for Ordinal=int and Packet=std::complex<float>.
00966 template<>
00967 void
00968 reduceAll<int, std::complex<float> > (const Comm<int>& comm,
00969                                       const EReductionType reductType,
00970                                       const int count,
00971                                       const std::complex<float> sendBuffer[],
00972                                       std::complex<float> globalReducts[])
00973 {
00974   TEUCHOS_COMM_TIME_MONITOR(
00975     "Teuchos::reduceAll<int, std::complex<float> > (" << count << ", "
00976     << toString (reductType) << ")"
00977     );
00978   reduceAllImpl<std::complex<float> > (comm, reductType, count, sendBuffer, globalReducts);
00979 }
00980 
00981 template<>
00982 RCP<Teuchos::CommRequest<int> >
00983 ireceive<int, std::complex<float> > (const Comm<int>& comm,
00984                                      const ArrayRCP<std::complex<float> >& recvBuffer,
00985                                      const int sourceRank)
00986 {
00987   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<float> >");
00988   return ireceiveImpl<std::complex<float> > (comm, recvBuffer, sourceRank);
00989 }
00990 
00991 template<>
00992 RCP<Teuchos::CommRequest<int> >
00993 ireceive<int, std::complex<float> > (const ArrayRCP<std::complex<float> >& recvBuffer,
00994                                      const int sourceRank,
00995                                      const int tag,
00996                                      const Comm<int>& comm)
00997 {
00998   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<float> >");
00999   return ireceiveImpl<std::complex<float> > (recvBuffer, sourceRank, tag, comm);
01000 }
01001 
01002 template<>
01003 void
01004 send<int, std::complex<float> > (const Comm<int>& comm,
01005                                  const int count,
01006                                  const std::complex<float> sendBuffer[],
01007                                  const int destRank)
01008 {
01009   return sendImpl<std::complex<float> > (comm, count, sendBuffer, destRank);
01010 }
01011 
01012 template<>
01013 void
01014 send<int, std::complex<float> > (const std::complex<float> sendBuffer[],
01015                                  const int count,
01016                                  const int destRank,
01017                                  const int tag,
01018                                  const Comm<int>& comm)
01019 {
01020   return sendImpl<std::complex<float> > (sendBuffer, count, destRank, tag, comm);
01021 }
01022 
01023 template<>
01024 RCP<Teuchos::CommRequest<int> >
01025 isend (const ArrayRCP<const std::complex<float> >& sendBuffer,
01026        const int destRank,
01027        const int tag,
01028        const Comm<int>& comm)
01029 {
01030   return isendImpl<std::complex<float> > (sendBuffer, destRank, tag, comm);
01031 }
01032 #endif // TEUCHOS_HAVE_COMPLEX
01033 
01034 
01035 // Specialization for Ordinal=int and Packet=double.
01036 template<>
01037 void
01038 reduceAll<int, double> (const Comm<int>& comm,
01039                         const EReductionType reductType,
01040                         const int count,
01041                         const double sendBuffer[],
01042                         double globalReducts[])
01043 {
01044   TEUCHOS_COMM_TIME_MONITOR(
01045     "Teuchos::reduceAll<int, double> (" << count << ", "
01046     << toString (reductType) << ")"
01047     );
01048   reduceAllImpl<double> (comm, reductType, count, sendBuffer, globalReducts);
01049 }
01050 
01051 template<>
01052 RCP<Teuchos::CommRequest<int> >
01053 ireceive<int, double> (const Comm<int>& comm,
01054                        const ArrayRCP<double>& recvBuffer,
01055                        const int sourceRank)
01056 {
01057   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, double>");
01058   return ireceiveImpl<double> (comm, recvBuffer, sourceRank);
01059 }
01060 
01061 template<>
01062 RCP<Teuchos::CommRequest<int> >
01063 ireceive<int, double> (const ArrayRCP<double>& recvBuffer,
01064                        const int sourceRank,
01065                        const int tag,
01066                        const Comm<int>& comm)
01067 {
01068   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, double>");
01069   return ireceiveImpl<double> (recvBuffer, sourceRank, tag, comm);
01070 }
01071 
01072 template<>
01073 void
01074 send<int, double> (const Comm<int>& comm,
01075                    const int count,
01076                    const double sendBuffer[],
01077                    const int destRank)
01078 {
01079   return sendImpl<double> (comm, count, sendBuffer, destRank);
01080 }
01081 
01082 template<>
01083 void
01084 send<int, double> (const double sendBuffer[],
01085                    const int count,
01086                    const int destRank,
01087                    const int tag,
01088                    const Comm<int>& comm)
01089 {
01090   return sendImpl<double> (sendBuffer, count, destRank, tag, comm);
01091 }
01092 
01093 template<>
01094 RCP<Teuchos::CommRequest<int> >
01095 isend (const ArrayRCP<const double>& sendBuffer,
01096         const int destRank,
01097         const int tag,
01098         const Comm<int>& comm)
01099 {
01100   return isendImpl<double> (sendBuffer, destRank, tag, comm);
01101 }
01102 
01103 // Specialization for Ordinal=int and Packet=float.
01104 template<>
01105 void
01106 reduceAll<int, float> (const Comm<int>& comm,
01107                        const EReductionType reductType,
01108                        const int count,
01109                        const float sendBuffer[],
01110                        float globalReducts[])
01111 {
01112   TEUCHOS_COMM_TIME_MONITOR(
01113     "Teuchos::reduceAll<int, float> (" << count << ", "
01114     << toString (reductType) << ")"
01115     );
01116   reduceAllImpl<float> (comm, reductType, count, sendBuffer, globalReducts);
01117 }
01118 
01119 template<>
01120 RCP<Teuchos::CommRequest<int> >
01121 ireceive<int, float> (const Comm<int>& comm,
01122                       const ArrayRCP<float>& recvBuffer,
01123                       const int sourceRank)
01124 {
01125   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, float>");
01126   return ireceiveImpl<float> (comm, recvBuffer, sourceRank);
01127 }
01128 
01129 template<>
01130 RCP<Teuchos::CommRequest<int> >
01131 ireceive<int, float> (const ArrayRCP<float>& recvBuffer,
01132                       const int sourceRank,
01133                       const int tag,
01134                       const Comm<int>& comm)
01135 {
01136   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, float>");
01137   return ireceiveImpl<float> (recvBuffer, sourceRank, tag, comm);
01138 }
01139 
01140 template<>
01141 void
01142 send<int, float> (const Comm<int>& comm,
01143                   const int count,
01144                   const float sendBuffer[],
01145                   const int destRank)
01146 {
01147   return sendImpl<float> (comm, count, sendBuffer, destRank);
01148 }
01149 
01150 template<>
01151 void
01152 send<int, float> (const float sendBuffer[],
01153                   const int count,
01154                   const int destRank,
01155                   const int tag,
01156                   const Comm<int>& comm)
01157 {
01158   return sendImpl<float> (sendBuffer, count, destRank, tag, comm);
01159 }
01160 
01161 template<>
01162 RCP<Teuchos::CommRequest<int> >
01163 isend (const ArrayRCP<const float>& sendBuffer,
01164        const int destRank,
01165        const int tag,
01166        const Comm<int>& comm)
01167 {
01168   return isendImpl<float> (sendBuffer, destRank, tag, comm);
01169 }
01170 
01171 
01172 #ifdef TEUCHOS_HAVE_LONG_LONG_INT
01173 // Specialization for Ordinal=int and Packet=long long.
01174 template<>
01175 void
01176 gather<int, long long> (const long long sendBuf[],
01177                         const int sendCount,
01178                         long long recvBuf[],
01179                         const int recvCount,
01180                         const int root,
01181                         const Comm<int>& comm)
01182 {
01183   gatherImpl<long long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
01184 }
01185 
01186 template<>
01187 void
01188 gatherv<int, long long> (const long long sendBuf[],
01189                          const int sendCount,
01190                          long long recvBuf[],
01191                          const int recvCounts[],
01192                          const int displs[],
01193                          const int root,
01194                          const Comm<int>& comm)
01195 {
01196   gathervImpl<long long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
01197 }
01198 
01199 template<>
01200 void
01201 reduceAll<int, long long> (const Comm<int>& comm,
01202                            const EReductionType reductType,
01203                            const int count,
01204                            const long long sendBuffer[],
01205                            long long globalReducts[])
01206 {
01207   TEUCHOS_COMM_TIME_MONITOR(
01208     "Teuchos::reduceAll<int, long long> (" << count << ", "
01209     << toString (reductType) << ")"
01210     );
01211   reduceAllImpl<long long> (comm, reductType, count, sendBuffer, globalReducts);
01212 }
01213 
01214 template<>
01215 RCP<Teuchos::CommRequest<int> >
01216 ireceive<int, long long> (const Comm<int>& comm,
01217                           const ArrayRCP<long long>& recvBuffer,
01218                           const int sourceRank)
01219 {
01220   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long long>");
01221   return ireceiveImpl<long long> (comm, recvBuffer, sourceRank);
01222 }
01223 
01224 template<>
01225 RCP<Teuchos::CommRequest<int> >
01226 ireceive<int, long long> (const ArrayRCP<long long>& recvBuffer,
01227                           const int sourceRank,
01228                           const int tag,
01229                           const Comm<int>& comm)
01230 {
01231   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long long>");
01232   return ireceiveImpl<long long> (recvBuffer, sourceRank, tag, comm);
01233 }
01234 
01235 template<>
01236 void
01237 send<int, long long> (const Comm<int>& comm,
01238                       const int count,
01239                       const long long sendBuffer[],
01240                       const int destRank)
01241 {
01242   return sendImpl<long long> (comm, count, sendBuffer, destRank);
01243 }
01244 
01245 template<>
01246 void
01247 send<int, long long> (const long long sendBuffer[],
01248                       const int count,
01249                       const int destRank,
01250                       const int tag,
01251                       const Comm<int>& comm)
01252 {
01253   return sendImpl<long long> (sendBuffer, count, destRank, tag, comm);
01254 }
01255 
01256 template<>
01257 RCP<Teuchos::CommRequest<int> >
01258 isend (const ArrayRCP<const long long>& sendBuffer,
01259        const int destRank,
01260        const int tag,
01261        const Comm<int>& comm)
01262 {
01263   return isendImpl<long long> (sendBuffer, destRank, tag, comm);
01264 }
01265 
01266 // Specialization for Ordinal=int and Packet=unsigned long long.
01267 template<>
01268 void
01269 gather<int, unsigned long long> (const unsigned long long sendBuf[],
01270                                  const int sendCount,
01271                                  unsigned long long recvBuf[],
01272                                  const int recvCount,
01273                                  const int root,
01274                                  const Comm<int>& comm)
01275 {
01276   gatherImpl<unsigned long long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
01277 }
01278 
01279 template<>
01280 void
01281 gatherv<int, unsigned long long> (const unsigned long long sendBuf[],
01282                                   const int sendCount,
01283                                   unsigned long long recvBuf[],
01284                                   const int recvCounts[],
01285                                   const int displs[],
01286                                   const int root,
01287                                   const Comm<int>& comm)
01288 {
01289   gathervImpl<unsigned long long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
01290 }
01291 
01292 template<>
01293 void
01294 reduceAll<int, unsigned long long> (const Comm<int>& comm,
01295                                     const EReductionType reductType,
01296                                     const int count,
01297                                     const unsigned long long sendBuffer[],
01298                                     unsigned long long globalReducts[])
01299 {
01300   TEUCHOS_COMM_TIME_MONITOR(
01301     "Teuchos::reduceAll<int, unsigned long long> (" << count << ", "
01302     << toString (reductType) << ")"
01303     );
01304   reduceAllImpl<unsigned long long> (comm, reductType, count, sendBuffer, globalReducts);
01305 }
01306 
01307 template<>
01308 RCP<Teuchos::CommRequest<int> >
01309 ireceive<int, unsigned long long> (const Comm<int>& comm,
01310                                    const ArrayRCP<unsigned long long>& recvBuffer,
01311                                    const int sourceRank)
01312 {
01313   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long long>");
01314   return ireceiveImpl<unsigned long long> (comm, recvBuffer, sourceRank);
01315 }
01316 
01317 template<>
01318 RCP<Teuchos::CommRequest<int> >
01319 ireceive<int, unsigned long long> (const ArrayRCP<unsigned long long>& recvBuffer,
01320                                    const int sourceRank,
01321                                    const int tag,
01322                                    const Comm<int>& comm)
01323 {
01324   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long long>");
01325   return ireceiveImpl<unsigned long long> (recvBuffer, sourceRank, tag, comm);
01326 }
01327 
01328 template<>
01329 void
01330 send<int, unsigned long long> (const Comm<int>& comm,
01331                                const int count,
01332                                const unsigned long long sendBuffer[],
01333                                const int destRank)
01334 {
01335   return sendImpl<unsigned long long> (comm, count, sendBuffer, destRank);
01336 }
01337 
01338 template<>
01339 void
01340 send<int, unsigned long long> (const unsigned long long sendBuffer[],
01341                                const int count,
01342                                const int destRank,
01343                                const int tag,
01344                                const Comm<int>& comm)
01345 {
01346   return sendImpl<unsigned long long> (sendBuffer, count, destRank, tag, comm);
01347 }
01348 
01349 template<>
01350 RCP<Teuchos::CommRequest<int> >
01351 isend (const ArrayRCP<const unsigned long long>& sendBuffer,
01352        const int destRank,
01353        const int tag,
01354        const Comm<int>& comm)
01355 {
01356   return isendImpl<unsigned long long> (sendBuffer, destRank, tag, comm);
01357 }
01358 
01359 #endif // TEUCHOS_HAVE_LONG_LONG_INT
01360 
01361 
01362 // Specialization for Ordinal=int and Packet=long.
01363 template<>
01364 void
01365 gather<int, long> (const long sendBuf[],
01366                    const int sendCount,
01367                    long recvBuf[],
01368                    const int recvCount,
01369                    const int root,
01370                    const Comm<int>& comm)
01371 {
01372   gatherImpl<long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
01373 }
01374 
01375 template<>
01376 void
01377 gatherv<int, long> (const long sendBuf[],
01378                     const int sendCount,
01379                     long recvBuf[],
01380                     const int recvCounts[],
01381                     const int displs[],
01382                     const int root,
01383                     const Comm<int>& comm)
01384 {
01385   gathervImpl<long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
01386 }
01387 
01388 template<>
01389 void
01390 reduceAll<int, long> (const Comm<int>& comm,
01391                       const EReductionType reductType,
01392                       const int count,
01393                       const long sendBuffer[],
01394                       long globalReducts[])
01395 {
01396   TEUCHOS_COMM_TIME_MONITOR(
01397     "Teuchos::reduceAll<int, long> (" << count << ", "
01398     << toString (reductType) << ")"
01399     );
01400   reduceAllImpl<long> (comm, reductType, count, sendBuffer, globalReducts);
01401 }
01402 
01403 template<>
01404 RCP<Teuchos::CommRequest<int> >
01405 ireceive<int, long> (const Comm<int>& comm,
01406                      const ArrayRCP<long>& recvBuffer,
01407                      const int sourceRank)
01408 {
01409   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long>");
01410   return ireceiveImpl<long> (comm, recvBuffer, sourceRank);
01411 }
01412 
01413 template<>
01414 RCP<Teuchos::CommRequest<int> >
01415 ireceive<int, long> (const ArrayRCP<long>& recvBuffer,
01416                      const int sourceRank,
01417                      const int tag,
01418                      const Comm<int>& comm)
01419 {
01420   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long>");
01421   return ireceiveImpl<long> (recvBuffer, sourceRank, tag, comm);
01422 }
01423 
01424 template<>
01425 void
01426 send<int, long> (const Comm<int>& comm,
01427                  const int count,
01428                  const long sendBuffer[],
01429                  const int destRank)
01430 {
01431   return sendImpl<long> (comm, count, sendBuffer, destRank);
01432 }
01433 
01434 template<>
01435 void
01436 send<int, long> (const long sendBuffer[],
01437                  const int count,
01438                  const int destRank,
01439                  const int tag,
01440                  const Comm<int>& comm)
01441 {
01442   return sendImpl<long> (sendBuffer, count, destRank, tag, comm);
01443 }
01444 
01445 template<>
01446 RCP<Teuchos::CommRequest<int> >
01447 isend (const ArrayRCP<const long>& sendBuffer,
01448        const int destRank,
01449        const int tag,
01450        const Comm<int>& comm)
01451 {
01452   return isendImpl<long> (sendBuffer, destRank, tag, comm);
01453 }
01454 
01455 
01456 // Specialization for Ordinal=int and Packet=unsigned long.
01457 template<>
01458 void
01459 gather<int, unsigned long> (const unsigned long sendBuf[],
01460                             const int sendCount,
01461                             unsigned long recvBuf[],
01462                             const int recvCount,
01463                             const int root,
01464                             const Comm<int>& comm)
01465 {
01466   gatherImpl<unsigned long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
01467 }
01468 
01469 template<>
01470 void
01471 gatherv<int, unsigned long> (const unsigned long sendBuf[],
01472                              const int sendCount,
01473                              unsigned long recvBuf[],
01474                              const int recvCounts[],
01475                              const int displs[],
01476                              const int root,
01477                              const Comm<int>& comm)
01478 {
01479   gathervImpl<unsigned long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
01480 }
01481 
01482 template<>
01483 void
01484 reduceAll<int, unsigned long> (const Comm<int>& comm,
01485                                const EReductionType reductType,
01486                                const int count,
01487                                const unsigned long sendBuffer[],
01488                                unsigned long globalReducts[])
01489 {
01490   TEUCHOS_COMM_TIME_MONITOR(
01491     "Teuchos::reduceAll<int, unsigned long> (" << count << ", "
01492     << toString (reductType) << ")"
01493     );
01494   reduceAllImpl<unsigned long> (comm, reductType, count, sendBuffer, globalReducts);
01495 }
01496 
01497 template<>
01498 RCP<Teuchos::CommRequest<int> >
01499 ireceive<int, unsigned long> (const Comm<int>& comm,
01500                               const ArrayRCP<unsigned long>& recvBuffer,
01501                               const int sourceRank)
01502 {
01503   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long>");
01504   return ireceiveImpl<unsigned long> (comm, recvBuffer, sourceRank);
01505 }
01506 
01507 template<>
01508 RCP<Teuchos::CommRequest<int> >
01509 ireceive<int, unsigned long> (const ArrayRCP<unsigned long>& recvBuffer,
01510                               const int sourceRank,
01511                               const int tag,
01512                               const Comm<int>& comm)
01513 {
01514   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long>");
01515   return ireceiveImpl<unsigned long> (recvBuffer, sourceRank, tag, comm);
01516 }
01517 
01518 template<>
01519 void
01520 send<int, unsigned long> (const Comm<int>& comm,
01521                           const int count,
01522                           const unsigned long sendBuffer[],
01523                           const int destRank)
01524 {
01525   return sendImpl<unsigned long> (comm, count, sendBuffer, destRank);
01526 }
01527 
01528 template<>
01529 void
01530 send<int, unsigned long> (const unsigned long sendBuffer[],
01531                  const int count,
01532                  const int destRank,
01533                  const int tag,
01534                  const Comm<int>& comm)
01535 {
01536   return sendImpl<unsigned long> (sendBuffer, count, destRank, tag, comm);
01537 }
01538 
01539 template<>
01540 RCP<Teuchos::CommRequest<int> >
01541 isend (const ArrayRCP<const unsigned long>& sendBuffer,
01542        const int destRank,
01543        const int tag,
01544        const Comm<int>& comm)
01545 {
01546   return isendImpl<unsigned long> (sendBuffer, destRank, tag, comm);
01547 }
01548 
01549 // Specialization for Ordinal=int and Packet=int.
01550 template<>
01551 void
01552 gather<int, int> (const int sendBuf[],
01553                   const int sendCount,
01554                   int recvBuf[],
01555                   const int recvCount,
01556                   const int root,
01557                   const Comm<int>& comm)
01558 {
01559   gatherImpl<int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
01560 }
01561 
01562 template<>
01563 void
01564 gatherv<int, int> (const int sendBuf[],
01565                    const int sendCount,
01566                    int recvBuf[],
01567                    const int recvCounts[],
01568                    const int displs[],
01569                    const int root,
01570                    const Comm<int>& comm)
01571 {
01572   gathervImpl<int> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
01573 }
01574 
01575 template<>
01576 void
01577 reduceAll<int, int> (const Comm<int>& comm,
01578                      const EReductionType reductType,
01579                      const int count,
01580                      const int sendBuffer[],
01581                      int globalReducts[])
01582 {
01583   TEUCHOS_COMM_TIME_MONITOR(
01584     "Teuchos::reduceAll<int, int> (" << count << ", "
01585     << toString (reductType) << ")"
01586     );
01587   reduceAllImpl<int> (comm, reductType, count, sendBuffer, globalReducts);
01588 }
01589 
01590 template<>
01591 void
01592 reduceAllAndScatter<int, int> (const Comm<int>& comm,
01593                                const EReductionType reductType,
01594                                const int sendCount,
01595                                const int sendBuffer[],
01596                                const int recvCounts[],
01597                                int myGlobalReducts[])
01598 {
01599   reduceAllAndScatterImpl<int> (comm, reductType, sendCount, sendBuffer,
01600                                 recvCounts, myGlobalReducts);
01601 }
01602 
01603 template<>
01604 RCP<Teuchos::CommRequest<int> >
01605 ireceive<int, int> (const Comm<int>& comm,
01606                     const ArrayRCP<int>& recvBuffer,
01607                     const int sourceRank)
01608 {
01609   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, int>");
01610   return ireceiveImpl<int> (comm, recvBuffer, sourceRank);
01611 }
01612 
01613 template<>
01614 RCP<Teuchos::CommRequest<int> >
01615 ireceive<int, int> (const ArrayRCP<int>& recvBuffer,
01616                     const int sourceRank,
01617                     const int tag,
01618                     const Comm<int>& comm)
01619 {
01620   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, int>");
01621   return ireceiveImpl<int> (recvBuffer, sourceRank, tag, comm);
01622 }
01623 
01624 template<>
01625 void
01626 send<int, int> (const Comm<int>& comm,
01627                 const int count,
01628                 const int sendBuffer[],
01629                 const int destRank)
01630 {
01631   return sendImpl<int> (comm, count, sendBuffer, destRank);
01632 }
01633 
01634 template<>
01635 void
01636 send<int, int> (const int sendBuffer[],
01637                 const int count,
01638                 const int destRank,
01639                 const int tag,
01640                 const Comm<int>& comm)
01641 {
01642   return sendImpl<int> (sendBuffer, count, destRank, tag, comm);
01643 }
01644 
01645 template<>
01646 RCP<Teuchos::CommRequest<int> >
01647 isend (const ArrayRCP<const int>& sendBuffer,
01648        const int destRank,
01649        const int tag,
01650        const Comm<int>& comm)
01651 {
01652   return isendImpl<int> (sendBuffer, destRank, tag, comm);
01653 }
01654 
01655 // Specialization for Ordinal=int and Packet=unsigned int.
01656 template<>
01657 void
01658 gather<int, unsigned int> (const unsigned int sendBuf[],
01659                             const int sendCount,
01660                             unsigned int recvBuf[],
01661                             const int recvCount,
01662                             const int root,
01663                             const Comm<int>& comm)
01664 {
01665   gatherImpl<unsigned int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
01666 }
01667 
01668 template<>
01669 void
01670 gatherv<int, unsigned int> (const unsigned int sendBuf[],
01671                              const int sendCount,
01672                              unsigned int recvBuf[],
01673                              const int recvCounts[],
01674                              const int displs[],
01675                              const int root,
01676                              const Comm<int>& comm)
01677 {
01678   gathervImpl<unsigned int> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
01679 }
01680 
01681 template<>
01682 void
01683 reduceAll<int, unsigned int> (const Comm<int>& comm,
01684                               const EReductionType reductType,
01685                               const int count,
01686                               const unsigned int sendBuffer[],
01687                               unsigned int globalReducts[])
01688 {
01689   TEUCHOS_COMM_TIME_MONITOR(
01690     "Teuchos::reduceAll<int, unsigned int> (" << count << ", "
01691     << toString (reductType) << ")"
01692     );
01693   reduceAllImpl<unsigned int> (comm, reductType, count, sendBuffer, globalReducts);
01694 }
01695 
01696 template<>
01697 RCP<Teuchos::CommRequest<int> >
01698 ireceive<int, unsigned int> (const Comm<int>& comm,
01699                              const ArrayRCP<unsigned int>& recvBuffer,
01700                              const int sourceRank)
01701 {
01702   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned int>");
01703   return ireceiveImpl<unsigned int> (comm, recvBuffer, sourceRank);
01704 }
01705 
01706 template<>
01707 RCP<Teuchos::CommRequest<int> >
01708 ireceive<int, unsigned int> (const ArrayRCP<unsigned int>& recvBuffer,
01709                              const int sourceRank,
01710                              const int tag,
01711                              const Comm<int>& comm)
01712 {
01713   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned int>");
01714   return ireceiveImpl<unsigned int> (recvBuffer, sourceRank, tag, comm);
01715 }
01716 
01717 template<>
01718 void
01719 send<int, unsigned int> (const Comm<int>& comm,
01720                          const int count,
01721                          const unsigned int sendBuffer[],
01722                          const int destRank)
01723 {
01724   return sendImpl<unsigned int> (comm, count, sendBuffer, destRank);
01725 }
01726 
01727 template<>
01728 void
01729 send<int, unsigned int> (const unsigned int sendBuffer[],
01730                          const int count,
01731                          const int destRank,
01732                          const int tag,
01733                          const Comm<int>& comm)
01734 {
01735   return sendImpl<unsigned int> (sendBuffer, count, destRank, tag, comm);
01736 }
01737 
01738 template<>
01739 RCP<Teuchos::CommRequest<int> >
01740 isend (const ArrayRCP<const unsigned int>& sendBuffer,
01741        const int destRank,
01742        const int tag,
01743        const Comm<int>& comm)
01744 {
01745   return isendImpl<unsigned int> (sendBuffer, destRank, tag, comm);
01746 }
01747 
01748 
01749 // Specialization for Ordinal=int and Packet=short.
01750 template<>
01751 void
01752 gather<int, short> (const short sendBuf[],
01753                     const int sendCount,
01754                     short recvBuf[],
01755                     const int recvCount,
01756                     const int root,
01757                     const Comm<int>& comm)
01758 {
01759   gatherImpl<short> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
01760 }
01761 
01762 template<>
01763 void
01764 gatherv<int, short> (const short sendBuf[],
01765                      const int sendCount,
01766                      short recvBuf[],
01767                      const int recvCounts[],
01768                      const int displs[],
01769                      const int root,
01770                      const Comm<int>& comm)
01771 {
01772   gathervImpl<short> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
01773 }
01774 
01775 template<>
01776 void
01777 reduceAll<int, short> (const Comm<int>& comm,
01778                        const EReductionType reductType,
01779                        const int count,
01780                        const short sendBuffer[],
01781                        short globalReducts[])
01782 {
01783   TEUCHOS_COMM_TIME_MONITOR(
01784     "Teuchos::reduceAll<int, short> (" << count << ", "
01785     << toString (reductType) << ")"
01786     );
01787   reduceAllImpl<short> (comm, reductType, count, sendBuffer, globalReducts);
01788 }
01789 
01790 template<>
01791 RCP<Teuchos::CommRequest<int> >
01792 ireceive<int, short> (const Comm<int>& comm,
01793                       const ArrayRCP<short>& recvBuffer,
01794                       const int sourceRank)
01795 {
01796   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, short>");
01797   return ireceiveImpl<short> (comm, recvBuffer, sourceRank);
01798 }
01799 
01800 template<>
01801 RCP<Teuchos::CommRequest<int> >
01802 ireceive<int, short> (const ArrayRCP<short>& recvBuffer,
01803                       const int sourceRank,
01804                       const int tag,
01805                       const Comm<int>& comm)
01806 {
01807   TEUCHOS_COMM_TIME_MONITOR("ireceive<int, short>");
01808   return ireceiveImpl<short> (recvBuffer, sourceRank, tag, comm);
01809 }
01810 
01811 template<>
01812 void
01813 send<int, short> (const Comm<int>& comm,
01814                   const int count,
01815                   const short sendBuffer[],
01816                   const int destRank)
01817 {
01818   return sendImpl<short> (comm, count, sendBuffer, destRank);
01819 }
01820 
01821 template<>
01822 void
01823 send<int, short> (const short sendBuffer[],
01824                   const int count,
01825                   const int destRank,
01826                   const int tag,
01827                   const Comm<int>& comm)
01828 {
01829   return sendImpl<short> (sendBuffer, count, destRank, tag, comm);
01830 }
01831 
01832 template<>
01833 RCP<Teuchos::CommRequest<int> >
01834 isend (const ArrayRCP<const short>& sendBuffer,
01835        const int destRank,
01836        const int tag,
01837        const Comm<int>& comm)
01838 {
01839   return isendImpl<short> (sendBuffer, destRank, tag, comm);
01840 }
01841 
01842 // mfh 18 Oct 2012: The specialization for Packet=char seems to be
01843 // causing problems such as the following:
01844 //
01845 // http://testing.sandia.gov/cdash/testDetails.php?test=9909246&build=747699
01846 //
01847 // I am disabling it for now.  This should revert back to the old
01848 // behavior for Packet=char.  That should fix the Tpetra errors, since
01849 // many Tpetra objects inherit from DistObject<char, ...>.
01850 #if 0
01851 // Specialization for Ordinal=int and Packet=char.
01852 template<>
01853 void
01854 reduceAll<int, char> (const Comm<int>& comm,
01855                       const EReductionType reductType,
01856                       const int count,
01857                       const char sendBuffer[],
01858                       char globalReducts[])
01859 {
01860   TEUCHOS_COMM_TIME_MONITOR(
01861     "Teuchos::reduceAll<int, char> (" << count << ", "
01862     << toString (reductType) << ")"
01863     );
01864   reduceAllImpl<char> (comm, reductType, count, sendBuffer, globalReducts);
01865 }
01866 #endif // 0
01867 
01868 } // namespace Teuchos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines