PlayaVectorImpl.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_VECTORIMPL_HPP
00043 #define PLAYA_VECTORIMPL_HPP
00044 
00045 
00046 #include "PlayaVectorDecl.hpp"
00047 #include "PlayaBlockVectorBaseDecl.hpp"
00048 #include "PlayaVectorFunctorsImpl.hpp"
00049 #include "PlayaSingleChunkVector.hpp"
00050 #include "PlayaLoadableVector.hpp"
00051 #include "PlayaPrintable.hpp"
00052 #include "PlayaExceptions.hpp"
00053 #include "PlayaGeneralizedIndex.hpp"
00054 #include "PlayaOut.hpp"
00055 #include "Teuchos_StrUtils.hpp"
00056 #include "PlayaTabs.hpp"
00057 #include "PlayaDebug.hpp"
00058 
00059 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00060 #include "PlayaVectorSpaceImpl.hpp"
00061 #include "PlayaBlockIteratorImpl.hpp"
00062 #endif
00063 
00064 
00065 
00066 extern "C"
00067 {
00068 void daxpy_(int*, double*, double*, int*, double*, int*);
00069 }
00070 
00071 
00072 namespace Playa
00073 {
00074 using Playa::Out;
00075 using Playa::Tabs;
00076 using Playa::Printable;
00077 
00078 
00079 
00080 
00081 //===========================================================================
00082 template <class Scalar> 
00083 Vector<Scalar>& Vector<Scalar>::operator+=(const Vector<Scalar>& other)
00084 {
00085   return update(1.0, other, 1.0);
00086 }  
00087 
00088 
00089 
00090 //===========================================================================
00091 template <class Scalar> 
00092 Vector<Scalar>& Vector<Scalar>::operator-=(const Vector<Scalar>& other)
00093 {
00094   return update(-1.0, other, 1.0);
00095 }  
00096 
00097 
00098 //===========================================================================
00099 template <class Scalar> 
00100 Vector<Scalar>& Vector<Scalar>::operator*=(const Scalar& a)
00101 {
00102   return scale(a);
00103 }  
00104 
00105 //===========================================================================
00106 template <class Scalar> 
00107 Vector<Scalar>& Vector<Scalar>::operator/=(const Scalar& a)
00108 {
00109   return scale(1.0/a);
00110 }  
00111 
00112 
00113 //===========================================================================
00114 template <class Scalar> 
00115 int Vector<Scalar>::numBlocks() const 
00116 {
00117   return this->ptr()->numBlocks();
00118 }  
00119 
00120 
00121 //===========================================================================
00122 template <class Scalar> 
00123 void Vector<Scalar>::setBlock(int i, const Vector<Scalar>& v)
00124 {
00125   BlockVectorBase<Scalar>* bv = 
00126     dynamic_cast<BlockVectorBase<Scalar>* >(this->ptr().get());
00127   TEUCHOS_TEST_FOR_EXCEPTION(bv == 0, std::runtime_error,
00128     "setBlock() called on a vector is not a block vector");
00129   bv->setBlock(i, v);
00130 }  
00131 
00132 
00133 //===========================================================================
00134 template <class Scalar> 
00135 const Vector<Scalar>& Vector<Scalar>::getBlock(int i) const
00136 {
00137   const BlockVectorBase<Scalar>* bv = 
00138     dynamic_cast<const BlockVectorBase<Scalar>* >(this->ptr().get());
00139   if (bv==0 && numBlocks()==1) return *this;
00140 
00141   TEUCHOS_TEST_FOR_EXCEPTION(bv == 0, std::runtime_error,
00142     "getBlock() called on a vector is not a block vector");
00143   return bv->getBlock(i);
00144 }
00145 
00146 //===========================================================================
00147 template <class Scalar> 
00148 Vector<Scalar> Vector<Scalar>::getNonConstBlock(int i)
00149 {
00150   BlockVectorBase<Scalar>* bv = 
00151     dynamic_cast<BlockVectorBase<Scalar>* >(this->ptr().get());
00152   if (bv==0 && numBlocks()==1) return *this;
00153 
00154   TEUCHOS_TEST_FOR_EXCEPTION(bv == 0, std::runtime_error,
00155     "getBlock() called on a vector is not a block vector");
00156   return bv->getNonConstBlock(i);
00157 }
00158 
00159 
00160 //========================================================================
00161 template <class Scalar> inline
00162 const Vector<Scalar>& Vector<Scalar>
00163 ::getBlock(const BlockIterator<Scalar>& b) const
00164 {
00165   /* Check that the block iterator is valid */
00166   TEUCHOS_TEST_FOR_EXCEPTION(b.atEnd(), RuntimeError, 
00167     "Attempt to use a block iterator that's run off end");
00168 
00169   return this->getBlock(b.blockIndex());
00170 }
00171 
00172 
00173 
00174 //========================================================================
00175 template <class Scalar> inline
00176 Vector<Scalar> Vector<Scalar>
00177 ::getNonConstBlock(const BlockIterator<Scalar>& b)
00178 {
00179   /* Check that the block iterator is valid */
00180   TEUCHOS_TEST_FOR_EXCEPTION(b.atEnd(), RuntimeError, 
00181     "Attempt to use a block iterator that's run off end");
00182 
00183   return this->getNonConstBlock(b.blockIndex());
00184 }
00185 
00186 
00187 //========================================================================
00188 template <class Scalar> inline
00189 const Vector<Scalar>& Vector<Scalar>
00190 ::getBlock(const std::deque<int>& b) const
00191 {
00192   /* Check that the block iterator is valid */
00193   TEUCHOS_TEST_FOR_EXCEPTION(b.size()==0, RuntimeError, 
00194     "Attempt to use an empty block iterator");
00195   
00196   if (b.size()==1) 
00197   {
00198     return this->getBlock(b.front());
00199   }
00200 
00201   int b0 = b.front();
00202   std::deque<int> tmp = b;
00203   tmp.pop_front();
00204   return this->getBlock(b0).getBlock(tmp);
00205 }
00206 
00207 //========================================================================
00208 template <class Scalar> inline
00209 Vector<Scalar> Vector<Scalar>
00210 ::getNonConstBlock(const std::deque<int>& b) 
00211 {
00212   /* Check that the block iterator is valid */
00213   TEUCHOS_TEST_FOR_EXCEPTION(b.size()==0, RuntimeError, 
00214     "Attempt to use an empty block iterator");
00215   
00216   if (b.size()==1) 
00217   {
00218     return this->getNonConstBlock(b.front());
00219   }
00220 
00221   int b0 = b.front();
00222   std::deque<int> tmp = b;
00223   tmp.pop_front();
00224   return this->getNonConstBlock(b0).getNonConstBlock(tmp);
00225 }
00226 
00227 //===========================================================================
00228 template <class Scalar> 
00229 ConstDataChunk<Scalar> Vector<Scalar>::nextConstChunk() const
00230 {
00231   return this->ptr()->nextConstChunk();
00232 }
00233 
00234 //===========================================================================
00235 template <class Scalar> 
00236 NonConstDataChunk<Scalar> Vector<Scalar>::nextChunk() 
00237 {
00238   return this->ptr()->nextChunk();
00239 }
00240 
00241 
00242 //===========================================================================
00243 template <class Scalar> 
00244 bool Vector<Scalar>::hasMoreChunks() const 
00245 {
00246   return this->ptr()->hasMoreChunks();
00247 }
00248 
00249 //===========================================================================
00250 template <class Scalar> 
00251 void Vector<Scalar>::rewind() const
00252 {
00253   return this->ptr()->rewind();
00254 }
00255 
00256 
00257 
00258 //===========================================================================
00259 
00260 template <class Scalar> 
00261 void Vector<Scalar>::print(std::ostream& os) const 
00262 {
00263   const Printable* p = 
00264     dynamic_cast<const Printable* >(this->ptr().get());
00265   if (false && p != 0)
00266   {
00267     p->print(os);
00268     return;
00269   }
00270   else
00271   {
00272     Tabs tab(0);
00273     int np = this->comm().getNProc();
00274     int rank = this->comm().getRank();
00275     if (rank==0) 
00276     {
00277       os << tab << this->description() << std::endl;
00278     }
00279     this->comm().synchronize();        
00280     
00281     os << tab << "rank= " << std::setw(10) << rank << " base GNI=" 
00282        << std::setw(10) << this->space().baseGlobalNaturalIndex() 
00283        << " local size=" << std::setw(10) 
00284        << this->space().numLocalElements() << std::endl; 
00285     for (BlockIterator<Scalar> b=this->space().beginBlock(); 
00286          b!=this->space().endBlock(); b++)
00287     {
00288       Tabs tab1;
00289       this->comm().synchronize();        
00290       if (rank==0 && this->numBlocks()>1)
00291         os << tab1 << "Block=" << b << std::endl;
00292       for (int r=0; r<np; r++)
00293       {
00294         Tabs tab2;
00295         this->comm().synchronize();        
00296         if (rank != r) continue;
00297         if (np > 1) os << tab2 << "Processor=" << r << std::endl;        
00298     
00299         const Vector<Scalar>& xBlock = this->getBlock(b);        
00300         os << tab2 << "rank= " << rank << " base GNI=" 
00301            << xBlock.space().baseGlobalNaturalIndex() << std::endl; 
00302 
00303         int low = xBlock.space().baseGlobalNaturalIndex();
00304         while(xBlock.hasMoreChunks())
00305         {
00306           Tabs tab3;
00307           ConstDataChunk<Scalar> myChunk = xBlock.nextConstChunk();
00308           const Scalar* me = myChunk.values();
00309           for (int i=0; i<myChunk.size(); i++)
00310           {
00311             os << tab3 << std::setw(10) << low+i << " " << std::setw(20)
00312                << me[i] << std::endl;
00313           }
00314         }
00315         for(int i=0; i<6; i++)
00316         {
00317           this->comm().synchronize();        
00318         }
00319       }
00320     }
00321     
00322     this->rewind();
00323   }
00324 }
00325 
00326 template <class Scalar> 
00327 std::string Vector<Scalar>::description() const 
00328 {
00329   const Describable* d = 
00330     dynamic_cast<const Describable* >(this->ptr().get());
00331   if (d != 0)
00332   {
00333     return d->description();
00334   }
00335   return "Vector[type=unknown, dim=" + Teuchos::toString(dim()) + "]";
00336 }
00337 
00338   
00339 
00340 //===========================================================================
00341 
00342 template <class Scalar>
00343 template <class UF> inline
00344 Vector<Scalar>& Vector<Scalar>::applyUnaryFunctor(const UF& func) 
00345 {
00346   TimeMonitor t(*opTimer());
00347 
00348   if (this->numBlocks() > 1)
00349   {
00350     for (int b=0; b<numBlocks(); b++)
00351     {
00352       Vector<Scalar> xBlock = this->getNonConstBlock(b);
00353       xBlock.applyUnaryFunctor(func);
00354     }
00355   }
00356   else
00357   {
00358     while(this->hasMoreChunks())
00359     {
00360       NonConstDataChunk<Scalar> myChunk = this->nextChunk();
00361       Scalar* me = myChunk.values();
00362       for (int i=0; i<myChunk.size(); i++)
00363       {
00364         me[i] = func(me[i]);
00365       }
00366     }
00367   }
00368 
00369   this->rewind();
00370 
00371   return *this;
00372 }
00373 
00374 //===========================================================================
00375 
00376 template <class Scalar>
00377 template <class UF> inline
00378 Vector<Scalar>& Vector<Scalar>::acceptUnaryFunctor(const UF& func,
00379   const Vector<Scalar>& other) 
00380 {
00381   TimeMonitor t(*opTimer());
00382 
00383   TEUCHOS_TEST_FOR_EXCEPTION(!this->space().isCompatible(other.space()),
00384     std::runtime_error,
00385     "Spaces this=" << this->space() << " and other="
00386     << other.space() << " are not compatible in unary accept-operation "
00387     << func.description());
00388 
00389   if (this->numBlocks() > 1)
00390   {
00391     for (int b=0; b<this->numBlocks(); b++)
00392     {
00393       Vector<Scalar> myBlock = this->getNonConstBlock(b);
00394       Vector<Scalar> yourBlock = other.getBlock(b);
00395       myBlock.acceptUnaryFunctor(func, yourBlock);
00396     }
00397   }
00398   else
00399   {
00400     while(this->hasMoreChunks())
00401     {
00402       NonConstDataChunk<Scalar> myChunk = this->nextChunk();
00403       ConstDataChunk<Scalar> yourChunk = other.nextConstChunk();
00404       Scalar* me = myChunk.values();
00405       const Scalar* you = yourChunk.values();
00406       for (int i=0; i<myChunk.size(); i++)
00407       {
00408         me[i] = func(you[i]);
00409       }
00410     }
00411     other.rewind();
00412     this->rewind();
00413   }
00414 
00415   return *this;
00416 }
00417 
00418 //===========================================================================
00419 
00420 template <class Scalar>
00421 template <class VF> inline
00422 Vector<Scalar>& Vector<Scalar>::applyBinaryFunctor(const VF& func,
00423   const Vector<Scalar>& other) 
00424 {
00425   TimeMonitor t(*opTimer());
00426 
00427   TEUCHOS_TEST_FOR_EXCEPTION(!this->space().isCompatible(other.space()),
00428     std::runtime_error,
00429     "Spaces this=" << this->space() << " and other="
00430     << other.space() << " are not compatible in binary operation "
00431     << func.description());
00432 
00433   if (this->numBlocks() > 1)
00434   {
00435     for (int b=0; b<this->numBlocks(); b++)
00436     {
00437       Vector<Scalar> myBlock = this->getNonConstBlock(b);
00438       Vector<Scalar> yourBlock = other.getBlock(b);
00439       myBlock.applyBinaryFunctor(func, yourBlock);
00440     }
00441   }
00442   else
00443   {
00444     while(this->hasMoreChunks())
00445     {
00446       NonConstDataChunk<Scalar> myChunk = this->nextChunk();
00447       ConstDataChunk<Scalar> yourChunk = other.nextConstChunk();
00448       Scalar* me = myChunk.values();
00449       const Scalar* you = yourChunk.values();
00450       for (int i=0; i<myChunk.size(); i++)
00451       {
00452         me[i] = func(me[i], you[i]);
00453       }
00454     }
00455     other.rewind();
00456     this->rewind();
00457   }
00458 
00459   return *this;
00460 }
00461 
00462 //===========================================================================
00463 template <class Scalar> 
00464 template <class VF> inline
00465 Vector<Scalar>& Vector<Scalar>::applyTernaryFunctor(
00466   const VF& func,
00467   const Vector<Scalar>& y, 
00468   const Vector<Scalar>& z)
00469 {
00470   TimeMonitor t(*opTimer());
00471 
00472   TEUCHOS_TEST_FOR_EXCEPTION(!this->space().isCompatible(y.space())
00473     || !this->space().isCompatible(z.space()),
00474     std::runtime_error,
00475     "Spaces this=" << this->space() << ", Y="
00476     << y.space() << " and Z=" << z.space()
00477     << " are not compatible in ternary operation "
00478     << func.description());
00479 
00480   if (this->numBlocks() > 1)
00481   {
00482     for (int b=0; b<this->numBlocks(); b++)
00483     {
00484       Vector<Scalar> xBlock = this->getNonConstBlock(b);
00485       Vector<Scalar> yBlock = y.getBlock(b);
00486       Vector<Scalar> zBlock = z.getBlock(b);
00487       xBlock.applyTernaryFunctor(func, yBlock, zBlock);
00488     }
00489   }
00490   else
00491   {
00492     while(this->hasMoreChunks())
00493       {
00494         NonConstDataChunk<Scalar> xChunk = this->nextChunk();
00495         ConstDataChunk<Scalar> yChunk = y.nextConstChunk();
00496         ConstDataChunk<Scalar> zChunk = z.nextConstChunk();
00497         Scalar* xv = xChunk.values();
00498         const Scalar* yv = yChunk.values();
00499         const Scalar* zv = zChunk.values();
00500         for (int i=0; i<xChunk.size(); i++)
00501         {
00502           xv[i] = func(xv[i], yv[i], zv[i]);
00503         }
00504       }
00505     this->rewind();
00506     y.rewind();
00507     z.rewind();
00508   }
00509   return *this;
00510 }
00511 
00512 
00513 
00514 //===========================================================================
00515 
00516 template <class Scalar>
00517 template <class RF> inline
00518 typename PlayaFunctors::VectorFunctorTraits<Scalar, RF>::ReturnType
00519 Vector<Scalar>::applyUnaryReductionFunctor(const RF& func) const 
00520 {
00521   TimeMonitor t(*opTimer());
00522 
00523   for (BlockIterator<Scalar> b=this->space().beginBlock(); b!=this->space().endBlock(); b++)
00524   {
00525     Vector<Scalar> xBlock = this->getBlock(b);
00526     while(xBlock.hasMoreChunks())
00527     {
00528       ConstDataChunk<Scalar> myChunk = xBlock.nextConstChunk();
00529       const Scalar* me = myChunk.values();
00530       for (int i=0; i<myChunk.size(); i++)
00531       {
00532         func.step(i, me[i]);
00533       }
00534     }
00535   }
00536 
00537   func.postProc();
00538   this->rewind();
00539 
00540   return func.result();
00541 }
00542 
00543 
00544 //===========================================================================
00545 
00546 template <class Scalar>
00547 template <class RF> inline
00548 typename PlayaFunctors::VectorFunctorTraits<Scalar, RF>::ReturnType
00549 Vector<Scalar>::applyBinaryReductionFunctor(const RF& func, const Vector<Scalar>& y) const 
00550 {
00551   TimeMonitor t(*opTimer());
00552 
00553   TEUCHOS_TEST_FOR_EXCEPTION(!this->space().isCompatible(y.space()),
00554     std::runtime_error,
00555     "Spaces this=" << this->space() << " and other="
00556     << y.space() << " are not compatible in binary reduction operation "
00557     << func.description());
00558 
00559   for (BlockIterator<Scalar> b=this->space().beginBlock(); b!=this->space().endBlock(); b++)
00560   {
00561     Vector<Scalar> xBlock = this->getBlock(b);
00562     Vector<Scalar> yBlock = y.getBlock(b);
00563     while(xBlock.hasMoreChunks())
00564     {
00565       ConstDataChunk<Scalar> xChunk = xBlock.nextConstChunk();
00566       ConstDataChunk<Scalar> yChunk = yBlock.nextConstChunk();
00567       const Scalar* me = xChunk.values();
00568       const Scalar* you = yChunk.values();
00569       for (int i=0; i<xChunk.size(); i++)
00570       {
00571         func.step(i, me[i], you[i]);
00572       }
00573     }
00574   }
00575 
00576   func.postProc();
00577   this->rewind();
00578   y.rewind();
00579 
00580   return func.result();
00581 }
00582 
00583 
00584 //===========================================================================
00585 template <class Scalar> inline 
00586 Vector<Scalar>& Vector<Scalar>::scale(const Scalar& alpha)
00587 {
00588   return applyUnaryFunctor(PlayaFunctors::ScalarMult<Scalar>(alpha));
00589 }
00590 
00591 //===========================================================================
00592 template <class Scalar> inline 
00593 Vector<Scalar>& Vector<Scalar>::selfReciprocal()
00594 {
00595   return applyUnaryFunctor(PlayaFunctors::Reciprocal<Scalar>());
00596 }
00597 
00598 
00599 //===========================================================================
00600 template <class Scalar> inline 
00601 Vector<Scalar>& Vector<Scalar>::selfAbs()
00602 {
00603   return applyUnaryFunctor(PlayaFunctors::Abs<Scalar>());
00604 }
00605 
00606 
00607 //===========================================================================
00608 template <class Scalar> inline 
00609 Vector<Scalar>& Vector<Scalar>::randomize()
00610 {
00611   return applyUnaryFunctor(PlayaFunctors::Random<Scalar>());
00612 }
00613 
00614 
00615 //===========================================================================
00616 template <class Scalar> inline 
00617 Vector<Scalar>& Vector<Scalar>::update(const Scalar& alpha, 
00618   const Vector<Scalar>& other, const Scalar& gamma)
00619 {
00620   this->ptr()->update(alpha, other.ptr().get(), gamma);
00621   return *this;
00622 }
00623 
00624 
00625 //===========================================================================
00626 template <class Scalar> inline 
00627 Vector<Scalar>& Vector<Scalar>::acceptCopyOf(const Vector<Scalar>& x)
00628 {
00629   if (this->ptr().get()==0 || !this->space().isCompatible(x.space()) )
00630   {
00631     this->ptr() = x.space().createMember().ptr();
00632   }
00633   return acceptUnaryFunctor(PlayaFunctors::Identity<Scalar>(), x);
00634 }
00635 
00636 template <class Scalar> inline 
00637 Vector<Scalar> Vector<Scalar>::copy() const 
00638 {
00639   Vector<Scalar> rtn = space().createMember();
00640   rtn.acceptCopyOf(*this);
00641   return rtn;
00642 }
00643 
00644 
00645 
00646 //===========================================================================
00647 template <class Scalar> inline 
00648 Vector<Scalar>& Vector<Scalar>::selfDotStar(const Vector<Scalar>& other) 
00649 {
00650   return applyBinaryFunctor(PlayaFunctors::DotStar<Scalar>(), other);
00651 }
00652 
00653 //===========================================================================
00654 template <class Scalar> inline 
00655 Vector<Scalar>& Vector<Scalar>::selfDotSlash(const Vector<Scalar>& other) 
00656 {
00657   return applyBinaryFunctor(PlayaFunctors::DotSlash<Scalar>(), other);
00658 }
00659 
00660 
00661 //===========================================================================
00662 template <class Scalar> inline 
00663 Vector<Scalar> Vector<Scalar>::dotStar(const Vector<Scalar>& other) const
00664 {
00665   Vector<Scalar> rtn = space().createMember();
00666   rtn.acceptCopyOf(*this);
00667   rtn.selfDotStar(other);
00668   return rtn;
00669 }
00670 
00671 //===========================================================================
00672 template <class Scalar> inline 
00673 Vector<Scalar> Vector<Scalar>::dotSlash(const Vector<Scalar>& other) const
00674 {
00675   Vector<Scalar> rtn = space().createMember();
00676   rtn.acceptCopyOf(*this);
00677   rtn.selfDotSlash(other);
00678   return rtn;
00679 }
00680 
00681 
00682 //===========================================================================
00683 template <class Scalar> inline 
00684 Vector<Scalar> Vector<Scalar>::abs() const 
00685 {
00686   Vector<Scalar> rtn = space().createMember();
00687   rtn.acceptCopyOf(*this);
00688   rtn.selfAbs();
00689   return rtn;
00690 }
00691 
00692 
00693 
00694 
00695 
00696 //===========================================================================
00697 template <class Scalar> inline 
00698 Vector<Scalar> Vector<Scalar>::reciprocal() const 
00699 {
00700   Vector<Scalar> rtn = space().createMember();
00701   rtn.acceptCopyOf(*this);
00702   rtn.selfReciprocal();
00703   return rtn;
00704 }
00705 
00706 
00707 
00708 //===========================================================================
00709 template <class Scalar> inline
00710 Vector<Scalar>& Vector<Scalar>::update(const Scalar& alpha, 
00711   const Vector<Scalar>& x, 
00712   const Scalar& beta, 
00713   const Vector<Scalar>& y, 
00714   const Scalar& gamma)
00715 {
00716   this->ptr()->update(alpha, x.ptr().get(), beta, y.ptr().get(), gamma);
00717   return *this;
00718 }
00719 
00720 
00721 //===========================================================================
00722 template <class Scalar> inline
00723 Vector<Scalar>& Vector<Scalar>::update(const Scalar& alpha, 
00724   const Vector<Scalar>& x, 
00725   const Scalar& beta, 
00726   const Vector<Scalar>& y, 
00727   const Scalar& gamma, 
00728   const Vector<Scalar>& z, 
00729   const Scalar& delta)
00730 {
00731   this->ptr()->update(alpha, x.ptr().get(), beta, y.ptr().get(), 
00732     gamma, z.ptr().get(), delta);
00733   return *this;
00734 }
00735 
00736 
00737 
00738 //===========================================================================
00739 template <class Scalar> inline 
00740 Scalar Vector<Scalar>::dot(const Vector<Scalar>& other) const 
00741 {
00742   PLAYA_CHECK_SPACES(this->space(), other.space());
00743   return this->ptr()->dot(other.ptr().get());
00744 }
00745 
00746 
00747 //===========================================================================
00748 template <class Scalar> inline 
00749 Scalar Vector<Scalar>::operator*(const Vector<Scalar>& other) const 
00750 {
00751   PLAYA_CHECK_SPACES(this->space(), other.space());
00752   return this->ptr()->dot(other.ptr().get());
00753 }
00754 
00755 
00756 
00757 
00758 //===========================================================================
00759 template <class Scalar> inline 
00760 Scalar Vector<Scalar>::norm1() const 
00761 {
00762   return applyUnaryReductionFunctor(PlayaFunctors::Norm1<Scalar>(this->comm()));
00763 }
00764 
00765 
00766 
00767 
00768 //===========================================================================
00769 template <class Scalar> inline 
00770 Scalar Vector<Scalar>::norm2() const 
00771 {
00772   return this->ptr()->norm2();
00773 }
00774 
00775 
00776 
00777 
00778 //===========================================================================
00779 template <class Scalar> inline 
00780 Scalar Vector<Scalar>::norm2(const Vector<Scalar>& weights) const 
00781 {
00782   return applyBinaryReductionFunctor(PlayaFunctors::WeightedNorm2<Scalar>(this->comm()), weights);
00783 }
00784 
00785 
00786 
00787 
00788 
00789 //===========================================================================
00790 template <class Scalar> inline 
00791 Scalar Vector<Scalar>::normInf() const 
00792 {
00793   return applyUnaryReductionFunctor(PlayaFunctors::NormInf<Scalar>(this->comm()));
00794 }
00795 
00796 
00797 
00798 
00799 //===========================================================================
00800 template <class Scalar> inline 
00801 void Vector<Scalar>::zero()
00802 {
00803   setToConstant(0.0);
00804 }
00805 
00806 
00807 
00808 
00809 //===========================================================================
00810 template <class Scalar> inline 
00811 void Vector<Scalar>::setToConstant(const Scalar& alpha)
00812 {
00813   applyUnaryFunctor(PlayaFunctors::SetConstant<Scalar>(alpha));
00814 }
00815 
00816 
00817 //===========================================================================
00818 template <class Scalar> inline 
00819 Scalar Vector<Scalar>::max()const
00820 {
00821   return applyUnaryReductionFunctor(PlayaFunctors::Max<Scalar>(this->comm()));
00822 }
00823 
00824 
00825 //===========================================================================
00826 template <class Scalar> inline 
00827 Scalar Vector<Scalar>::min()const
00828 {
00829   return applyUnaryReductionFunctor(PlayaFunctors::Min<Scalar>(this->comm()));
00830 }
00831 
00832 
00833 //===========================================================================
00834 
00835 template <class Scalar> inline 
00836 const Scalar& Vector<Scalar>::operator[](int localIndex) const
00837 {
00838   const SingleChunkVector<Scalar>* scv 
00839     = dynamic_cast<const SingleChunkVector<Scalar>* >(this->ptr().get());
00840 
00841   if (scv)
00842   {
00843     if (Debug::on)
00844     {
00845       PLAYA_BOUNDSCHECK(localIndex, 0, scv->chunkSize(), 
00846         "const Vector::operator[]()");
00847     }
00848     return scv->dataPtr()[localIndex];
00849   }
00850   
00851   int chunkBase = 0;
00852   while(this->ptr()->hasMoreChunks())
00853   {
00854     ConstDataChunk<Scalar> chunk = this->nextConstChunk();
00855     int chunkSize = chunk.size();
00856     if (localIndex >= chunkBase && localIndex < chunkBase+chunkSize)
00857     {
00858       this->ptr()->rewind();
00859       return chunk.values()[localIndex-chunkBase];
00860     }
00861     chunkBase += chunkSize;
00862   }
00863   
00864   TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00865     "Vector operator[] local index " 
00866     << localIndex << " out of range [0, " << chunkBase << ")");
00867 
00868   return scv->dataPtr()[0]; // -Wall, will never be called.
00869 }
00870 
00871 //===========================================================================
00872 
00873 template <class Scalar> inline 
00874 Scalar& Vector<Scalar>::operator[](int localIndex)
00875 {
00876   SingleChunkVector<Scalar>* scv 
00877     = dynamic_cast<SingleChunkVector<Scalar>* >(this->ptr().get());
00878 
00879   if (scv)
00880   {
00881     if (Debug::on)
00882     {
00883       PLAYA_BOUNDSCHECK(localIndex, 0, scv->chunkSize(), 
00884         "non-const Vector::operator[]()");
00885     }
00886     return scv->dataPtr()[localIndex];
00887   }
00888   
00889   int chunkBase = 0;
00890   while(this->ptr()->hasMoreChunks())
00891   {
00892     NonConstDataChunk<Scalar> chunk = this->nextChunk();
00893     int chunkSize = chunk.size();
00894     if (localIndex >= chunkBase && localIndex < chunkBase+chunkSize)
00895     {
00896       this->ptr()->rewind();
00897       return chunk.values()[localIndex-chunkBase];
00898     }
00899     chunkBase += chunkSize;
00900   }
00901   
00902   TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00903     "Vector operator[] local index " 
00904     << localIndex << " out of range [0, " << chunkBase << ")");
00905 
00906   return scv->dataPtr()[0]; // -Wall, will never be called.
00907 }
00908 
00909 //===========================================================================
00910 
00911 template <class Scalar> inline 
00912 const Scalar& Vector<Scalar>::operator()(const BlockIterator<Scalar>& b,
00913   int localIndexWithinBlock) const
00914 {
00915   return this->getBlock(b)[localIndexWithinBlock];
00916 }
00917 
00918 
00919 //===========================================================================
00920 
00921 template <class Scalar> inline 
00922 Scalar& Vector<Scalar>::operator()(const BlockIterator<Scalar>& b,
00923   int localIndexWithinBlock) 
00924 {
00925   return this->getNonConstBlock(b)[localIndexWithinBlock];
00926 }
00927 
00928 
00929 //===========================================================================
00930 
00931 template <class Scalar> inline
00932 Scalar* dataPtr(Vector<Scalar> vec) 
00933 {
00934   SingleChunkVector<Scalar>* v 
00935     = dynamic_cast<SingleChunkVector<Scalar>* >(vec.ptr().get());
00936   TEUCHOS_TEST_FOR_EXCEPT(v==0);
00937   return v->dataPtr();
00938 }
00939 
00940 
00941 //===========================================================================
00942 
00943 template <class Scalar> inline
00944 const Scalar* dataPtr(const Vector<Scalar>& vec) 
00945 {
00946   const SingleChunkVector<Scalar>* v 
00947     = dynamic_cast<const SingleChunkVector<Scalar>* >(vec.ptr().get());
00948   TEUCHOS_TEST_FOR_EXCEPT(v==0);
00949   return v->dataPtr();
00950 }
00951 
00952 //===========================================================================
00953 
00954 template <class Scalar> inline
00955 LoadableVector<Scalar>* loadable(Vector<Scalar> vec) 
00956 {
00957   LoadableVector<Scalar>* lv 
00958     = dynamic_cast<LoadableVector<Scalar>* >(vec.ptr().get());
00959   TEUCHOS_TEST_FOR_EXCEPT(lv==0);
00960   return lv;
00961 }
00962 
00963 }
00964 
00965 
00966 
00967 
00968 #endif

Site Contact