PlayaBlockIteratorImpl.hpp

00001 /* @HEADER@ */
00002 //   
00003 /* @HEADER@ */
00004 
00005 #ifndef PLAYA_BLOCKITERATORIMPL_HPP
00006 #define PLAYA_BLOCKITERATORIMPL_HPP
00007 
00008 
00009 #include "PlayaBlockIteratorDecl.hpp"
00010 #include "PlayaVectorSpaceDecl.hpp"
00011 #include "PlayaExceptions.hpp"
00012 
00013 namespace Playa
00014 {
00015 
00016 template <class Scalar> inline
00017 bool BlockIterator<Scalar>
00018 ::operator==(const BlockIterator<Scalar>& other) const
00019 {
00020   if (debug())
00021   {
00022     Out::os() << "comparing: LHS=" << *this
00023               << ", RHS=" << other << std::endl;
00024   }
00025   if (this->atEnd_ && other.atEnd_) return true;
00026   if (this->atEnd_ != other.atEnd_) return false;
00027   if (this->index_.size() != other.index_.size()) return false;
00028 
00029   for (unsigned int i=0; i<this->index_.size(); i++)
00030   {
00031     if (this->index_[i] != other.index_[i]) return false;
00032   }
00033 
00034   return true;
00035 }
00036 
00037 template <class Scalar> inline
00038 bool BlockIterator<Scalar>
00039 ::operator<(const BlockIterator<Scalar>& other) const
00040 {
00041   if (debug())
00042   {
00043     Out::os() << "comparing (<): LHS=" << *this
00044               << ", RHS=" << other << std::endl;
00045   }
00046   TEUCHOS_TEST_FOR_EXCEPTION(this->space() != other.space(),
00047     RuntimeError, "Attempt to compare block iterators attached to "
00048     "two different spaces");
00049 
00050   if (!this->atEnd_ && other.atEnd_) return true;
00051   if (this->atEnd_ && !other.atEnd_) return false;
00052   if (this->atEnd_ && other.atEnd_) return false;
00053 
00054   int d = std::min(this->index_.size(), other.index_.size());
00055   
00056 
00057   for (int i=0; i<d; i++)
00058   {
00059     if (this->index_[i] < other.index_[i]) return true;
00060     if (this->index_[i] > other.index_[i]) return false;
00061   }
00062 
00063   return false;
00064 }
00065 
00066 
00067 
00068 template <class Scalar> inline
00069 BlockIterator<Scalar> BlockIterator<Scalar>::operator++(int)
00070 {
00071   if (debug())
00072   {
00073     Out::os() << "iter++" << std::endl;
00074   }
00075   BlockIterator<Scalar> old = *this;
00076 
00077   TEUCHOS_TEST_FOR_EXCEPTION(this->atEnd_, RuntimeError,
00078     "attempt to advance a BlockIterator beyond end");
00079 
00080   int depth = this->index_.size();
00081   TEUCHOS_TEST_FOR_EXCEPTION(depth <= 0, RuntimeError, 
00082     "empty index stack in BlockIterator");
00083 
00084   atEnd_ = !advance(depth-1);
00085 
00086   if (debug())
00087   {
00088     Out::os() << "old=" << old << ", new=" << *this << std::endl;
00089   }
00090   return old;
00091 }
00092 
00093 template <class Scalar> inline
00094 bool BlockIterator<Scalar>::advance(int level) 
00095 {
00096   if (level < 0) return false; 
00097 
00098   this->index_[level]++;
00099   std::deque<int> base = this->index_;
00100   base.pop_back();
00101   /* If we're at the end of this level, drop back a level */
00102   if (this->index_[level] >= this->space().getBlock(base).numBlocks())
00103   {
00104     this->index_.pop_back();
00105     return this->advance(level-1);
00106   }
00107   else /* go to the start of the next block */
00108   {
00109     goToStart(this->space().getBlock(*this), this->index_);
00110   }
00111   return true;
00112 }
00113 
00114 template <class Scalar> inline
00115 void BlockIterator<Scalar>
00116 ::goToStart(const VectorSpace<Scalar>& space,
00117   std::deque<int>& pos) const
00118 {
00119   pos.push_back(0);
00120   if (space.isBlockSpace())
00121   {
00122     goToStart(space.getBlock(0), pos);
00123   }
00124 }
00125 
00126 
00127 template <class Scalar> inline
00128 const VectorSpace<Scalar>& BlockIterator<Scalar>::space() const
00129 {
00130   return *(this->space_);
00131 }
00132 
00133 
00134 template <class Scalar> inline
00135 BlockIterator<Scalar>::BlockIterator(
00136   const VectorSpace<Scalar>& space,
00137   bool atEnd
00138   )
00139   : space_(rcp(new VectorSpace<Scalar>(space))),
00140     index_(),
00141     atEnd_(atEnd)
00142 {
00143   if (!atEnd) 
00144   {
00145     goToStart(space, index_);
00146   }
00147 }
00148 
00149 
00150 template <class Scalar> inline
00151 std::ostream& BlockIterator<Scalar>::print(std::ostream& os) const 
00152 {
00153   os << "BlockIterator";
00154   if (this->atEnd_) 
00155   {
00156     os << "[end]";
00157   }
00158   else
00159   {
00160     os << "[index={";
00161     for (unsigned int i=0; i<index_.size(); i++) 
00162     {
00163       if (i>0U) os << ", ";
00164       os << index_[i];
00165     }
00166     os << "}]";
00167   }
00168   return os;
00169 }
00170 
00171 
00172 
00173 }
00174 
00175 
00176 
00177 
00178 
00179 #endif

doxygen