PlayaVectorImpl.hpp

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

doxygen