casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ArrayAccessor.h
Go to the documentation of this file.
00001 //# ArrayAccessor.h: Fast 1D accessor/iterator for nD array classes
00002 //# Copyright (C) 2002,2004
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 //#
00027 //# $Id: ArrayAccessor.h 21024 2011-03-01 11:46:18Z gervandiepen $
00028 
00029 #ifndef CASA_ARRAYACCESSOR_H
00030 #define CASA_ARRAYACCESSOR_H
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <casa/Arrays/Array.h>
00035 
00036 namespace casa { //#Begin casa namespace
00037 
00038 //# Forward Declarations
00039 template <class T> class ArrayBaseAccessor;
00040 //# Next one suffices as declaration: only (part) specialisations allowed
00041 template <class T, class U> class ArrayAccessor;
00042 
00043 //# Hide simple Axis classes names from outside module
00044 
00045 namespace {
00046   // <summary> Class to enumerate compile-time axis numeration </summary>
00047   template <uInt AX> struct Axis {
00048     enum {
00049       // Specify the constant axis
00050       N=AX
00051     };
00052   };
00053   // <summary>Class to specify run-time axis values</summary>
00054   struct AxisN {
00055     // Construct the run-time axis number
00056     explicit AxisN(const uInt n) : N(n) {}
00057     // Axis number
00058     uInt N;
00059   };
00060 }
00061 
00062 // <summary> Axis independent base for the ArrayAccessor classes </summary>
00063 // <use visibility=local>
00064 // <synopsis>
00065 // The ArrayBaseAccessor class implements the axis independent parts of the
00066 // ArrayAccessor class. It can only be used from the ArrayAccessor class.
00067 // </synopsis>
00068 
00069 template <class T> class ArrayBaseAccessor {
00070  protected:
00071   //# Constructors
00072   // <group>
00073   // Default constructor (for use in e.g. containers)
00074   ArrayBaseAccessor() : arrayPtr_p(0), axis_p(0), ptr_p(0),
00075     step_p(0), begin_p(0), end_p(0) {;}
00076   // Construct from an Array
00077   // <group>
00078   explicit ArrayBaseAccessor(const Array<T> &arr) :
00079     arrayPtr_p(&arr), axis_p(0), ptr_p(const_cast<T*>(arrayPtr_p->data())),
00080     step_p(0), begin_p(0), end_p(0) {;}
00081   ArrayBaseAccessor(const Array<T> &arr, const uInt ax) :
00082     arrayPtr_p(&arr), axis_p(ax), ptr_p(const_cast<T*>(arrayPtr_p->data())),
00083     step_p(0), begin_p(0), end_p(0) {;}
00084   // </group>
00085   // Copy constructor (copy semantics)
00086   // <group>
00087   ArrayBaseAccessor(const ArrayBaseAccessor<T> &other) :
00088     arrayPtr_p(other.arrayPtr_p), axis_p(other.axis_p), ptr_p(other.ptr_p),
00089     step_p(other.step_p), begin_p(other.begin_p), end_p(other.end_p) {;}
00090   ArrayBaseAccessor(const ArrayBaseAccessor<T> &other, const uInt ax) :
00091     arrayPtr_p(other.arrayPtr_p), axis_p(ax), ptr_p(other.ptr_p),
00092     step_p(other.step_p), begin_p(other.begin_p), end_p(other.end_p) {;}
00093   // </group>
00094   
00095   //# Destructor
00096   // Destructor
00097   ~ArrayBaseAccessor() {;}
00098   // </group>
00099   
00100   // Assignment (copy semantics)
00101   ArrayBaseAccessor &operator=(const ArrayBaseAccessor<T> &other) {
00102     if (&other != this) {
00103       arrayPtr_p = other.arrayPtr_p; ptr_p = other.ptr_p;
00104     }; return *this; }
00105   // (Re-)initialize from Array
00106   // <group>
00107   void init(const Array<T> &arr) { arrayPtr_p = &arr;
00108   ptr_p = const_cast<T*>(arrayPtr_p->data()); }
00109   void init(const Array<T> &arr, const uInt ax) { arrayPtr_p = &arr;
00110   axis_p = ax; ptr_p = const_cast<T*>(arrayPtr_p->data()); }
00111   void init(const uInt ax) { arrayPtr_p = 0; axis_p = ax; ptr_p = 0; }
00112   // </group>
00113 
00114  public:
00115   //# Operators
00116   // Iterator-like operations.
00117   // <group>
00118   void operator+=(const uInt ix) { ptr_p += ix*step_p; }
00119   void operator-=(const uInt ix) { ptr_p -= ix*step_p; }
00120   void operator++() { ptr_p += step_p; }
00121   void operator++(int) { ptr_p += step_p; }
00122   void operator--() { ptr_p -= step_p; }
00123   void operator--(int) { ptr_p -= step_p; }
00124   // </group>
00125   
00126   // Dereferencing.
00127   // <group>
00128   const T &operator*() const { return *ptr_p; }
00129   T &operator*() { return *ptr_p; }
00130   T *data() { return ptr_p; }
00131   const Array<T> &baseArray() { return *arrayPtr_p; }
00132   uInt step() { return step_p; }
00133   // </group>
00134   
00135   // Index along current axis
00136   // <group>
00137   const T &operator[](const Int ix) const { return *(ptr_p + ix*step_p); };
00138   T &operator[](const Int ix) { return *(ptr_p + ix*step_p); }
00139   // </group>
00140   
00141   // End of index on line
00142   // <group>
00143   const T *end() { return end_p; }
00144   const T *end(const Int n) { return end_p + n*step_p; }
00145   // </group>
00146 
00147   // Start of index on line
00148   // <group>
00149   const T *begin() { return begin_p; }
00150   const T *begin(const Int n) { return begin_p + n*step_p; }
00151   // </group>
00152 
00153   // End when reverse indexing
00154   // <group>
00155   const T *rend() { return begin_p-step_p; }
00156   const T *rend(const Int n) { return begin_p + (n-1)*step_p; }
00157   // </group>
00158 
00159   // Begin when reverse indexing
00160   // <group>
00161   const T *rbegin() { return end_p-step_p; }
00162   const T *rbegin(const Int n) { return end_p + (n-1)*step_p; }
00163   // </group>
00164 
00165  protected:
00166   //# Data
00167   // The pointer to belonging array
00168   const Array<T> *arrayPtr_p;
00169   // Current run-time axis
00170   uInt axis_p;
00171   // Current access pointer
00172   T *ptr_p;
00173   // The increment to go from one point along an axis, to the next.
00174   Int step_p;
00175   // The start element of array
00176   const T *begin_p;
00177   // The one element beyond last on line
00178   const T *end_p;
00179   
00180 };
00181 
00182 // <summary> Fast 1D accessor/iterator for nD array classes </summary>
00183 // <use visibility=export>
00184 // <reviewed reviewer="Ger van Diepen" date="2002/12/01" tests="tArrayAccessor" demos="dArrayAccessor">
00185 // </reviewed>
00186 // <prerequisite>
00187 //   <li> Array indexing and access methods
00188 //       (<linkto class=Array>Array</linkto>)
00189 // </prerequisite>
00190 //
00191 // <etymology>
00192 // Array and access, rather than Iterator, which would suggest more
00193 // standard-like interfaces
00194 // </etymology>
00195 //
00196 // <synopsis>
00197 // Accessing a large multi-dimensional array by varying the indices of the
00198 // array can be a slow process. Timing indications are that for a cube
00199 // indexing with 3 indices was about seven times slower than using a
00200 // standard 1D C-like index into an array of basic Int types.
00201 // Improvements have made this less, partly due to some pre-calculation
00202 // necessary for this class, but can still be a factor of more than 3
00203 // slower. There are a variety of ways to access elements
00204 // <src>cube(i,j,k)</src>:
00205 // <ul>
00206 //   <li> Complete random access in all dimensions will need the
00207 //      use of the indexing: <src>cube(i,j,k);</src> or
00208 //      <src>cube(IPosition(3))</src> as described in the 
00209 //      <linkto class=Array>Array</linkto> and
00210 //      <linkto class=Cube>Cube</linkto> classes
00211 //   <li> Ordered access of all (or most) elements in an Array
00212 //      (in memory order) can be best achieved by the use of Array's
00213 //      <linkto class="Array#STL-iterator">STLIterator</linkto> classes.
00214 //      This is the fastest way for non-contiguous arrays, and only slightly
00215 //      slower than the use of <src>getStorage</src> for contiguous arrays.
00216 //   <li> Ordered access along memory order can also be achieved by the use
00217 //      of the
00218 //      <linkto class="Array:getStorage(Bool&)">
00219 //              <src>getStorage()</src></linkto> method.
00220 //      For contiguous arrays this could be slightly faster than the use of 
00221 //      the <src>STLIterator</src> (about 10% faster), but slower for 
00222 //      non-contiguous arrays. In addition it needs additional memory
00223 //      resources, which will lead to extra overhead. The general use of
00224 //      getStorage is discouraged with the introduction of the STLIterator.
00225 //      It should only be used when an interface to routines in
00226 //      other languages is needed (like Fortran), or when a large Array is
00227 //      known to be contiguous, and the data have to be referenced many times.
00228 //   <li> Access along one or more axes of a (large) multi-dimensional array
00229 //      is best achieved using the ArrayAccessor class. Its total
00230 //      access time is about 2 times faster than indexing (for cubes,
00231 //      more for more indices),
00232 //   <li> Special iteration (like in chunks) are catered for by the
00233 //      <linkto class=ArrayIterator>ArrayIterator</linkto>,
00234 //      <linkto class=MatrixIterator>MatrixIterator</linkto>,
00235 //      <linkto class=VectorIterator>VectorIterator</linkto> classes.
00236 // </ul>
00237 // The ArrayAccessor class is an iterator like pointer to the data
00238 // in the array. It is a 1-dimensional accessor. It is created with either
00239 // a constant (at compile time) axis indicator, or with a run-time
00240 // axis selector. ArrayAccessor constructor accepts a <src>const Array<></src>.
00241 // However, the underlying Array class can be modified at this moment. In
00242 // future a ConstArrayAccessor class is foreseen. 
00243 // <srcblock>
00244 //      Matrix<Double> mat(1000,500); // A 1000*500 matrix
00245 //      // Fill Matrix ...
00246 //      // Loop over index 1, than index 0:
00247 //      for (ArrayAccessor<Double, Axis<1> > i(mat); i != i.end(); ++i) {
00248 //        for (ArrayAccessor<Double, Axis<0> > j(i); j |= j.end(); ++j) {
00249 //          // Actions on *j (which points to mat(j,i)) or j[n]
00250 //          // (which points to mat(j+n,i))
00251 //      }}
00252 // </srcblock>
00253 // For run-time indices it would look like:
00254 // <srcblock>
00255 //      Matrix<Double> mat(1000,500); // A 1000*500 matrix
00256 //      // Fill Matrix ...
00257 //      // Loop over index 1, than index 0:
00258 //      for (ArrayAccessor<Double, AxisN> i(mat, AxisN(1));
00259 //           i != i.end(); ++i) {
00260 //        for (ArrayAccessor<Double, AxisN> j(i,AxisN(0)); j |= j.end(); ++j) {
00261 //          // Actions on *j (which points to mat(j,i)) or j[n]
00262 //          // (which points to mat(j+n,i))
00263 //      }}
00264 // </srcblock>
00265 // Compile-time and run-time axes can be mixed in constructors and assignments.
00266 //
00267 // <note role=tip> Like in all comparable situations, memory allocation
00268 // within a loop can slow down processes. For that reason the example above
00269 // can be better written (about 25% faster) as:
00270 // <srcblock>
00271 //      Matrix<Double> mat(1000,500); // A 1000*500 matrix
00272 //      ArrayAccessor<Double, Axis<0> > j; // accessor pre-allocated
00273 //      // Fill Matrix ...
00274 //      // Loop over index 1, than index 0:
00275 //      for (ArrayAccessor<Double, Axis<1> > i(mat); i != i.end(); ++i) {
00276 //        for (j=i; j |= j.end(); ++j) {
00277 //          // Actions on *j (which points to mat(j,i)) or j[n]
00278 //          // (which points to mat(j+n,i))
00279 //      }}
00280 // </srcblock>
00281 // </note>
00282 // <note role=tip> The underlying Array classes are structured with the
00283 // first index varying fastest. This means that in general (due to caching and 
00284 // swapping) operations are fastest when <src>Axis<0> ></src> is in the
00285 // innermost loop (if possible of course).
00286 // </note>
00287 // The demonstrator and test programs have more examples.
00288 //
00289 // The accessors can be dereferenced by the dereference operator (<src>*</src>)
00290 // and by the index operator (<src>[Int]</src>), which can handle negative
00291 // values.
00292 // Points around the accessor in any axis direction can be addressed
00293 // along any axis by the templated methods <src>next()</src>,
00294 // <src>prev()</src> and <src>index(Int)</src>. Either run-time or
00295 // compile-time axes can be used (see example).
00296 //
00297 // An accessor can be re-initialized with the init() function. It can also
00298 // be reset() to any pointer value. Mthods <src>end()</src>,
00299 // <src>begin()</src>, <src>rbegin()</src> and <src>rend()</src> are available 
00300 // for loop control (like in the STL iterators). In addition each of these
00301 // can have an optional integer argument, specifying an offset (in points
00302 // along the current axis).
00303 //
00304 // Operations <src>++ -- += -=</src> are available.
00305 //
00306 // This class is available for <src>Axis<n></src> and <src>AxisN</src>
00307 // specializations only.
00308 // </synopsis>
00309 //
00310 // <example>
00311 // <srcblock>
00312 //      // get a cube and fill it
00313 //      Cube<Double> cub(5,2,4);
00314 //      indgen(cub);
00315 //      // Loop over axes 2-0 and use index() over axis 1
00316 //      for (ArrayAccessor<Double, Axis<2> > i(cub); i != i.end() ; ++i) {
00317 //        for (ArrayAccessor<Double, Axis<0> > j(i);
00318 //          j != j.end(); ++j) {
00319 //          // show result
00320 //          cout << *j << ", " << j.index<Axis<1> >(1) << endl;
00321 //        };
00322 //      };
00323 // </srcblock>
00324 // See the demonstrator program in
00325 // <src>aips/implement/Arrays/test/dArrayAccessor.cc</src> and the
00326 // test program <src>tArrayAccessor</src> for more examples.
00327 // </example>
00328 //
00329 // <motivation>
00330 // To speed up especially interpolation code
00331 // </motivation>
00332 //
00333 // <templating arg=T>
00334 //    <li> Any valid Array templating argument
00335 // </templating>
00336 // <templating arg=U>
00337 //    <li> A class <src>Axis<n></src>
00338 //    <li> Class AxisN
00339 // </templating>
00340 //
00341 // <thrown>
00342 //    <li> Exceptions created in the Array class
00343 //    <li> Addressing errors
00344 // </thrown>
00345 //
00346 // <todo asof="2002/11/06">
00347 //   <li> add a ConstArrayAccessor class
00348 // </todo>
00349 //
00350 template <class T, uInt U> class ArrayAccessor<T, Axis<U> > :
00351 public ArrayBaseAccessor<T> {
00352  public:
00353   // Constructors
00354   // <group>
00355   // Default ctor. Note only available to accommodate containers of
00356   // ArrayAccessors. Use <src>init()</src> to initialize.
00357   ArrayAccessor() : ArrayBaseAccessor<T>() {;}
00358   // Construct an accessor from specified Array along the selected axis.
00359   // The accessor will point to the first element along the axis (i.e.
00360   // at (0,0,...)).
00361   explicit ArrayAccessor(const Array<T> &arr) :
00362     ArrayBaseAccessor<T>(arr) { initStep(); }
00363   // Construct from an ArrayAccessor along same axis. The accessor will point
00364   // at the same element as the originator.
00365   ArrayAccessor(const ArrayAccessor<T, Axis<U> > &other) :
00366     ArrayBaseAccessor<T>(other) {;}
00367   // Construct from accessor along another (or run-time) axis.
00368   // The accessor will point to the same element (but will be oriented
00369   // along another axis).
00370   // <group>
00371   template <uInt X>
00372     explicit ArrayAccessor(const ArrayAccessor<T, Axis<X> > &other) :
00373     ArrayBaseAccessor<T>(other) { initStep(); }
00374   explicit ArrayAccessor(const ArrayAccessor<T, AxisN > &other) :
00375     ArrayBaseAccessor<T>(other) { initStep(); }
00376   // </group>
00377   
00378   // Destructor
00379   ~ArrayAccessor() {;}
00380   // </group>
00381   
00382   // Assignment (copy semantics)
00383   // <group>
00384   // Assign from other compile-time accessor along same axis
00385   ArrayAccessor &operator=(const ArrayAccessor<T, Axis<U> > &other) {
00386     if (&other != this) {
00387       ArrayBaseAccessor<T>::operator=(other); this->step_p = other.step_p;
00388       this->begin_p = other.begin_p; this->end_p = other.end_p;
00389     }; return *this; }
00390   // Assign from other compile-time accessor along another axis
00391   template <uInt X>
00392     ArrayAccessor &operator=(const ArrayAccessor<T, Axis<X> > &other) {
00393     ArrayBaseAccessor<T>::operator=(other); initStep();
00394     return *this; }
00395   // Assign from run-time accessor along any axis
00396   ArrayAccessor &operator=(const ArrayAccessor<T, AxisN> &other) {
00397     ArrayBaseAccessor<T>::operator=(other); initStep(); return *this; }
00398   // </group>
00399   
00400   // (Re-)initialization to start of array (i.e. element (0,0,0,...))
00401   void init(const Array<T> &arr) { ArrayBaseAccessor<T>::init(arr);
00402   initStep(); }
00403 
00404   // Reset to start of dimension or to specified pointer
00405   // <group>
00406   void reset() { this->ptr_p = const_cast<T *>(this->begin_p); }
00407   void reset(const T * p) { this->ptr_p = const_cast<T *>(p); initStep(); }
00408   // </group>
00409 
00410   // Indexing  operations along another axis than the one of the current
00411   // object. See for the indexing and iterator operations along the
00412   // object's axis <linkto class=ArrayBaseAccessor>ArrayBaseAccessor</linkto> 
00413   // <group>
00414   // Get the value 'next' along the specified axis (e.g. with 
00415   // <src>a.next<Axis<2> >()</src>)
00416   // <group>
00417   template <class X>
00418     const T &next() const
00419     { return *(this->ptr_p + this->arrayPtr_p->steps()[X::N]); }
00420   template <class X>
00421     T &next() { return *(this->ptr_p + this->arrayPtr_p->steps()[X::N]); }
00422   // </group>
00423   // Get the value 'previous' along the specified axis (e.g. with 
00424   // <src>a.prev<Axis<2> >()</src>)
00425   // <group>
00426   template <class X>
00427     const T &prev() const
00428     { return *(this->ptr_p - this->arrayPtr_p->steps()[X::N]); }
00429   template <class X>
00430     T &prev() { return *(this->ptr_p - this->arrayPtr_p->steps()[X::N]); }
00431   // </group>
00432   // Get the next or previous along the specified run-time axis. E.g.
00433   // <src>a.prev(AxisN(2))</src>.
00434   // <group>
00435   const T &next(const AxisN ax) const
00436     { return *(this->ptr_p + this->arrayPtr_p->steps()[ax.N]); }
00437   T &next(const AxisN ax)
00438     { return *(this->ptr_p + this->arrayPtr_p->steps()[ax.N]); }
00439   const T &prev(const AxisN ax) const
00440     { return *(this->ptr_p - this->arrayPtr_p->steps()[ax.N]); }
00441   T &prev(const AxisN ax)
00442     { return *(this->ptr_p - this->arrayPtr_p->steps()[ax.N]); }
00443   // </group>
00444   // Give the value indexed with respect to the current accessor value
00445   // along the axis specified as either a compile-time or a run-time
00446   // axis. E.g. <src>a.index<Axis<3> >(5)</src> or 
00447   // <src>a.index(5, AxisN(3))</src>.
00448   // <group>
00449   template <class X>
00450     const T &index(const Int ix) const 
00451     { return *(this->ptr_p + ix*this->arrayPtr_p->steps()[X::N]); }
00452   template <class X>
00453     T &index(const Int ix)
00454     { return *(this->ptr_p + ix*this->arrayPtr_p->steps()[X::N]); }
00455   const T &index(const Int ix, const AxisN ax) const 
00456     { return *(this->ptr_p + ix*this->arrayPtr_p->steps()[ax.N]); }
00457   T &index(const Int ix, const AxisN ax)
00458     { return *(this->ptr_p + ix*this->arrayPtr_p->steps()[ax.N]); }
00459   // </group>
00460   // </group>
00461   
00462   // Comparison. The comparisons are done for the accessor pointer
00463   // value. They can be used to control loops.
00464   // <group>
00465   Bool operator==(const ArrayAccessor<T, Axis<U> > &other) const {
00466     return this->ptr_p == other.ptr_p; }
00467   Bool operator!=(const ArrayAccessor<T, Axis<U> > &other) const {
00468     return this->ptr_p != other.ptr_p; }
00469   Bool operator==(const T *other) const { return this->ptr_p == other; }
00470   Bool operator!=(const T *other) const { return this->ptr_p != other; }
00471   // </group>
00472   
00473  private:
00474   // Get proper offset
00475   Int initOff(Int x, uInt ax) {
00476     uInt st = this->arrayPtr_p->steps()[ax];
00477     return ((st) ? (ax == Axis<U>::N ? x/st : initOff(x%st, ax-1)) : 0); }
00478   // Initialize some internal values
00479   void initStep() {
00480     this->step_p = this->arrayPtr_p->steps()[Axis<U>::N];
00481     this->begin_p = this->end_p = this->ptr_p
00482                     - initOff(this->ptr_p - this->arrayPtr_p->data(),
00483                               this->arrayPtr_p->ndim()-1)*this->step_p;
00484     this->end_p += this->arrayPtr_p->shape()[Axis<U>::N]*this->step_p; }
00485   
00486 };
00487 
00488 #define ArrayAccessor_RT ArrayAccessor
00489 
00490 // <summary> Specialization for run-time axes </summary>
00491 // <use visibility=export>
00492 // <synopsis>
00493 // This class is a specialization for run-time axis selection within the
00494 // array accessor. The axis is specified in the constructors and in the
00495 // special indexing operators (<src>prev, next, index</src>) with
00496 // a parameter <src>AxisN(n)</src> in stead of a template parameter
00497 // <src><Axis<n> ></src>.
00498 //
00499 // Note that the name of the class is <src>ArrayAccessor</src>. The special
00500 // name is only to bypass cxx2html problems with duplicate class names. 
00501 // </synopsis>
00502 //
00503 template <class T> class ArrayAccessor_RT<T, AxisN> :
00504 public ArrayBaseAccessor<T> {
00505  public:
00506   // Constructors
00507   // <group>
00508   explicit ArrayAccessor_RT(const AxisN ax=AxisN(0)) :
00509     ArrayBaseAccessor<T>() { this->axis_p = ax.N; }
00510   explicit ArrayAccessor_RT(Array<T> &arr, const AxisN ax=AxisN(0)) :
00511     ArrayBaseAccessor<T>(arr, ax.N) { initStep(); }
00512   ArrayAccessor_RT(ArrayAccessor_RT<T, AxisN> &other) :
00513     ArrayBaseAccessor<T>(other) {;}
00514   explicit ArrayAccessor_RT(ArrayAccessor_RT<T, AxisN> &other,
00515                             const AxisN ax) :
00516     ArrayBaseAccessor<T>(other, ax.N) { initStep(); }
00517   template <uInt X>
00518     explicit ArrayAccessor_RT(ArrayAccessor_RT<T, Axis<X> > &other,
00519                               const AxisN ax=AxisN(0)) :
00520     ArrayBaseAccessor<T>(other, ax.N) { initStep(); }
00521   ArrayAccessor_RT &operator=(const ArrayAccessor_RT<T, AxisN> &other) {
00522     if (&other != this) {
00523       ArrayBaseAccessor<T>::operator=(other);
00524       initStep();
00525     }; return *this; }
00526   template <uInt X>
00527     ArrayAccessor_RT &operator=(const ArrayAccessor_RT<T, Axis<X> > &other) {
00528     ArrayBaseAccessor<T>::operator=(other);
00529     initStep(); return *this; }
00530   // </group>
00531 
00532   // Destructor
00533   ~ArrayAccessor_RT() {;}
00534 
00535   // (Re-)initialization to start of array (i.e. element (0,0,0,...)) or
00536   // re-initialize to an axis.
00537   // <group>
00538   void init(const Array<T> &arr, const AxisN ax)
00539     { ArrayBaseAccessor<T>::init(arr, ax.N); initStep(); }
00540   void init(const AxisN ax) 
00541     { ArrayBaseAccessor<T>::init(ax.N); }
00542   // </group>
00543 
00544   // Reset to start of dimension or to specified pointer
00545   // <group>
00546   void reset() { this->ptr_p = const_cast<T *>(this->begin_p); }
00547   void reset(const T *p) { this->ptr_p = const_cast<T *>(p); initStep(); }
00548   // </group>
00549 
00550   // Indexing  operations along another axis than the one of the current
00551   // object. See for the indexing and iterator operations along the
00552   // object's axis <linkto class=ArrayBaseAccessor>ArrayBaseAccessor</linkto> 
00553   // <group>
00554   template <class X>
00555     const T &next() const
00556     { return *(this->ptr_p + this->arrayPtr_p->steps()[X::N]); }
00557   template <class X>
00558     T &next() { return *(this->ptr_p + this->arrayPtr_p->steps()[X::N]); }
00559   template <class X>
00560     const T &prev() const
00561     { return *(this->ptr_p - this->arrayPtr_p->steps()[X::N]); }
00562   template <class X>
00563     T &prev() { return *(this->ptr_p - this->arrayPtr_p->steps()[X::N]); }
00564   const T &next(const AxisN ax) const
00565     { return *(this->ptr_p + this->arrayPtr_p->steps()[ax.N]); }
00566   T &next(const AxisN ax)
00567     { return *(this->ptr_p + this->arrayPtr_p->steps()[ax.N]); }
00568   const T &prev(const AxisN ax) const
00569     { return *(this->ptr_p - this->arrayPtr_p->steps()[ax.N]); }
00570   T &prev(const AxisN ax)
00571     { return *(this->ptr_p - this->arrayPtr_p->steps()[ax.N]); }
00572   template <class X>
00573     const T &index(const Int ix) const 
00574     { return *(this->ptr_p + ix*this->arrayPtr_p->steps()[X::N]); }
00575   template <class X>
00576     T &index(const Int ix)
00577     { return *(this->ptr_p + ix*this->arrayPtr_p->steps()[X::N]); }
00578   const T &index(const Int ix, const AxisN(ax)) const 
00579     { return *(this->ptr_p + ix*this->arrayPtr_p->steps()[ax.N]); }
00580   T &index(const Int ix, const AxisN(ax))
00581     { return *(this->ptr_p + ix*this->arrayPtr_p->steps()[ax.N]); }
00582   // </group>
00583 
00584   // Comparisons
00585   // <group>
00586   Bool operator==(const ArrayAccessor_RT<T, AxisN> &other) const {
00587     return this->ptr_p == other.ptr_p; }
00588   Bool operator!=(const ArrayAccessor_RT<T, AxisN> &other) const {
00589     return this->ptr_p != other.ptr_p; }
00590   Bool operator==(const T *other) const { return this->ptr_p == other; }
00591   Bool operator!=(const T *other) const { return this->ptr_p != other; }
00592   // </group>
00593 
00594  private: 
00595   // Get proper offset
00596   Int initOff(Int x, uInt ax) {
00597     uInt st = this->arrayPtr_p->steps()[ax];
00598     return ((st) ? (ax == this->axis_p ? x/st : initOff(x%st, ax-1)) : 0); }
00599   // Initialize some internal values
00600   void initStep() {
00601     this->step_p = this->arrayPtr_p->steps()[this->axis_p];
00602     this->begin_p = this->end_p = this->ptr_p
00603                     - initOff(this->ptr_p - this->arrayPtr_p->data(),
00604                               this->arrayPtr_p->ndim()-1)*this->step_p;
00605     this->end_p += this->arrayPtr_p->shape()[this->axis_p]*this->step_p; }
00606   
00607 };
00608 
00609 #undef ArrayAccessor_RT
00610 
00611 } //#End casa namespace
00612 #endif