00001
00002
00003
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
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
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
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
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];
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];
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