PlayaVectorOpsImpl.hpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                 Playa: Programmable Linear Algebra
00005 //                 Copyright 2012 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
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 Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 #ifndef PLAYA_VECTOROPSIMPL_HPP
00043 #define PLAYA_VECTOROPSIMPL_HPP
00044 
00045 #include "PlayaDefs.hpp"
00046 #include "PlayaVectorImpl.hpp"
00047 #include "PlayaVectorOpsDecl.hpp"
00048 #include "PlayaMPIComm.hpp"
00049 #include "Teuchos_RCP.hpp"
00050 
00051 namespace PlayaFunctors
00052 {
00053 template <class Scalar> class BoundedMinLocFunctor;
00054 
00055 template <class Scalar> class BoundedMaxLocFunctor;
00056 
00057 template <class Scalar> class Norm2Dist;
00058 
00059 template <class Scalar> class Norm1Dist;
00060 
00061 template <class Scalar> class NormInfDist;
00062 }
00063 
00064 namespace Playa
00065 {
00066 
00067 using namespace PlayaFunctors;
00068 
00069 /* */
00070 template <class Scalar> inline
00071 Scalar minloc(const Vector<Scalar>& x, int& gni)
00072 {
00073   return minlocWithBound(-HUGE_VAL, x, gni);
00074 }
00075 
00076 /* */
00077 template <class Scalar> inline
00078 Scalar maxloc(const Vector<Scalar>& x, int& gni)
00079 {
00080   return maxlocWithBound(-HUGE_VAL, x, gni);
00081 }
00082 
00083 /* */
00084 template <class Scalar> inline
00085 Scalar minlocWithBound(const Scalar& lowerBound, 
00086   const Vector<Scalar>& x, int& gni)
00087 {
00088   IndexedValue<Scalar> y = 
00089     x.applyUnaryReductionFunctor(BoundedMinLocFunctor<Scalar>(x.comm(), lowerBound, x.space().baseGlobalNaturalIndex()));
00090   gni = y.where;
00091   return y.what;
00092 }
00093 
00094 /* */
00095 template <class Scalar> inline
00096 Scalar maxlocWithBound(const Scalar& upperBound, 
00097   const Vector<Scalar>& x, int& gni)
00098 {
00099   IndexedValue<Scalar> y = 
00100     x.applyUnaryReductionFunctor(BoundedMaxLocFunctor<Scalar>(x.comm(), upperBound, x.space().baseGlobalNaturalIndex()));
00101   gni = y.where;
00102   return y.what;
00103 }
00104 
00105 
00106 /* */
00107 template <class Scalar>
00108 Scalar norm2Dist(const Vector<Scalar>& x, const Vector<Scalar>& y)
00109 {
00110   return x.applyBinaryReductionFunctor(
00111     PlayaFunctors::Norm2Dist<Scalar>(x.comm()), y);
00112 }
00113 
00114 /* */
00115 template <class Scalar>
00116 Scalar norm1Dist(const Vector<Scalar>& x, const Vector<Scalar>& y)
00117 {
00118   return x.applyBinaryReductionFunctor(
00119     PlayaFunctors::Norm1Dist<Scalar>(x.comm()), y);
00120 }
00121 
00122 /* */
00123 template <class Scalar>
00124 Scalar normInfDist(const Vector<Scalar>& x, const Vector<Scalar>& y)
00125 {
00126   return x.applyBinaryReductionFunctor(
00127     PlayaFunctors::NormInfDist<Scalar>(x.comm()), y);
00128 }
00129 
00130 /** \relates Vector \brief Compute the Euclidean norm of a vector */
00131 template <class Scalar>
00132 Scalar norm2(const Vector<Scalar>& x) {return x.norm2();}
00133 
00134 /** \relates Vector \brief Compute the one-norm of a vector */
00135 template <class Scalar>
00136 Scalar norm1(const Vector<Scalar>& x) {return x.norm1();}
00137 
00138 /** \relates Vector \brief Compute the infinity norm of a vector */
00139 template <class Scalar>
00140 Scalar normInf(const Vector<Scalar>& x) {return x.normInf();}
00141 
00142 } // end namespace Playa
00143 
00144 namespace PlayaFunctors
00145 {
00146 
00147 
00148 using namespace Playa;
00149 
00150 /** \brief Find minimum element above a lower bound, returning value and
00151  * location */
00152 template <class Scalar>
00153 class BoundedMinLocFunctor : public ReductionFunctorBase<Scalar>
00154 {
00155 public:
00156   /** */
00157   BoundedMinLocFunctor(const MPIComm& comm, const Scalar& bound,
00158     int baseGNI)
00159     : ReductionFunctorBase<Scalar>(comm), min_(), 
00160       bound_(bound), baseGNI_(baseGNI)
00161     {
00162       min_.what = HUGE_VAL;
00163       min_.where = -1;
00164     }
00165 
00166   /** */
00167   void step(int i, const Scalar& x) const 
00168     {
00169       if (x < min_.what && x > bound_) 
00170       {
00171         min_.what = x;
00172         min_.where = i;
00173       }
00174     }
00175 
00176   /** */
00177   void postProc() const 
00178     {
00179       min_.where += baseGNI_;
00180 
00181       IndexedValue<Scalar> out = min_;
00182 
00183       this->comm().allReduce(&min_, &out, 1, MPIDataType::doubleIntPairType(), 
00184         MPIOp::minlocOp());
00185       min_ = out;
00186     }
00187 
00188   /** */
00189   IndexedValue<Scalar> result() const 
00190     {
00191       return min_;
00192     }
00193 
00194   /** */
00195   std::string description() const {return "MinLoc()";}
00196 
00197 private:
00198   MPIComm comm_;
00199   mutable IndexedValue<Scalar> min_;
00200   Scalar bound_;
00201   int baseGNI_;
00202 };
00203 
00204 
00205 /** \brief Find maximum element below an upper bound, returning value and
00206  * location */
00207 template <class Scalar>
00208 class BoundedMaxLocFunctor : public ReductionFunctorBase<Scalar>
00209 {
00210 public:
00211   /** */
00212   BoundedMaxLocFunctor(const MPIComm& comm, const Scalar& bound,
00213     int baseGNI)
00214     : ReductionFunctorBase<Scalar>(comm), max_(), 
00215       bound_(bound), baseGNI_(baseGNI)
00216     {
00217       max_.what = -HUGE_VAL;
00218       max_.where = -1;
00219     }
00220 
00221   /** */
00222   void step(int i, const Scalar& x) const 
00223     {
00224       if (x > max_.what && x < bound_) 
00225       {
00226         max_.what = x;
00227         max_.where = i;
00228       }
00229     }
00230 
00231   /** */
00232   void postProc() const 
00233     {
00234       max_.where += baseGNI_;
00235 
00236       IndexedValue<Scalar> out = max_;
00237 
00238       this->comm().allReduce(&max_, &out, 1, MPIDataType::doubleIntPairType(), 
00239         MPIOp::minlocOp());
00240       max_ = out;
00241     }
00242 
00243   /** */
00244   IndexedValue<Scalar> result() const 
00245     {
00246       return max_;
00247     }
00248 
00249   /** */
00250   std::string description() const {return "MinLoc()";}
00251 
00252 private:
00253   MPIComm comm_;
00254   mutable IndexedValue<Scalar> max_;
00255   Scalar bound_;
00256   int baseGNI_;
00257 };
00258 
00259 
00260 
00261 /** \brief Euclidean distance between two vectors */
00262 template <class Scalar>
00263 class Norm2Dist : public ReductionFunctorBase<Scalar>
00264 {
00265 public:
00266   Norm2Dist(const MPIComm& comm)
00267     : ReductionFunctorBase<Scalar>(comm), val_(0.0) {}
00268 
00269   void step(int i, const Scalar& x, const Scalar& y) const 
00270     {
00271       Scalar d = x-y;
00272       val_ += d*d;
00273     }
00274 
00275   void postProc() const 
00276     {
00277       Scalar final = val_;
00278       this->comm().allReduce(&val_, &final, 1, MPIDataType::doubleType(), MPIOp::sumOp());
00279       val_ = final;
00280     }
00281 
00282   Scalar result() const 
00283     {
00284       return ::sqrt(val_);
00285     }
00286 
00287   /** */
00288   std::string description() const {return "Norm2Dist()";}
00289 
00290 private:
00291   mutable Scalar val_;
00292 };
00293 
00294 
00295 
00296 /** \brief One-norm distance between two vectors */
00297 template <class Scalar>
00298 class Norm1Dist : public ReductionFunctorBase<Scalar>
00299 {
00300 public:
00301   Norm1Dist(const MPIComm& comm)
00302     : ReductionFunctorBase<Scalar>(comm), val_(0.0) {}
00303 
00304   void step(int i, const Scalar& x, const Scalar& y) const 
00305     {
00306       Scalar d = x-y;
00307       val_ += ::fabs(d);
00308     }
00309 
00310   void postProc() const 
00311     {
00312       Scalar final = val_;
00313       this->comm().allReduce(&val_, &final, 1, MPIDataType::doubleType(), MPIOp::sumOp());
00314       val_ = final;
00315     }
00316 
00317   Scalar result() const 
00318     {
00319       return val_;
00320     }
00321 
00322   /** */
00323   std::string description() const {return "Norm1Dist()";}
00324 
00325 private:
00326   mutable Scalar val_;
00327 };
00328 
00329 /** \brief Infinity-norm distance between two vectors */
00330 template <class Scalar>
00331 class NormInfDist : public ReductionFunctorBase<Scalar>
00332 {
00333 public:
00334   NormInfDist(const MPIComm& comm)
00335     : ReductionFunctorBase<Scalar>(comm), val_(0.0) {}
00336 
00337   void step(int i, const Scalar& x, const Scalar& y) const 
00338     {
00339       Scalar d = ::fabs(x-y);
00340       if (d > val_) val_ = d;
00341     }
00342 
00343   void postProc() const 
00344     {
00345       Scalar final = val_;
00346       this->comm().allReduce(&val_, &final, 1, MPIDataType::doubleType(), MPIOp::maxOp());
00347       val_ = final;
00348     }
00349 
00350   Scalar result() const 
00351     {
00352       return val_;
00353     }
00354 
00355   /** */
00356   std::string description() const {return "NormInfDist()";}
00357 
00358 private:
00359   mutable Scalar val_;
00360 };
00361 
00362 
00363 /** \brief Specify return type of BoundedMinLocFunctor */
00364 template <class Scalar>
00365 class VectorFunctorTraits<Scalar, BoundedMinLocFunctor<Scalar> >
00366 {
00367 public:
00368   typedef IndexedValue<Scalar> ReturnType ;
00369 };
00370 
00371 
00372 /** \brief Specify return type of BoundedMaxLocFunctor */
00373 template <class Scalar>
00374 class VectorFunctorTraits<Scalar, BoundedMaxLocFunctor<Scalar> >
00375 {
00376 public:
00377   typedef IndexedValue<Scalar> ReturnType ;
00378 };
00379 
00380   
00381 }
00382 
00383 #endif

Site Contact