casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
LatticeIterInterface.h
Go to the documentation of this file.
00001 //# LatticeIterInterface.h: A base class for Lattice iterators
00002 //# Copyright (C) 1994,1995,1996,1997,1998,1999,2003
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: LatticeIterInterface.h 20229 2008-01-29 15:19:06Z gervandiepen $
00027 
00028 #ifndef LATTICES_LATTICEITERINTERFACE_H
00029 #define LATTICES_LATTICEITERINTERFACE_H
00030 
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <casa/Arrays/IPosition.h>
00035 #include <casa/Arrays/Array.h>
00036 #include <lattices/Lattices/LatticeNavigator.h>
00037 
00038 namespace casa { //# NAMESPACE CASA - BEGIN
00039 
00040 //# Forward Declarations
00041 template <class T> class Vector;
00042 template <class T> class Matrix;
00043 template <class T> class Cube;
00044 template <class T> class Lattice;
00045 template <class T> class LatticeIterator;
00046 template <class T> class RO_LatticeIterator;
00047 
00048 
00049 // <summary>
00050 // A base class for Lattice iterators
00051 // </summary>
00052 
00053 // <use visibility=local> 
00054 
00055 // <reviewed reviewer="Peter Barnes" date="1999/10/30" tests="tLatticeIterator.cc" demos="">
00056 // </reviewed>
00057 
00058 // <prerequisite>
00059 //   <li> letter/envelope schemes - see Coplien, "Advanced C++", ch 5.5
00060 //   <li> <linkto class="Lattice">Lattice</linkto>
00061 //   <li> <linkto class="LatticeIterator">LatticeIterator</linkto>
00062 // </prerequisite>
00063 
00064 // <etymology>
00065 // The LatticeIterInterface class name reflects its role as the abstract
00066 // base class for concrete read-write LatticeIterators
00067 // </etymology>
00068 
00069 // <synopsis>
00070 // This class is only for authors of Lattice letters for the LatticeIterator
00071 // envelope.  General users should see LatticeIterator.
00072 // 
00073 // The LatticeIterInterface class defines an abstract base for the standard
00074 // methods of iteration required by Lattices.  Declaring an Iterator that is
00075 // derived from this class forces it to meet the virtual requirements.
00076 //
00077 // The author of a Lattice derived class should consider the following:
00078 // <ul>
00079 // <li> The LatticeStepper class has strong effects on how the cursor is 
00080 // filled.  A non-integral shape of the cursor may allow a step of 
00081 // iteration to be only partially "touching" the Lattice.  We have dubbed
00082 // this "hangover."
00083 // <li> If the cursor has "hangover" it should be filled with a value that 
00084 // indicates the cursor is in undefined space.
00085 // <li> The cursor cannot be a reference to a part of the Lattice since 
00086 // hangover would imply a reference to undefined memory.  To enclose the 
00087 // Lattice with a zero valued hangover buffer would be inefficient.  The 
00088 // method thus forced upon the programmer is to "update" the cursor with 
00089 // Lattice values after each move or iteration and to "write" the possibly 
00090 // changed cursor values back into the Lattice before each iteration. An
00091 // algorithm which does the cursor update/write actions (and is independent 
00092 // of Lattice dimensionality) may be copied from ArrLatticeIter::cursorUpdate()
00093 // and ArrLatticeIter::cursorWrite(), respectively.
00094 // <li> The majority of the code in a new letter for LatticeIterator may be
00095 // cut and pasted from other implementations of letters.  See ArrLatticeIter
00096 // or PagedArrIter.
00097 // </ul>
00098 // </synopsis>
00099 
00100 // <example>
00101 // For an example see <linkto class=LatticeIterator>LatticeIterator</linkto>.
00102 // </example>
00103 
00104 // <motivation>
00105 // The is class provides a tidy base for letter/envelope techniques of 
00106 // iteration. 
00107 // </motivation>
00108 
00109 // <todo asof="1997/01/12">
00110 //  <li> IPositions are returned by value.  This a reflection of the 
00111 //       LatticeNavigator base class' inability to predict the
00112 //       availibility of data members for references.
00113 // </todo>
00114 
00115 
00116 template <class T> class LatticeIterInterface 
00117 {
00118 friend class Lattice<T>;
00119 friend class LatticeIterator<T>;
00120 friend class RO_LatticeIterator<T>;
00121 
00122 public:
00123   // Construct with the given navigator.
00124   LatticeIterInterface (const Lattice<T>& lattice,
00125                         const LatticeNavigator& navigator,
00126                         Bool useRef);
00127 
00128   // A virtual destructor. A virtual is needed to ensure that derived
00129   // classes declared as pointers to a LatticeIterInterface will scope their
00130   // destructor to the derived class destructor.
00131   virtual ~LatticeIterInterface();
00132 
00133 protected:
00134   // Default constructor (for derived classes).
00135   LatticeIterInterface();
00136 
00137   // Copy constructor (copy semantics).
00138   LatticeIterInterface (const LatticeIterInterface<T>& other);
00139    
00140   // Assignment (copy semantics).
00141   LatticeIterInterface& operator= (const LatticeIterInterface<T>& other);
00142    
00143   // Clone the object.
00144   virtual LatticeIterInterface<T>* clone() const;
00145 
00146   // Return the underlying lattice.
00147   Lattice<T>& lattice()
00148     { return *itsLattPtr; }
00149 
00150   // Increment operator - increment the cursor to the next position. The
00151   // implementation of the prefix operator calls the postfix one.
00152   // <group>
00153   Bool operator++();
00154   Bool operator++(int);
00155   // </group>
00156 
00157   // Decrement operator - decrement the cursor to the previous position. The
00158   // implementation of the prefix operator calls the postfix one.
00159   // <group>
00160   Bool operator--();
00161   Bool operator--(int);
00162   // </group>
00163 
00164   // Function which resets the cursor to the beginning of the Lattice and
00165   // resets the number of steps taken to zero.
00166   void reset();
00167 
00168   // Function which returns a value of "True" if the cursor is at the
00169   // beginning of the Lattice, otherwise, returns "False"
00170   Bool atStart() const;
00171 
00172   // Function which returns "True" if the cursor has been incremented to
00173   // the end of the lattice, otherwise, returns "False"
00174   Bool atEnd() const;
00175 
00176   // Function to return the number of steps (increments or decrements) taken
00177   // since construction (or since last reset).  This is a running count of
00178   // all cursor movement since doing N increments followed by N decrements
00179   // does not necessarily put the cursor back at the origin of the Lattice.
00180   uInt nsteps() const;
00181   
00182   // Function which returns the current position of the beginning of the
00183   // cursor within the Lattice. The returned IPosition will have the same
00184   // number of axes as the underlying Lattice.
00185   IPosition position() const;
00186   
00187   // Function which returns the current position of the end of the
00188   // cursor. The returned IPosition will have the same number of axes as the
00189   // underlying Lattice.
00190   IPosition endPosition() const;
00191 
00192   // Function which returns the shape of the Lattice being iterated through.
00193   // The returned IPosition will always have the same number of axes as the
00194   // underlying Lattice.
00195   IPosition latticeShape() const;
00196 
00197   // Function which returns the shape of the cursor which is iterating
00198   // through the Lattice. The cursor will always have as many dimensions as
00199   // the Lattice.
00200   IPosition cursorShape() const;
00201 
00202   // Functions which returns a window to the data in the Lattice. These are
00203   // used to read the data within the Lattice.  Use the function
00204   // that is appropriate to the current cursor dimension, AFTER REMOVING
00205   // DEGENERATE AXES, or use the <src>cursor</src> function which works with
00206   // any number of dimensions in the cursor. A call of the function whose
00207   // return value is inappropriate with respect to the current cursor
00208   // dimension will throw an exception (AipsError).
00209   // <br>The <src>doRead</src> flag indicates if the data need to be read or
00210   // if only a cursor with the correct shape has to be returned.
00211   // <br>The <src>autoRewrite</src> flag indicates if the data has to be
00212   // rewritten when the iterator state changes (e.g. moved, destructed).
00213   // <group>
00214   virtual Vector<T>& vectorCursor (Bool doRead, Bool autoRewrite);
00215   virtual Matrix<T>& matrixCursor (Bool doRead, Bool autoRewrite);
00216   virtual Cube<T>& cubeCursor (Bool doRead, Bool autoRewrite);
00217   virtual Array<T>& cursor (Bool doRead, Bool autoRewrite);
00218   //</group>
00219 
00220   // Function which checks the internals of the class for consistency.
00221   // Returns True if everything is fine otherwise returns False. The default
00222   // implementation of this function always returns True.
00223   Bool ok() const;
00224 
00225 protected:
00226   // Do the actual read of the data.
00227   virtual void readData (Bool doRead);
00228 
00229   // Rewrite the cursor data and clear the rewrite flag.
00230   virtual void rewriteData();
00231 
00232   // Update the cursor for the next chunk of data (resize if needed).
00233   virtual void cursorUpdate();
00234 
00235   // Allocate the internal buffer.
00236   void allocateBuffer();
00237 
00238   // Allocate the nondegenerate array with the correct type.
00239   void allocateCurPtr();
00240 
00241   // Synchronise the storage of itsCurPtr with itsCursor.
00242   void setCurPtr2Cursor();
00243 
00244   // Copy the base data of the other object.
00245   void copyBase (const LatticeIterInterface<T>& other);
00246 
00247 
00248   // Pointer to the method of Lattice transversal
00249   LatticeNavigator* itsNavPtr;
00250   // Pointer to the Lattice
00251   Lattice<T>*       itsLattPtr;
00252   // A buffer to hold the data. Usually itsCursor shares the data
00253   // with this buffer, but for an ArrayLattice itsCursor might reference
00254   // the lattice directly instead of making a copy in the buffer.
00255   Array<T>          itsBuffer;
00256   // Polymorphic pointer to the data in itsCursor.
00257   Array<T>*         itsCurPtr;
00258   // An Array which references the same data as the itsCurPtr, but has all
00259   // the degenerate axes. This is an optimization to avoid the overhead of
00260   // having to add the degenerate axes for each iteration.
00261   Array<T>          itsCursor;
00262   // Keep a reference to the data (if possible).
00263   Bool              itsUseRef;
00264   // Is the cursor a reference to the lattice?
00265   Bool              itsIsRef;
00266   // Have the data been read after a cursor update? (False=not read)
00267   Bool              itsHaveRead;
00268   // Rewrite the cursor data before moving or destructing?
00269   Bool              itsRewrite;
00270   // The axes forming the cursor.
00271   IPosition         itsCursorAxes;
00272 };
00273 
00274 
00275 
00276 template <class T>
00277 inline Bool LatticeIterInterface<T>::operator++() {
00278   return operator++ (0);
00279 }
00280 
00281 template <class T>
00282 inline Bool LatticeIterInterface<T>::operator--() {
00283   return operator-- (0);
00284 }
00285 
00286 template<class T>
00287 inline Bool LatticeIterInterface<T>::atStart() const
00288 {
00289   return itsNavPtr->atStart();
00290 }
00291 
00292 template<class T>
00293 inline Bool LatticeIterInterface<T>::atEnd() const
00294 {
00295   return itsNavPtr->atEnd();
00296 }
00297 
00298 template<class T>
00299 inline uInt LatticeIterInterface<T>::nsteps() const
00300 {
00301   return itsNavPtr->nsteps();
00302 }
00303 
00304 template<class T>
00305 inline IPosition LatticeIterInterface<T>::position() const
00306 {
00307   return itsNavPtr->position();
00308 }
00309 
00310 template<class T>
00311 inline IPosition LatticeIterInterface<T>::endPosition() const
00312 {
00313   return itsNavPtr->endPosition();
00314 }
00315 
00316 template<class T>
00317 inline IPosition LatticeIterInterface<T>::latticeShape() const
00318 {
00319   return itsNavPtr->latticeShape();
00320 }
00321 
00322 template<class T>
00323 inline IPosition LatticeIterInterface<T>::cursorShape() const
00324 {
00325   return itsNavPtr->cursorShape();
00326 }
00327 
00328 
00329 
00330 } //# NAMESPACE CASA - END
00331 
00332 #ifndef CASACORE_NO_AUTO_TEMPLATES
00333 #include <lattices/Lattices/LatticeIterInterface.tcc>
00334 #endif //# CASACORE_NO_AUTO_TEMPLATES
00335 #endif