casa
$Rev:20696$
|
00001 //# Array.h: A templated N-D Array class with zero origin 00002 //# Copyright (C) 1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,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: Array.h 21130 2011-10-18 07:39:05Z gervandiepen $ 00027 00028 #ifndef CASA_ARRAY_H 00029 #define CASA_ARRAY_H 00030 00031 //# Includes 00032 #include <casa/Arrays/ArrayBase.h> 00033 #include <casa/Containers/Block.h> 00034 #include <casa/Utilities/CountedPtr.h> 00035 #include <casa/Arrays/MaskLogiArrFwd.h> 00036 #include <casa/Arrays/IPosition.h> 00037 #include <casa/ostream.h> 00038 #include <iterator> 00039 #if defined(WHATEVER_VECTOR_FORWARD_DEC) 00040 WHATEVER_VECTOR_FORWARD_DEC; 00041 #else 00042 #include <casa/stdvector.h> 00043 #endif 00044 00045 namespace casa { //#Begin casa namespace 00046 //# Forward Declarations 00047 class AipsIO; 00048 class Slice; 00049 class Slicer; 00050 template<class T> class Matrix; 00051 template<class T> class ArrayIterator; 00052 template<class T> class MaskedArray; 00053 template<class Domain, class Range> class Functional; 00054 //template <class T, class U> class vector; 00055 00056 00057 // <summary> A templated N-D Array class with zero origin </summary> 00058 00059 // Array<T> is a templated, N-dimensional, Array class. The origin is zero, 00060 // but by default indices are zero-based. This Array class is the 00061 // base class for specialized Vector<T>, Matrix<T>, and Cube<T> classes. 00062 // 00063 // Indexing into the array, and positions in general, are given with IPosition 00064 // (essentially a vector of integers) objects. That is, an N-dimensional 00065 // array requires a length-N IPosition to define a position within the array. 00066 // Unlike C, indexing is done with (), not []. Also, the storage order 00067 // is the same as in FORTRAN, i.e. memory varies most rapidly with the first 00068 // index. 00069 // <srcblock> 00070 // // axisLengths = [1,2,3,4,5] 00071 // IPosition axisLengths(5, 1, 2, 3, 4, 5); 00072 // Array<Int> ai(axisLengths); // ai is a 5 dimensional array of 00073 // // integers; indices are 0-based 00074 // // => ai.nelements() == 120 00075 // Array<Int> ai2(axisLengths); // The first element is at index 0 00076 // IPosition zero(5); zero = 0; // [0,0,0,0,0] 00077 // //... 00078 // </srcblock> 00079 // Indexing into an N-dimensional array is relatively expensive. Normally 00080 // you will index into a Vector, Matrix, or Cube. These may be obtained from 00081 // an N-dimensional array by creating a reference, or by using an 00082 // ArrayIterator. The "shape" of the array is an IPosition which gives the 00083 // length of each axis. 00084 // 00085 // An Array may be standalone, or it may refer to another array, or to 00086 // part of another array (by refer we mean that if you change a pixel in 00087 // the current array, a pixel in the referred to array also changes, i.e. 00088 // they share underlying storage). 00089 // <note role=warning> 00090 // One way one array can reference another is through the copy 00091 // constructor. While this might be what you want, you should 00092 // probably use the reference() member function to make it explicit. 00093 // The copy constructor is used when arguments are passed by value; 00094 // normally functions should not pass Arrays by value, rather they 00095 // should pass a reference or a const reference. On the positive 00096 // side, returning an array from a function is efficient since no 00097 // copying need be done. 00098 // </note> 00099 // 00100 // Aside from the explicit reference() member function, a user will 00101 // most commonly encounter an array which references another array 00102 // when he takes an array slice (or section). A slice is a sub-region of 00103 // an array (which might also have a stride: every nth row, every mth column, 00104 // ...). 00105 // <srcblock> 00106 // IPosition lengths(3,10,20,30); 00107 // Array<Int> ai(lengths); // A 10x20x30 cube 00108 // Cube<Int> ci; 00109 // //... 00110 // ci.reference(ai1); // ci and ai now reference the same 00111 // // storage 00112 // ci(0,0,0) = 123; // Can use Cube indexing 00113 // ci.xyPlane(2) = 0; // and other member functions 00114 // IPosition zero(3,0,0,0); 00115 // assert(ai(zero) == 123); // True because ai, ci are references 00116 // //... 00117 // Array<Int> subArray; 00118 // IPosition blc(3,0,0,0), trc(3,5,5,5); 00119 // subArray.reference(ai(blc, trc)); 00120 // subArray = 10; // All of subArray, which is the 00121 // // subcube from 0,0,0 to 5,5,5 in 00122 // // ai, has the value 10. 00123 // </srcblock> 00124 // While the last example has an array slice referenced explicitly by another 00125 // array variable, normally the user will often only use the slice as 00126 // a temporary in an expresion, for example: 00127 // <srcblock> 00128 // Array<Complex> array; 00129 // IPosition blc, trc, offset; 00130 // //... 00131 // // Copy from one region of the array into another 00132 // array(blc, trc) = array(blc+offset, trc+offset); 00133 // </srcblock> 00134 // 00135 // The Array classes are intended to operate on relatively large 00136 // amounts of data. While they haven't been extensively tuned yet, 00137 // they are relatively efficient in terms of speed. Presently they 00138 // are not space efficient -- the overhead is about 15 words. While 00139 // this will be improved (probably to about 1/2 that), these array 00140 // classes are not appropriate for very large numbers of very small 00141 // arrays. The Block<T> class may be what you want in this circumstance. 00142 // 00143 // Element by element mathematical and logical operations are available 00144 // for arrays (defined in aips/ArrayMath.h and aips/ArrayLogical.h). 00145 // Because arithmetic and logical functions are split out, it is possible 00146 // to create an Array<T> (and hence Vector<T> etc) for any type T that has 00147 // a default constructor, assignment operator, and copy constructor. In 00148 // particular, Array<String> works. 00149 // 00150 // If compiled with the preprocessor symbol AIPS_DEBUG symbol, array 00151 // consistency ("invariants") will be checked in most member 00152 // functions, and indexing will be range-checked. This should not be 00153 // defined for production runs. 00154 // 00155 // A tutorial for the ArrayClasses is available in the "AIPS++ Programming 00156 // Manual." 00157 // 00158 // <note role=tip> 00159 // Most of the data members and functions which are "protected" should 00160 // likely become "private". 00161 // </note> 00162 // 00163 // <todo asof="1999/12/30"> 00164 // <li> Integrate into the Lattice hierarchy 00165 // <li> Factor out the common functions (shape etc) into a type-independent 00166 // base class. 00167 // </todo> 00168 00169 template<class T> class Array : public ArrayBase 00170 { 00171 public: 00172 00173 // Result has dimensionality of zero, and nelements is zero. 00174 Array(); 00175 00176 // Create an array of the given shape, i.e. after construction 00177 // array.ndim() == shape.nelements() and array.shape() == shape. 00178 // The origin of the Array is zero. 00179 explicit Array(const IPosition &shape); 00180 00181 // Create an array of the given shape and initialize it with the 00182 // initial value. 00183 Array(const IPosition &shape, const T &initialValue); 00184 00185 // After construction, this and other reference the same storage. 00186 Array(const Array<T> &other); 00187 00188 // Create an Array of a given shape from a pointer. 00189 Array(const IPosition &shape, T *storage, StorageInitPolicy policy = COPY); 00190 // Create an Array of a given shape from a pointer. Because the pointer 00191 // is const, a copy is always made. 00192 Array(const IPosition &shape, const T *storage); 00193 00194 // Frees up storage only if this array was the last reference to it. 00195 virtual ~Array(); 00196 00197 // Assign the other array to this array. 00198 // If the shapes mismatch, this array is resized. 00199 virtual void assign (const Array<T>& other); 00200 00201 // Set every element of the array to "value." Also could use the 00202 // assignment operator which assigns an array from a scalar. 00203 void set(const T &value); 00204 00205 // Apply the function to every element of the array. This modifies 00206 // the array in place. 00207 // <group> 00208 // This version takes a function which takes a T and returns a T. 00209 void apply(T (*function)(T)); 00210 // This version takes a function which takes a const T reference and 00211 // returns a T. 00212 void apply(T (*function)(const T &)); 00213 // This version applies a functional. 00214 void apply(const Functional<T,T> &function); 00215 // </group> 00216 00217 // After invocation, this array and other reference the same storage. That 00218 // is, modifying an element through one will show up in the other. The 00219 // arrays appear to be identical; they have the same shape. 00220 // <br>Please note that this function makes it possible to reference a 00221 // const Array, thus effectively it makes a const Array non-const. 00222 // Although this may seem undesirable at first sight, it is necessary to 00223 // be able to make references to temporary Array objects, in particular to 00224 // Array slices. Otherwise one first needs to use the copy constructor. 00225 //# The const has been introduced on 2005-Mar-31 because of the hassle 00226 //# involved in calling the copy ctor before reference. 00227 virtual void reference(const Array<T> &other); 00228 00229 // Copy the values in other to this. If the array on the left hand 00230 // side has no elements, then it is resized to be the same size as 00231 // as the array on the right hand side. Otherwise, the arrays must 00232 // conform (same shapes). 00233 // <srcblock> 00234 // IPosition shape(2,10,10); // some shape 00235 // Array<Double> ad(shape); 00236 // //... 00237 // Array<Double> ad2; // N.B. ad2.nelements() == 0 00238 // ad2 = ad; // ad2 resizes, then elements 00239 // // are copied. 00240 // shape = 20; 00241 // Array<Double> ad3(shape); 00242 // ad3 = ad; // Error: arrays do not conform 00243 // </srcblock> 00244 // Note that the assign function can be used to assign a 00245 // non-conforming array. 00246 virtual Array<T> &operator=(const Array<T> &other); 00247 00248 // Set every element of this array to "value". In other words, a scalar 00249 // behaves as if it were a constant conformant array. 00250 Array<T> &operator=(const T &value); 00251 00252 // Copy to this those values in marray whose corresponding elements 00253 // in marray's mask are True. 00254 // 00255 // <thrown> 00256 // <li> ArrayConformanceError 00257 // </thrown> 00258 // 00259 Array<T> &operator= (const MaskedArray<T> &marray); 00260 00261 // This makes a copy of the array and returns it. This can be 00262 // useful for, e.g. making working copies of function arguments 00263 // that you can write into. 00264 // <srcblock> 00265 // void someFunction(const Array<Int> &arg) 00266 // { 00267 // Array<Int> tmp(arg.copy()); 00268 // // ... 00269 // } 00270 // </srcblock> 00271 // Note that since the copy constructor makes a reference, if we just 00272 // created used to copy constructor, modifying "tmp" would also 00273 // modify "arg". Clearly another alternative would simply be: 00274 // <srcblock> 00275 // void someFunction(const Array<Int> &arg) 00276 // { 00277 // Array<Int> tmp; 00278 // tmp = arg; 00279 // // ... 00280 // } 00281 // </srcblock> 00282 // which likely would be simpler to understand. (Should copy() 00283 // be deprecated and removed?) 00284 Array<T> copy() const; // Make a copy of this 00285 00286 // This function copies the matching part of from array to this array. 00287 // The matching part is the part with the minimum size for each axis. 00288 // E.g. if this array has shape [4,5,6] and from array has shape [7,3], 00289 // the matching part has shape [4,3]. 00290 // <br>Note it is used by the resize function if 00291 // <src>copyValues==True</src>. 00292 void copyMatchingPart (const Array<T> &from); 00293 00294 // This ensures that this array does not reference any other storage. 00295 // <note role=tip> 00296 // When a section is taken of an array with non-unity strides, 00297 // storage can be wasted if the array, which originally contained 00298 // all the data, goes away. unique() also reclaims storage. This 00299 // is an optimization users don't normally need to understand. 00300 // 00301 // <srcblock> 00302 // IPosition shape(...), blc(...), trc(...), inc(...); 00303 // Array<Float> af(shape); 00304 // inc = 2; // or anything > 1 00305 // Array<Float> aSection.reference(af(blc, trc, inc)); 00306 // af.reference(anotherArray); 00307 // // aSection now references storage that has a stride 00308 // // in it, but nothing else is. Storage is wasted. 00309 // aSection.unique(); 00310 // </srcblock> 00311 // </note> 00312 void unique(); 00313 00314 // Create an STL vector from an Array. The created vector is a linear 00315 // representation of the Array memory. See 00316 // <linkto class=Vector>Vector</linkto> for 00317 // details of the operation and its reverse (i.e. creating a 00318 // <src>Vector</src> from a <src>vector</src>), and for details of 00319 // definition and instantiation. 00320 template <class U> 00321 void tovector(vector<T, U> &out) const; 00322 00323 vector<T> tovector() const; 00324 00325 // It is occasionally useful to have an array which access the same 00326 // storage appear to have a different shape. For example, 00327 // turning an N-dimensional array into a Vector. 00328 // <br>When the array data are contiguous, the array can be reshaped 00329 // to any form as long as the number of elements stays the same. 00330 // When not contiguous, it is only possible to remove or add axes 00331 // with length 1. 00332 // <srcblock> 00333 // IPosition squareShape(2,5,5); 00334 // Array<Float> square(squareShape); 00335 // IPosition lineShape(1,25); 00336 // Vector<Float> line(square.reform(lineShape)); 00337 // // "square"'s storage may now be accessed through Vector "line" 00338 // </srcblock> 00339 Array<T> reform(const IPosition &shape) const; 00340 00341 // These member functions remove degenerate (ie. length==1) axes from 00342 // Arrays. Only axes greater than startingAxis are considered (normally 00343 // one wants to remove trailing axes). The first two of these functions 00344 // return an Array reference with axes removed. The latter two functions 00345 // let this Array object reference the 'other' array with degenerated axes 00346 // removed. 00347 // <br> 00348 // Unless throwIfError is False, an exception will be thrown if 00349 // startingAxis exceeds the array's dimensionality. 00350 // <br> 00351 // The functions with argument <src>ignoreAxes</src> do 00352 // not consider the axes given in that argument. In this way it can be 00353 // achieved that degenerate axes are kept. 00354 // <note role=caution> When the two functions returning <src>void</src> 00355 // are invoked on a derived object (e.g. Matrix), an exception is 00356 // thrown if removing the degenerate axes from other does not result 00357 // in a correct number of axes. 00358 // </note> 00359 // <group> 00360 Array<T> nonDegenerate(uInt startingAxis=0, Bool throwIfError=True) const; 00361 Array<T> nonDegenerate(const IPosition& ignoreAxes) const; 00362 void nonDegenerate(const Array<T> &other, uInt startingAxis=0, 00363 Bool throwIfError=True); 00364 void nonDegenerate(const Array<T> &other, const IPosition &ignoreAxes) 00365 { doNonDegenerate (other, ignoreAxes); } 00366 // </group> 00367 00368 // Remove degenerate axes from this Array object. 00369 // Note it does not make sense to use these functions on a derived object 00370 // like Matrix, because it is not possible to remove axes from them. 00371 // <group> 00372 void removeDegenerate(uInt startingAxis=0, 00373 Bool throwIfError=True); 00374 void removeDegenerate(const IPosition &ignoreAxes); 00375 // </group> 00376 00377 // This member function returns an Array reference with the specified 00378 // number of extra axes, all of length one, appended to the end of the 00379 // Array. Note that the <src>reform</src> function can also be 00380 // used to add extra axes. 00381 // <group> 00382 const Array<T> addDegenerate(uInt numAxes) const; 00383 Array<T> addDegenerate(uInt numAxes); 00384 // </group> 00385 00386 // Make this array a different shape. If <src>copyValues==True</src> 00387 // the old values are copied over to the new array. 00388 // Copying is done on a per axis basis, thus a subsection with the 00389 // minimum of the old and new shape is copied. 00390 // <br>Resize without argument is equal to resize(IPosition()). 00391 // <br>It is important to note that if multiple Array objects 00392 // reference the same data storage, this Array object still references 00393 // the same data storage as the other Array objects if the shape does 00394 // not change. Otherwise this Array object references newly allocated 00395 // storage, while the other Array objects still reference the existing 00396 // data storage. 00397 // <br>If you want to be sure that the data storage of this Array object 00398 // is not referenced by other Array objects, the function unique should 00399 // be called first. 00400 // <group> 00401 virtual void resize(); 00402 virtual void resize(const IPosition &newShape, Bool copyValues=False); 00403 // </group> 00404 00405 // Access a single element of the array. This is relatively 00406 // expensive. Extensive indexing should be done through one 00407 // of the Array specializations (Vector, Matrix, Cube). If 00408 // AIPS_DEBUG is defined, index checking will be performed. 00409 // <group> 00410 T &operator()(const IPosition &); 00411 const T &operator()(const IPosition &) const; 00412 // </group> 00413 00414 // Get a reference to an array section extending 00415 // from start to end (inclusive). 00416 // <group> 00417 Array<T> operator()(const IPosition &start, 00418 const IPosition &end); 00419 const Array<T> operator()(const IPosition &start, 00420 const IPosition &end) const; 00421 // Along the ith axis, every inc[i]'th element is chosen. 00422 Array<T> operator()(const IPosition &start, 00423 const IPosition &end, 00424 const IPosition &inc); 00425 const Array<T> operator()(const IPosition &start, 00426 const IPosition &end, 00427 const IPosition &inc) const; 00428 // </group> 00429 00430 // Get a reference to an array section using a Slicer. 00431 // <group> 00432 Array<T> operator()(const Slicer&); 00433 const Array<T> operator()(const Slicer&) const; 00434 // </group> 00435 00436 // Get a reference to a section of an array. 00437 // This is the same as operator(). 00438 virtual ArrayBase* getSection (const Slicer&); 00439 00440 // Get the subset given by the i-th value of the last axis. So for a cube 00441 // it returns the i-th xy plane. For a Matrix it returns the i-th row. 00442 // The returned array references the original array data; its dimensionality 00443 // is one less. For a 1-dim array it still returns a 1-dim array. 00444 // <note>This function should not be used in tight loops as it is (much) 00445 // slower than iterating using begin() and end(), ArrayIter, or 00446 // ArrayAccessor.</note> 00447 Array<T> operator[] (uInt i) const; 00448 00449 00450 // The array is masked by the input LogicalArray. 00451 // This mask must conform to the array. 00452 // <group> 00453 const MaskedArray<T> operator() (const LogicalArray &mask) const; 00454 MaskedArray<T> operator() (const LogicalArray &mask); 00455 // </group> 00456 00457 // The array is masked by the input MaskedLogicalArray. 00458 // The mask is effectively the AND of the internal LogicalArray 00459 // and the internal mask of the MaskedLogicalArray. 00460 // The MaskedLogicalArray must conform to the array. 00461 // <group> 00462 const MaskedArray<T> operator() (const MaskedLogicalArray &mask) const; 00463 MaskedArray<T> operator() (const MaskedLogicalArray &mask); 00464 // </group> 00465 00466 // The number of references the underlying storage has assigned to it. 00467 // It is 1 unless there are outstanding references to the storage (e.g., 00468 // through a slice). Normally you have no need to do this since the 00469 // arrays handle all of the references for you. 00470 uInt nrefs() const; 00471 00472 // Check to see if the Array is consistent. This is about the same thing 00473 // as checking for invariants. If AIPS_DEBUG is defined, this is invoked 00474 // after construction and on entry to most member functions. 00475 virtual Bool ok() const; 00476 00477 // Are the shapes identical? 00478 // <group> 00479 Bool conform (const Array<T> &other) const 00480 { return conform2(other); } 00481 Bool conform (const MaskedArray<T> &other) const; 00482 // </group> 00483 00484 // Get a pointer to the beginning of the array. 00485 // Note that the array may not be contiguous. 00486 // <group> 00487 T* data() 00488 { return begin_p; } 00489 const T* data() const 00490 { return begin_p; } 00491 // </group> 00492 00493 // Generally use of this should be shunned, except to use a FORTRAN routine 00494 // or something similar. Because you can't know the state of the underlying 00495 // data layout (in particular, if there are increments) sometimes the 00496 // pointer returned will be to a copy, but often this won't be necessary. 00497 // A boolean is returned which tells you if this is a copy (and hence the 00498 // storage must be deleted). Note that if you don't do anything unusual, 00499 // getStorage followed by freeStorage or putStorage will do the deletion 00500 // for you (if required). e.g.: 00501 // <srcblock> 00502 // Array<Int> a(shape); ... 00503 // Bool deleteIt; Int *storage = a.getStorage(deleteIt); 00504 // foo(storage, a.nelements()); a.puStorage(storage, deleteIt); 00505 // // or a.freeStorage(storage, deleteIt) if a is const. 00506 // </srcblock> 00507 // NB: However, if you only use getStorage, you will have to delete the 00508 // pointer yourself using freeStorage(). 00509 // 00510 // It would probably be useful to have corresponding "copyin" "copyout" 00511 // functions that used a user supplied buffer. 00512 // Note that deleteIt is set in this function. 00513 // <group> 00514 T *getStorage(Bool &deleteIt); 00515 const T *getStorage(Bool &deleteIt) const; 00516 // </group> 00517 00518 // putStorage() is normally called after a call to getStorage() (cf). 00519 // The "storage" pointer is set to zero. 00520 void putStorage(T *&storage, Bool deleteAndCopy); 00521 00522 // If deleteIt is set, delete "storage". Normally freeStorage calls 00523 // will follow calls to getStorage. The reason the pointer is "const" 00524 // is because only const pointers are released from const arrays. 00525 // The "storage" pointer is set to zero. 00526 void freeStorage(const T *&storage, Bool deleteIt) const; 00527 00528 // Replace the data values with those in the pointer <src>storage</src>. 00529 // The results are undefined is storage does not point at nelements() or 00530 // more data elements. After takeStorage() is called, <src>unique()</src> 00531 // is True. 00532 // <group> 00533 virtual void takeStorage(const IPosition &shape, T *storage, 00534 StorageInitPolicy policy = COPY); 00535 // Since the pointer is const, a copy is always taken. 00536 virtual void takeStorage(const IPosition &shape, const T *storage); 00537 // </group> 00538 00539 00540 // Used to iterate through Arrays. Derived classes VectorIterator and 00541 // MatrixIterator are probably more useful. 00542 friend class ArrayIterator<T>; 00543 00544 // Create an ArrayIterator object of the correct type. 00545 virtual ArrayPositionIterator* makeIterator (uInt byDim); 00546 00547 // Needed to be a friend for Matrix<T>::reference() 00548 friend class Matrix<T>; 00549 00550 00551 // <group name=STL-iterator> 00552 // See the function begin() and end() for a detailed description 00553 // of the STL iterator capability. 00554 class BaseIteratorSTL 00555 { 00556 public: 00557 // Create the begin const_iterator object for an Array. 00558 explicit BaseIteratorSTL (const Array<T>&); 00559 // Create the end const_iterator object for an Array. 00560 // It also acts as the default constructor. 00561 explicit BaseIteratorSTL (const T* end = 0) 00562 : itsPos(end), itsLineEnd(0), itsLineIncr(0), itsLineAxis(0), 00563 itsArray(0), itsContig(False) {} 00564 00565 void nextElem() 00566 { 00567 itsPos++; 00568 if (!itsContig) { 00569 itsPos += itsLineIncr; 00570 if (itsPos > itsLineEnd) increment(); 00571 } 00572 } 00573 void nextLine() 00574 { 00575 itsPos = itsLineEnd; 00576 increment(); 00577 } 00578 00579 bool operator== (const BaseIteratorSTL& other) const 00580 { return itsPos == other.itsPos; } 00581 00582 bool operator!= (const BaseIteratorSTL& other) const 00583 { return itsPos != other.itsPos; } 00584 00585 T* getPos() 00586 { return const_cast<T*>(itsPos); } 00587 00588 friend ostream& operator<< (ostream& os, const BaseIteratorSTL& iter) 00589 { os << iter.itsPos; return os; } 00590 00591 protected: 00592 // Increment iterator for a non-contiguous array. 00593 void increment(); 00594 00595 const T* itsPos; 00596 const T* itsLineEnd; 00597 size_t itsLineIncr; 00598 uInt itsLineAxis; 00599 IPosition itsCurPos; 00600 IPosition itsLastPos; 00601 const Array<T>* itsArray; 00602 Bool itsContig; 00603 }; 00604 00605 class IteratorSTL: public BaseIteratorSTL 00606 { 00607 public: 00608 // <group name=STL-iterator-typedefs> 00609 typedef T value_type; 00610 typedef value_type* pointer; 00611 typedef value_type& reference; 00612 typedef std::size_t size_type; 00613 typedef ptrdiff_t difference_type; 00614 typedef std::forward_iterator_tag iterator_category; 00615 // </group> 00616 00617 // Create the begin iterator object for an Array. 00618 explicit IteratorSTL (Array<T>& arr) 00619 : BaseIteratorSTL (arr) {} 00620 // Create the end iterator object for an Array. 00621 // It also acts as the default constructor. 00622 explicit IteratorSTL (const T* end = 0) 00623 : BaseIteratorSTL (end) {} 00624 00625 const IteratorSTL& operator++() 00626 { 00627 this->nextElem(); 00628 return *this; 00629 } 00630 IteratorSTL operator++(int) 00631 { 00632 IteratorSTL old(*this); 00633 this->nextElem(); 00634 return old; 00635 } 00636 00637 T& operator*() 00638 { return *this->getPos(); } 00639 T* operator->() 00640 { return this->getPos(); } 00641 }; 00642 00643 class ConstIteratorSTL: public BaseIteratorSTL 00644 { 00645 public: 00646 // <group name=STL-iterator-typedefs> 00647 typedef T value_type; 00648 typedef const value_type* pointer; 00649 typedef const value_type& reference; 00650 typedef std::size_t size_type; 00651 typedef ptrdiff_t difference_type; 00652 typedef std::forward_iterator_tag iterator_category; 00653 // </group> 00654 00655 // Create the begin const_iterator object for an Array. 00656 explicit ConstIteratorSTL (const Array<T>& arr) 00657 : BaseIteratorSTL (arr) {} 00658 // Create the end const_iterator object for an Array. 00659 // It also acts as the default constructor. 00660 explicit ConstIteratorSTL (const T* end = 0) 00661 : BaseIteratorSTL (end) {} 00662 // Create from a non-const iterator. 00663 ConstIteratorSTL (const IteratorSTL& iter) 00664 : BaseIteratorSTL (iter) {} 00665 00666 const ConstIteratorSTL& operator++() 00667 { 00668 this->nextElem(); 00669 return *this; 00670 } 00671 ConstIteratorSTL operator++(int) 00672 { 00673 ConstIteratorSTL old(*this); 00674 this->nextElem(); 00675 return old; 00676 } 00677 00678 const T& operator*() const 00679 { return *this->itsPos; } 00680 const T* operator->() 00681 { return this->itsPos; } 00682 00683 const T* pos() const 00684 { return this->itsPos; } 00685 }; 00686 // </group> 00687 00688 // Define the STL-style iterator functions (only forward iterator). 00689 // It makes it possible to iterate through all data elements of an array 00690 // and to use it common STL functions. 00691 // The end() function is relatively expensive, so it should not be 00692 // used inside a for statement. It is much better to call it beforehand 00693 // as shown in the example below. Furthermore it is very important to 00694 // use <src>++iter</src>, because <src>iter++</src> is 4 times slower. 00695 // <srcblock> 00696 // Array<Int> arr(shape); 00697 // Array<Int>::iterator iterend(arr.end()); 00698 // for (Array<Int>::iterator iter=arr.begin(); iter!=iterend; ++iter) { 00699 // *iter += 1; 00700 // } 00701 // </srcblock> 00702 // The Array class supports random access, so in principle a random 00703 // iterator could be implemented, but its performance would not be great, 00704 // especially for non-contiguous arrays. 00705 // <br>Some other STL like functions exist for performance reasons. 00706 // If the array is contiguous, it is possible to use the 00707 // <src>cbegin</src> and <src>cend</src> functions which are 00708 // about 10% faster. 00709 // <group name=STL-iterator> 00710 // STL-style typedefs. 00711 // <group> 00712 typedef T value_type; 00713 typedef IteratorSTL iterator; 00714 typedef ConstIteratorSTL const_iterator; 00715 typedef T* contiter; 00716 typedef const T* const_contiter; 00717 // </group> 00718 // Get the begin iterator object for any array. 00719 // <group> 00720 iterator begin() 00721 { return iterator (*this); } 00722 const_iterator begin() const 00723 { return const_iterator (*this); } 00724 iterator end() 00725 { return iterator(end_p); } 00726 const_iterator end() const 00727 { return const_iterator(end_p); } 00728 // </group> 00729 00730 // Get the begin iterator object for a contiguous array. 00731 // <group> 00732 contiter cbegin() 00733 { return begin_p; } 00734 const_contiter cbegin() const 00735 { return begin_p; } 00736 contiter cend() 00737 { return end_p; } 00738 const_contiter cend() const 00739 { return end_p; } 00740 // </group> 00741 00742 // </group> 00743 00744 00745 protected: 00746 // Remove the degenerate axes from the Array object. 00747 // This is the implementation of the nonDegenerate functions. 00748 // It has a different name to be able to make it virtual without having 00749 // the "hide virtual function" message when compiling derived classes. 00750 virtual void doNonDegenerate(const Array<T> &other, 00751 const IPosition &ignoreAxes); 00752 00753 00754 // Reference counted block that contains the storage. 00755 CountedPtr<Block<T> > data_p; 00756 00757 // This pointer is adjusted to point to the first element of the array. 00758 // It is not necessarily the same thing as data->storage() since 00759 // this array might be a section, e.g. have a blc which shifts us forward 00760 // into the block. 00761 T *begin_p; 00762 00763 // The end for an STL-style iteration. 00764 T* end_p; 00765 00766 00767 // Fill the steps and the end for a derived class. 00768 void makeSteps() 00769 { baseMakeSteps(); this->setEndIter(); } 00770 00771 // Set the end iterator. 00772 void setEndIter() 00773 { end_p = (nels_p==0 ? 0 : (contiguous_p ? begin_p + nels_p : 00774 begin_p + size_t(length_p(ndim()-1)) * steps_p(ndim()-1))); } 00775 }; 00776 00777 }//#End casa namespace 00778 #ifndef CASACORE_NO_AUTO_TEMPLATES 00779 #include <casa/Arrays/Array.tcc> 00780 #endif //# CASACORE_NO_AUTO_TEMPLATES 00781 #endif