casa
$Rev:20696$
|
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