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,2015 00003 //# Associated Universities, Inc. Washington DC, USA, 00004 //# National Astronomical Observatory of Japan 00005 //# 2-21-1, Osawa, Mitaka, Tokyo, 181-8588, Japan. 00006 //# 00007 //# This library is free software; you can redistribute it and/or modify it 00008 //# under the terms of the GNU Library General Public License as published by 00009 //# the Free Software Foundation; either version 2 of the License, or (at your 00010 //# option) any later version. 00011 //# 00012 //# This library is distributed in the hope that it will be useful, but WITHOUT 00013 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00015 //# License for more details. 00016 //# 00017 //# You should have received a copy of the GNU Library General Public License 00018 //# along with this library; if not, write to the Free Software Foundation, 00019 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00020 //# 00021 //# Correspondence concerning AIPS++ should be addressed as follows: 00022 //# Internet email: aips2-request@nrao.edu. 00023 //# Postal address: AIPS++ Project Office 00024 //# National Radio Astronomy Observatory 00025 //# 520 Edgemont Road 00026 //# Charlottesville, VA 22903-2475 USA 00027 //# 00028 //# $Id: Array.h 21545 2015-01-22 19:36:35Z gervandiepen $ 00029 00030 #ifndef CASA_ARRAY_H 00031 #define CASA_ARRAY_H 00032 00033 //# Includes 00034 #include <casacore/casa/aips.h> 00035 #include <casacore/casa/Arrays/ArrayBase.h> 00036 #include <casacore/casa/Containers/Block.h> 00037 #include <casacore/casa/Utilities/CountedPtr.h> 00038 #include <casacore/casa/Arrays/MaskLogiArrFwd.h> 00039 #include <casacore/casa/Arrays/IPosition.h> 00040 #include <casacore/casa/ostream.h> 00041 #include <iterator> 00042 #if defined(WHATEVER_VECTOR_FORWARD_DEC) 00043 WHATEVER_VECTOR_FORWARD_DEC; 00044 #else 00045 #include <casacore/casa/stdvector.h> 00046 #endif 00047 00048 namespace casacore { //#Begin casa namespace 00049 //# Forward Declarations 00050 class AipsIO; 00051 class Slice; 00052 class Slicer; 00053 template<class T> class Matrix; 00054 template<class T> class ArrayIterator; 00055 template<class T> class MaskedArray; 00056 template<class Domain, class Range> class Functional; 00057 //template <class T, class U> class vector; 00058 00059 00060 // <summary> A templated N-D Array class with zero origin </summary> 00061 00062 // Array<T> is a templated, N-dimensional, Array class. The origin is zero, 00063 // but by default indices are zero-based. This Array class is the 00064 // base class for specialized Vector<T>, Matrix<T>, and Cube<T> classes. 00065 // 00066 // Indexing into the array, and positions in general, are given with IPosition 00067 // (essentially a vector of integers) objects. That is, an N-dimensional 00068 // array requires a length-N IPosition to define a position within the array. 00069 // Unlike C, indexing is done with (), not []. Also, the storage order 00070 // is the same as in FORTRAN, i.e. memory varies most rapidly with the first 00071 // index. 00072 // <srcblock> 00073 // // axisLengths = [1,2,3,4,5] 00074 // IPosition axisLengths(5, 1, 2, 3, 4, 5); 00075 // Array<Int> ai(axisLengths); // ai is a 5 dimensional array of 00076 // // integers; indices are 0-based 00077 // // => ai.nelements() == 120 00078 // Array<Int> ai2(axisLengths); // The first element is at index 0 00079 // IPosition zero(5); zero = 0; // [0,0,0,0,0] 00080 // //... 00081 // </srcblock> 00082 // Indexing into an N-dimensional array is relatively expensive. Normally 00083 // you will index into a Vector, Matrix, or Cube. These may be obtained from 00084 // an N-dimensional array by creating a reference, or by using an 00085 // ArrayIterator. The "shape" of the array is an IPosition which gives the 00086 // length of each axis. 00087 // 00088 // An Array may be standalone, or it may refer to another array, or to 00089 // part of another array (by refer we mean that if you change a pixel in 00090 // the current array, a pixel in the referred to array also changes, i.e. 00091 // they share underlying storage). 00092 // <note role=warning> 00093 // One way one array can reference another is through the copy 00094 // constructor. While this might be what you want, you should 00095 // probably use the reference() member function to make it explicit. 00096 // The copy constructor is used when arguments are passed by value; 00097 // normally functions should not pass Arrays by value, rather they 00098 // should pass a reference or a const reference. On the positive 00099 // side, returning an array from a function is efficient since no 00100 // copying need be done. 00101 // </note> 00102 // 00103 // Aside from the explicit reference() member function, a user will 00104 // most commonly encounter an array which references another array 00105 // when he takes an array slice (or section). A slice is a sub-region of 00106 // an array (which might also have a stride: every nth row, every mth column, 00107 // ...). 00108 // <srcblock> 00109 // IPosition lengths(3,10,20,30); 00110 // Array<Int> ai(lengths); // A 10x20x30 cube 00111 // Cube<Int> ci; 00112 // //... 00113 // ci.reference(ai1); // ci and ai now reference the same 00114 // // storage 00115 // ci(0,0,0) = 123; // Can use Cube indexing 00116 // ci.xyPlane(2) = 0; // and other member functions 00117 // IPosition zero(3,0,0,0); 00118 // assert(ai(zero) == 123); // True because ai, ci are references 00119 // //... 00120 // Array<Int> subArray; 00121 // IPosition blc(3,0,0,0), trc(3,5,5,5); 00122 // subArray.reference(ai(blc, trc)); 00123 // subArray = 10; // All of subArray, which is the 00124 // // subcube from 0,0,0 to 5,5,5 in 00125 // // ai, has the value 10. 00126 // </srcblock> 00127 // While the last example has an array slice referenced explicitly by another 00128 // array variable, normally the user will often only use the slice as 00129 // a temporary in an expresion, for example: 00130 // <srcblock> 00131 // Array<Complex> array; 00132 // IPosition blc, trc, offset; 00133 // //... 00134 // // Copy from one region of the array into another 00135 // array(blc, trc) = array(blc+offset, trc+offset); 00136 // </srcblock> 00137 // 00138 // The Array classes are intended to operate on relatively large 00139 // amounts of data. While they haven't been extensively tuned yet, 00140 // they are relatively efficient in terms of speed. Presently they 00141 // are not space efficient -- the overhead is about 15 words. While 00142 // this will be improved (probably to about 1/2 that), these array 00143 // classes are not appropriate for very large numbers of very small 00144 // arrays. The Block<T> class may be what you want in this circumstance. 00145 // 00146 // Element by element mathematical and logical operations are available 00147 // for arrays (defined in aips/ArrayMath.h and aips/ArrayLogical.h). 00148 // Because arithmetic and logical functions are split out, it is possible 00149 // to create an Array<T> (and hence Vector<T> etc) for any type T that has 00150 // a default constructor, assignment operator, and copy constructor. In 00151 // particular, Array<String> works. 00152 // 00153 // If compiled with the preprocessor symbol AIPS_DEBUG symbol, array 00154 // consistency ("invariants") will be checked in most member 00155 // functions, and indexing will be range-checked. This should not be 00156 // defined for production runs. 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 // Storage will be allocated by <src>DefaultAllocator<T></src>. 00175 Array(); 00176 00177 // Create an array of the given shape, i.e. after construction 00178 // array.ndim() == shape.nelements() and array.shape() == shape. 00179 // The origin of the Array is zero. 00180 // Storage is allocated by <src>DefaultAllocator<T></src>. 00181 // Without initPolicy parameter, the initialization of elements depends on type <src>T</src>. 00182 // When <src>T</src> is a fundamental type like <src>int</src>, elements are NOT initialized. 00183 // When <src>T</src> is a class type like <src>casa::Complex</src> or <src>std::string</src>, elements are initialized. 00184 // This inconsistent behavior confuses programmers and make it hard to write efficient and generic code using template. 00185 // Especially when <src>T</src> is of type <src>Complex</src> or <src>DComplex</src> and it is unnecessary to initialize, 00186 // provide initPolicy with value <src>NO_INIT</src> to skip the initialization. 00187 // Therefore, it is strongly recommended to explicitly provide initPolicy parameter, 00188 explicit Array(const IPosition &shape); 00189 00190 // Create an array of the given shape, i.e. after construction 00191 // array.ndim() == shape.nelements() and array.shape() == shape. 00192 // The origin of the Array is zero. 00193 // Storage is allocated by <src>DefaultAllocator<T></src>. 00194 // When initPolicy parameter is <src>INIT</src>, elements are initialized with the default value of <src>T()</src>. 00195 // When initPolicy parameter is <src>NO_INIT</src>, elements are NOT initialized and programmers are responsible to 00196 // initialize elements before they are referred, especially when <src>T</src> is such type like <src>std::string</src>. 00197 // <srcblock> 00198 // IPosition shape(1, 10); 00199 // Array<Int> ai(shape, ArrayInitPolicy::NO_INIT); 00200 // size_t nread = fread(ai.data(), sizeof(Int), ai.nelements(), fp); 00201 // </srcblock> 00202 Array(const IPosition &shape, ArrayInitPolicy initPolicy); 00203 00204 // Create an array of the given shape and initialize it with the 00205 // initial value. 00206 // Storage is allocated by <src>DefaultAllocator<T></src>. 00207 Array(const IPosition &shape, const T &initialValue); 00208 00209 // After construction, this and other reference the same storage. 00210 Array(const Array<T> &other); 00211 00212 // Create an Array of a given shape from a pointer. 00213 // If <src>policy</src> is <src>COPY</src>, storage of a new copy is allocated by <src>DefaultAllocator<T></src>. 00214 // If <src>policy</src> is <src>TAKE_OVER</src>, <src>storage</src> will be destructed and released by <src>NewDelAllocator<T></src>. 00215 // It is strongly recommended to supply an appropriate <src>allocator</src> argument explicitly 00216 // whenever <src>policy</src> == <src>TAKE_OVER</src> 00217 // to let <src>Array</src> to know how to release the <src>storage</src>. 00218 Array(const IPosition &shape, T *storage, StorageInitPolicy policy = COPY); 00219 00220 // Create an Array of a given shape from a pointer. 00221 // If <src>policy</src> is <src>COPY</src>, storage of a new copy is allocated by the specified allocator. 00222 // If <src>policy</src> is <src>TAKE_OVER</src>, <src>storage</src> will be destructed and released by the specified allocator. 00223 // Otherwise, <src>allocator</src> is ignored. 00224 // It is strongly recommended to allocate and initialize <src>storage</src> with <src>DefaultAllocator<T></src> 00225 // rather than new[] or <src>NewDelAllocator<T></src> because new[] can't decouple allocation and initialization. 00226 // <src>DefaultAllocator<T>::type</src> is a subclass of std::allocator. You can allocate <src>storage</src> via 00227 // the allocator as below. 00228 // <srcblock> 00229 // FILE *fp = ...; 00230 // typedef DefaultAllocator<Int> Alloc; 00231 // Alloc::type alloc; 00232 // IPosition shape(1, 10); 00233 // Int *ptr = alloc.allocate(shape.product()); 00234 // size_t nread = fread(ptr, sizeof(Int), shape.product(), fp); 00235 // Array<Int> ai(shape, ptr, TAKE_OVER, Alloc::value); 00236 // </srcblock> 00237 Array(const IPosition &shape, T *storage, StorageInitPolicy policy, AbstractAllocator<T> const &allocator); 00238 00239 // Create an Array of a given shape from a pointer. Because the pointer 00240 // is const, a copy is always made. 00241 // The copy is allocated by <src>DefaultAllocator<T></src>. 00242 Array(const IPosition &shape, const T *storage); 00243 00244 // Frees up storage only if this array was the last reference to it. 00245 virtual ~Array(); 00246 00247 // Make an empty array of the same template type. 00248 virtual CountedPtr<ArrayBase> makeArray() const; 00249 00250 // Assign the other array to this array. 00251 // If the shapes mismatch, this array is resized. 00252 // <group> 00253 virtual void assign (const Array<T>& other); 00254 virtual void assignBase (const ArrayBase& other, Bool checkType=True); 00255 // </group> 00256 00257 // Set every element of the array to "value." Also could use the 00258 // assignment operator which assigns an array from a scalar. 00259 void set(const T &value); 00260 00261 // Apply the function to every element of the array. This modifies 00262 // the array in place. 00263 // <group> 00264 // This version takes a function which takes a T and returns a T. 00265 void apply(T (*function)(T)); 00266 // This version takes a function which takes a const T reference and 00267 // returns a T. 00268 void apply(T (*function)(const T &)); 00269 // This version applies a functional. 00270 void apply(const Functional<T,T> &function); 00271 // </group> 00272 00273 // After invocation, this array and other reference the same storage. That 00274 // is, modifying an element through one will show up in the other. The 00275 // arrays appear to be identical; they have the same shape. 00276 // <br>Please note that this function makes it possible to reference a 00277 // const Array, thus effectively it makes a const Array non-const. 00278 // Although this may seem undesirable at first sight, it is necessary to 00279 // be able to make references to temporary Array objects, in particular to 00280 // Array slices. Otherwise one first needs to use the copy constructor. 00281 //# The const has been introduced on 2005-Mar-31 because of the hassle 00282 //# involved in calling the copy ctor before reference. 00283 virtual void reference(const Array<T> &other); 00284 00285 // Copy the values in other to this. If the array on the left hand 00286 // side has no elements, then it is resized to be the same size as 00287 // as the array on the right hand side. Otherwise, the arrays must 00288 // conform (same shapes). 00289 // <srcblock> 00290 // IPosition shape(2,10,10); // some shape 00291 // Array<Double> ad(shape); 00292 // //... 00293 // Array<Double> ad2; // N.B. ad2.nelements() == 0 00294 // ad2 = ad; // ad2 resizes, then elements 00295 // // are copied. 00296 // shape = 20; 00297 // Array<Double> ad3(shape); 00298 // ad3 = ad; // Error: arrays do not conform 00299 // </srcblock> 00300 // Note that the assign function can be used to assign a 00301 // non-conforming array. 00302 virtual Array<T> &operator=(const Array<T> &other); 00303 00304 // Set every element of this array to "value". In other words, a scalar 00305 // behaves as if it were a constant conformant array. 00306 Array<T> &operator=(const T &value); 00307 00308 // Copy to this those values in marray whose corresponding elements 00309 // in marray's mask are True. 00310 // 00311 // <thrown> 00312 // <li> ArrayConformanceError 00313 // </thrown> 00314 // 00315 Array<T> &operator= (const MaskedArray<T> &marray); 00316 00317 // This makes a copy of the array and returns it. This can be 00318 // useful for, e.g. making working copies of function arguments 00319 // that you can write into. 00320 // <srcblock> 00321 // void someFunction(const Array<Int> &arg) 00322 // { 00323 // Array<Int> tmp(arg.copy()); 00324 // // ... 00325 // } 00326 // </srcblock> 00327 // Note that since the copy constructor makes a reference, if we just 00328 // created used to copy constructor, modifying "tmp" would also 00329 // modify "arg". Clearly another alternative would simply be: 00330 // <srcblock> 00331 // void someFunction(const Array<Int> &arg) 00332 // { 00333 // Array<Int> tmp; 00334 // tmp = arg; 00335 // // ... 00336 // } 00337 // </srcblock> 00338 // which likely would be simpler to understand. (Should copy() 00339 // be deprecated and removed?) 00340 // 00341 Array<T> copy(ArrayInitPolicy policy = ArrayInitPolicy::NO_INIT) const; // Make a copy of this 00342 00343 // This function copies the matching part of from array to this array. 00344 // The matching part is the part with the minimum size for each axis. 00345 // E.g. if this array has shape [4,5,6] and from array has shape [7,3], 00346 // the matching part has shape [4,3]. 00347 // <br>Note it is used by the resize function if 00348 // <src>copyValues==True</src>. 00349 void copyMatchingPart (const Array<T> &from); 00350 00351 // This ensures that this array does not reference any other storage. 00352 // <note role=tip> 00353 // When a section is taken of an array with non-unity strides, 00354 // storage can be wasted if the array, which originally contained 00355 // all the data, goes away. unique() also reclaims storage. This 00356 // is an optimization users don't normally need to understand. 00357 // 00358 // <srcblock> 00359 // IPosition shape(...), blc(...), trc(...), inc(...); 00360 // Array<Float> af(shape); 00361 // inc = 2; // or anything > 1 00362 // Array<Float> aSection.reference(af(blc, trc, inc)); 00363 // af.reference(anotherArray); 00364 // // aSection now references storage that has a stride 00365 // // in it, but nothing else is. Storage is wasted. 00366 // aSection.unique(); 00367 // </srcblock> 00368 // </note> 00369 void unique(); 00370 00371 // Create an STL vector from an Array. The created vector is a linear 00372 // representation of the Array memory. See 00373 // <linkto class=Vector>Vector</linkto> for 00374 // details of the operation and its reverse (i.e. creating a 00375 // <src>Vector</src> from a <src>vector</src>), and for details of 00376 // definition and instantiation. 00377 // <group> 00378 template <class U> 00379 void tovector(vector<T, U> &out) const; 00380 00381 vector<T> tovector() const; 00382 // </group> 00383 00384 // It is occasionally useful to have an array which access the same 00385 // storage appear to have a different shape. For example, 00386 // turning an N-dimensional array into a Vector. 00387 // <br>When the array data are contiguous, the array can be reshaped 00388 // to any form as long as the number of elements stays the same. 00389 // When not contiguous, it is only possible to remove or add axes 00390 // with length 1. 00391 // <srcblock> 00392 // IPosition squareShape(2,5,5); 00393 // Array<Float> square(squareShape); 00394 // IPosition lineShape(1,25); 00395 // Vector<Float> line(square.reform(lineShape)); 00396 // // "square"'s storage may now be accessed through Vector "line" 00397 // </srcblock> 00398 Array<T> reform(const IPosition &shape) const; 00399 00400 // Having an array that can be reused without requiring reallocation can 00401 // be useful for large arrays. The method reformOrResize permits this 00402 // usage. 00403 // 00404 // The reformOrResize method first attempts to reform the matrix so that 00405 // it reuses the existing storage for an array with a new shape. If the 00406 // existing storage will not hold the new shape, then the method will 00407 // resize the array when resizeIfNeeded is true; if a resize is needed and 00408 // resizeIfNeeded is false, then an ArrayConformanceError is thrown. The 00409 // copyDataIfNeeded parameter is passed to resize if resizing is performed. 00410 // resizePercentage is the percent of additional storage to be addeed when 00411 // a resize is performed; this allows the allocations to be amortized when 00412 // the caller expects to be calling this method again in the future. The 00413 // parameter is used to define an allocation shape which is larger than 00414 // the newShape by increasing the last dimension by resizePercentage percent 00415 // (i.e., lastDim = (lastDim * (100 + resizePercentage)) / 100). If 00416 // resizePercentage <= 0 then resizing uses newShape as-is. Returns true 00417 // if resizing (allocation) was performed. 00418 // 00419 // To truncate the array so that it no longer holds additional storage, 00420 // use the resize method. 00421 // 00422 // Array may not be shared with another Array object during this call. 00423 // Exception thrown if it is shared. 00424 00425 bool reformOrResize (const IPosition & newShape, 00426 uInt resizePercentage = 0, 00427 Bool resizeIfNeeded = True); 00428 00429 // Use this method to extend or reduce the last dimension of an array. If 00430 // sufficient excess capacity exists then the bookkeeping is adjusted to 00431 // support the new shape. If insufficient storage exists then a new array 00432 // is allocated (unless resizeIfNeeded is false; then an exception is thrown). 00433 // If resizing is not required then the data remains untouched; if resizing 00434 // is required then the data is copied into the new storage. The resizePercentage 00435 // works the same as for reformOrResize (see above). This method never releases 00436 // extra storage; use "resize" to do this. Array may not be sharing storage 00437 // with another array at call time; an exception will be thrown if the array is shared. 00438 // Returns true if the array was extension required a Array<T>::resize operation. 00439 00440 bool adjustLastAxis (const IPosition & newShape, 00441 uInt resizePercentage = 0, 00442 bool resizeIfNeeded = True); 00443 00444 // Returns the number of elements allocated. This value is >= to the value returned 00445 // by size(). 00446 00447 size_t capacity () const; 00448 00449 // These member functions remove degenerate (ie. length==1) axes from 00450 // Arrays. Only axes greater than startingAxis are considered (normally 00451 // one wants to remove trailing axes). The first two of these functions 00452 // return an Array reference with axes removed. The latter two functions 00453 // let this Array object reference the 'other' array with degenerated axes 00454 // removed. 00455 // <br> 00456 // Unless throwIfError is False, an exception will be thrown if 00457 // startingAxis exceeds the array's dimensionality. 00458 // <br> 00459 // The functions with argument <src>ignoreAxes</src> do 00460 // not consider the axes given in that argument. In this way it can be 00461 // achieved that degenerate axes are kept. 00462 // <note role=caution> When the two functions returning <src>void</src> 00463 // are invoked on a derived object (e.g. Matrix), an exception is 00464 // thrown if removing the degenerate axes from other does not result 00465 // in a correct number of axes. 00466 // </note> 00467 // <group> 00468 Array<T> nonDegenerate(uInt startingAxis=0, Bool throwIfError=True) const; 00469 Array<T> nonDegenerate(const IPosition& ignoreAxes) const; 00470 void nonDegenerate(const Array<T> &other, uInt startingAxis=0, 00471 Bool throwIfError=True); 00472 void nonDegenerate(const Array<T> &other, const IPosition &ignoreAxes) 00473 { doNonDegenerate (other, ignoreAxes); } 00474 // </group> 00475 00476 // Remove degenerate axes from this Array object. 00477 // Note it does not make sense to use these functions on a derived object 00478 // like Matrix, because it is not possible to remove axes from them. 00479 // <group> 00480 void removeDegenerate(uInt startingAxis=0, 00481 Bool throwIfError=True); 00482 void removeDegenerate(const IPosition &ignoreAxes); 00483 // </group> 00484 00485 // This member function returns an Array reference with the specified 00486 // number of extra axes, all of length one, appended to the end of the 00487 // Array. Note that the <src>reform</src> function can also be 00488 // used to add extra axes. 00489 // <group> 00490 const Array<T> addDegenerate(uInt numAxes) const; 00491 Array<T> addDegenerate(uInt numAxes); 00492 // </group> 00493 00494 // Make this array a different shape. If <src>copyValues==True</src> 00495 // the old values are copied over to the new array. 00496 // Copying is done on a per axis basis, thus a subsection with the 00497 // minimum of the old and new shape is copied. 00498 // <br>Resize without argument is equal to resize(IPosition()). 00499 // <br>It is important to note that if multiple Array objects 00500 // reference the same data storage, this Array object still references 00501 // the same data storage as the other Array objects if the shape does 00502 // not change. Otherwise this Array object references newly allocated 00503 // storage, while the other Array objects still reference the existing 00504 // data storage. 00505 // <br>If you want to be sure that the data storage of this Array object 00506 // is not referenced by other Array objects, the function unique should 00507 // be called first. 00508 // <group> 00509 virtual void resize(); 00510 virtual void resize(const IPosition &newShape, Bool copyValues=False); 00511 virtual void resize(const IPosition &newShape, Bool copyValues, ArrayInitPolicy policy); 00512 // </group> 00513 00514 // Access a single element of the array. This is relatively 00515 // expensive. Extensive indexing should be done through one 00516 // of the Array specializations (Vector, Matrix, Cube). If 00517 // AIPS_DEBUG is defined, index checking will be performed. 00518 // <group> 00519 T &operator()(const IPosition &); 00520 const T &operator()(const IPosition &) const; 00521 // </group> 00522 00523 // Get a reference to an array section extending 00524 // from start to end (inclusive). 00525 // <group> 00526 Array<T> operator()(const IPosition &start, 00527 const IPosition &end); 00528 const Array<T> operator()(const IPosition &start, 00529 const IPosition &end) const; 00530 // Along the ith axis, every inc[i]'th element is chosen. 00531 Array<T> operator()(const IPosition &start, 00532 const IPosition &end, 00533 const IPosition &inc); 00534 const Array<T> operator()(const IPosition &start, 00535 const IPosition &end, 00536 const IPosition &inc) const; 00537 // </group> 00538 00539 // Get a reference to an array section using a Slicer. 00540 // <group> 00541 Array<T> operator()(const Slicer&); 00542 const Array<T> operator()(const Slicer&) const; 00543 // </group> 00544 00545 // Get a reference to a section of an array. 00546 // This is the same as operator(), but can be used in a type-agnostic way. 00547 virtual CountedPtr<ArrayBase> getSection (const Slicer&) const; 00548 00549 // Get the subset given by the i-th value of the last axis. So for a cube 00550 // it returns the i-th xy plane. For a Matrix it returns the i-th row. 00551 // The returned array references the original array data; its dimensionality 00552 // is one less. For a 1-dim array it still returns a 1-dim array. 00553 // <note>This function should not be used in tight loops as it is (much) 00554 // slower than iterating using begin() and end(), ArrayIter, or 00555 // ArrayAccessor.</note> 00556 Array<T> operator[] (size_t i) const; 00557 00558 // Get the diagonal of each matrix part in the full array. 00559 // The matrices are taken using axes firstAxes and firstAxis+1. 00560 // diag==0 is main diagonal; diag>0 above the main diagonal; diag<0 below. 00561 Array<T> diagonals (uInt firstAxis=0, Int64 diag=0) const; 00562 00563 // The array is masked by the input LogicalArray. 00564 // This mask must conform to the array. 00565 // <group> 00566 const MaskedArray<T> operator() (const LogicalArray &mask) const; 00567 MaskedArray<T> operator() (const LogicalArray &mask); 00568 // </group> 00569 00570 // The array is masked by the input MaskedLogicalArray. 00571 // The mask is effectively the AND of the internal LogicalArray 00572 // and the internal mask of the MaskedLogicalArray. 00573 // The MaskedLogicalArray must conform to the array. 00574 // <group> 00575 const MaskedArray<T> operator() (const MaskedLogicalArray &mask) const; 00576 MaskedArray<T> operator() (const MaskedLogicalArray &mask); 00577 // </group> 00578 00579 // The number of references the underlying storage has assigned to it. 00580 // It is 1 unless there are outstanding references to the storage (e.g., 00581 // through a slice). Normally you have no need to do this since the 00582 // arrays handle all of the references for you. 00583 uInt nrefs() const; 00584 00585 // Check to see if the Array is consistent. This is about the same thing 00586 // as checking for invariants. If AIPS_DEBUG is defined, this is invoked 00587 // after construction and on entry to most member functions. 00588 virtual Bool ok() const; 00589 00590 // Are the shapes identical? 00591 // <group> 00592 Bool conform (const Array<T> &other) const 00593 { return conform2(other); } 00594 Bool conform (const MaskedArray<T> &other) const; 00595 // </group> 00596 00597 // Get a pointer to the beginning of the array. 00598 // Note that the array may not be contiguous. 00599 // <group> 00600 T* data() 00601 { return begin_p; } 00602 const T* data() const 00603 { return begin_p; } 00604 // </group> 00605 00606 // Generally use of this should be shunned, except to use a FORTRAN routine 00607 // or something similar. Because you can't know the state of the underlying 00608 // data layout (in particular, if there are increments) sometimes the 00609 // pointer returned will be to a copy, but often this won't be necessary. 00610 // A boolean is returned which tells you if this is a copy (and hence the 00611 // storage must be deleted). Note that if you don't do anything unusual, 00612 // getStorage followed by freeStorage or putStorage will do the deletion 00613 // for you (if required). e.g.: 00614 // <srcblock> 00615 // Array<Int> a(shape); ... 00616 // Bool deleteIt; Int *storage = a.getStorage(deleteIt); 00617 // foo(storage, a.nelements()); a.puStorage(storage, deleteIt); 00618 // // or a.freeStorage(storage, deleteIt) if a is const. 00619 // </srcblock> 00620 // NB: However, if you only use getStorage, you will have to delete the 00621 // pointer yourself using freeStorage(). 00622 // 00623 // It would probably be useful to have corresponding "copyin" "copyout" 00624 // functions that used a user supplied buffer. 00625 // Note that deleteIt is set in this function. 00626 // <group> 00627 T *getStorage(Bool &deleteIt); 00628 const T *getStorage(Bool &deleteIt) const 00629 { 00630 // The cast is OK because the return pointer will be cast to const 00631 return const_cast<Array<T>*>(this)->getStorage(deleteIt); 00632 } 00633 virtual void *getVStorage(Bool &deleteIt); 00634 virtual const void *getVStorage(Bool &deleteIt) const; 00635 // </group> 00636 00637 // putStorage() is normally called after a call to getStorage() (cf). 00638 // The "storage" pointer is set to zero. 00639 void putStorage(T *&storage, Bool deleteAndCopy); 00640 virtual void putVStorage(void *&storage, Bool deleteAndCopy); 00641 00642 // If deleteIt is set, delete "storage". Normally freeStorage calls 00643 // will follow calls to getStorage. The reason the pointer is "const" 00644 // is because only const pointers are released from const arrays. 00645 // The "storage" pointer is set to zero. 00646 void freeStorage(const T *&storage, Bool deleteIt) const; 00647 void freeVStorage(const void *&storage, Bool deleteIt) const; 00648 00649 // Replace the data values with those in the pointer <src>storage</src>. 00650 // The results are undefined if storage does not point at nelements() or 00651 // more data elements. After takeStorage() is called, <src>nrefs()</src> 00652 // is 1. 00653 // <group> 00654 // If <src>policy</src> is <src>COPY</src>, storage of a new copy is allocated by <src>DefaultAllocator<T></src>. 00655 // If <src>policy</src> is <src>TAKE_OVER</src>, <src>storage</src> will be destructed and released by <src>NewDelAllocator<T></src>. 00656 // It is strongly recommended to supply an appropriate <src>allocator</src> argument explicitly 00657 // whenever <src>policy</src> == <src>TAKE_OVER</src> 00658 // to let <src>Array</src> to know how to release the <src>storage</src>. 00659 virtual void takeStorage(const IPosition &shape, T *storage, 00660 StorageInitPolicy policy = COPY); 00661 00662 // If <src>policy</src> is <src>COPY</src>, storage of a new copy is allocated by <src>allocator</src>. 00663 // If <src>policy</src> is <src>TAKE_OVER</src>, <src>storage</src> will be destructed and released by <src>allocator</src>. 00664 // Otherwise, <src>storage</src> is ignored. 00665 virtual void takeStorage(const IPosition &shape, T *storage, 00666 StorageInitPolicy policy, AbstractAllocator<T> const &allocator); 00667 00668 // Since the pointer is const, a copy is always taken. 00669 // Storage of a new copy is allocated by <src>DefaultAllocator<T></src>. 00670 virtual void takeStorage(const IPosition &shape, const T *storage); 00671 00672 // Since the pointer is const, a copy is always taken. 00673 // Storage of a new copy is allocated by the specified allocator. 00674 virtual void takeStorage(const IPosition &shape, const T *storage, 00675 AbstractAllocator<T> const &allocator); 00676 // </group> 00677 00678 00679 // Used to iterate through Arrays. Derived classes VectorIterator and 00680 // MatrixIterator are probably more useful. 00681 friend class ArrayIterator<T>; 00682 00683 // Create an ArrayIterator object of the correct type. 00684 virtual CountedPtr<ArrayPositionIterator> makeIterator (uInt byDim) const; 00685 00686 // Needed to be a friend for Matrix<T>::reference() 00687 friend class Matrix<T>; 00688 00689 00690 // <group name=STL-iterator> 00691 // See the function begin() and end() for a detailed description 00692 // of the STL iterator capability. 00693 class BaseIteratorSTL 00694 { 00695 public: 00696 // Create the begin const_iterator object for an Array. 00697 explicit BaseIteratorSTL (const Array<T>&); 00698 // Create the end const_iterator object for an Array. 00699 // It also acts as the default constructor. 00700 explicit BaseIteratorSTL (const T* end = 0) 00701 : itsPos(end), itsLineEnd(0), itsLineIncr(0), itsLineAxis(0), 00702 itsArray(0), itsContig(False) {} 00703 00704 void nextElem() 00705 { 00706 itsPos++; 00707 if (!itsContig) { 00708 itsPos += itsLineIncr; 00709 if (itsPos > itsLineEnd) increment(); 00710 } 00711 } 00712 void nextLine() 00713 { 00714 itsPos = itsLineEnd; 00715 increment(); 00716 } 00717 00718 bool operator== (const BaseIteratorSTL& other) const 00719 { return itsPos == other.itsPos; } 00720 00721 bool operator!= (const BaseIteratorSTL& other) const 00722 { return itsPos != other.itsPos; } 00723 00724 T* getPos() 00725 { return const_cast<T*>(itsPos); } 00726 00727 friend ostream& operator<< (ostream& os, const BaseIteratorSTL& iter) 00728 { os << iter.itsPos; return os; } 00729 00730 protected: 00731 // Increment iterator for a non-contiguous array. 00732 void increment(); 00733 00734 const T* itsPos; 00735 const T* itsLineEnd; 00736 size_t itsLineIncr; 00737 uInt itsLineAxis; 00738 IPosition itsCurPos; 00739 IPosition itsLastPos; 00740 const Array<T>* itsArray; 00741 Bool itsContig; 00742 }; 00743 00744 class IteratorSTL: public BaseIteratorSTL 00745 { 00746 public: 00747 // <group name=STL-iterator-typedefs> 00748 typedef T value_type; 00749 typedef value_type* pointer; 00750 typedef value_type& reference; 00751 typedef std::size_t size_type; 00752 typedef ptrdiff_t difference_type; 00753 typedef std::forward_iterator_tag iterator_category; 00754 // </group> 00755 00756 // Create the begin iterator object for an Array. 00757 explicit IteratorSTL (Array<T>& arr) 00758 : BaseIteratorSTL (arr) {} 00759 // Create the end iterator object for an Array. 00760 // It also acts as the default constructor. 00761 explicit IteratorSTL (const T* end = 0) 00762 : BaseIteratorSTL (end) {} 00763 00764 const IteratorSTL& operator++() 00765 { 00766 this->nextElem(); 00767 return *this; 00768 } 00769 IteratorSTL operator++(int) 00770 { 00771 IteratorSTL old(*this); 00772 this->nextElem(); 00773 return old; 00774 } 00775 00776 T& operator*() 00777 { return *this->getPos(); } 00778 T* operator->() 00779 { return this->getPos(); } 00780 }; 00781 00782 class ConstIteratorSTL: public BaseIteratorSTL 00783 { 00784 public: 00785 // <group name=STL-iterator-typedefs> 00786 typedef T value_type; 00787 typedef const value_type* pointer; 00788 typedef const value_type& reference; 00789 typedef std::size_t size_type; 00790 typedef ptrdiff_t difference_type; 00791 typedef std::forward_iterator_tag iterator_category; 00792 // </group> 00793 00794 // Create the begin const_iterator object for an Array. 00795 explicit ConstIteratorSTL (const Array<T>& arr) 00796 : BaseIteratorSTL (arr) {} 00797 // Create the end const_iterator object for an Array. 00798 // It also acts as the default constructor. 00799 explicit ConstIteratorSTL (const T* end = 0) 00800 : BaseIteratorSTL (end) {} 00801 // Create from a non-const iterator. 00802 ConstIteratorSTL (const IteratorSTL& iter) 00803 : BaseIteratorSTL (iter) {} 00804 00805 const ConstIteratorSTL& operator++() 00806 { 00807 this->nextElem(); 00808 return *this; 00809 } 00810 ConstIteratorSTL operator++(int) 00811 { 00812 ConstIteratorSTL old(*this); 00813 this->nextElem(); 00814 return old; 00815 } 00816 00817 const T& operator*() const 00818 { return *this->itsPos; } 00819 const T* operator->() 00820 { return this->itsPos; } 00821 00822 const T* pos() const 00823 { return this->itsPos; } 00824 }; 00825 // </group> 00826 00827 // Define the STL-style iterator functions (only forward iterator). 00828 // It makes it possible to iterate through all data elements of an array 00829 // and to use it common STL functions. 00830 // The end() function is relatively expensive, so it should not be 00831 // used inside a for statement. It is much better to call it beforehand 00832 // as shown in the example below. Furthermore it is very important to 00833 // use <src>++iter</src>, because <src>iter++</src> is 4 times slower. 00834 // <srcblock> 00835 // Array<Int> arr(shape); 00836 // Array<Int>::iterator iterend(arr.end()); 00837 // for (Array<Int>::iterator iter=arr.begin(); iter!=iterend; ++iter) { 00838 // *iter += 1; 00839 // } 00840 // </srcblock> 00841 // The Array class supports random access, so in principle a random 00842 // iterator could be implemented, but its performance would not be great, 00843 // especially for non-contiguous arrays. 00844 // <br>Some other STL like functions exist for performance reasons. 00845 // If the array is contiguous, it is possible to use the 00846 // <src>cbegin</src> and <src>cend</src> functions which are 00847 // about 10% faster. 00848 // <group name=STL-iterator> 00849 // STL-style typedefs. 00850 // <group> 00851 typedef T value_type; 00852 typedef IteratorSTL iterator; 00853 typedef ConstIteratorSTL const_iterator; 00854 typedef T* contiter; 00855 typedef const T* const_contiter; 00856 // </group> 00857 // Get the begin iterator object for any array. 00858 // <group> 00859 iterator begin() 00860 { return iterator (*this); } 00861 const_iterator begin() const 00862 { return const_iterator (*this); } 00863 iterator end() 00864 { return iterator(end_p); } 00865 const_iterator end() const 00866 { return const_iterator(end_p); } 00867 // </group> 00868 00869 // Get the begin iterator object for a contiguous array. 00870 // <group> 00871 contiter cbegin() 00872 { return begin_p; } 00873 const_contiter cbegin() const 00874 { return begin_p; } 00875 contiter cend() 00876 { return end_p; } 00877 const_contiter cend() const 00878 { return end_p; } 00879 // </group> 00880 00881 // </group> 00882 00883 00884 private: 00885 Array(Allocator_private::AllocSpec<T> allocator); 00886 Array(const IPosition &shape, ArrayInitPolicy initPolicy, Allocator_private::BulkAllocator<T> *allocator); 00887 // Makes a copy using the allocator. 00888 Array<T> copy(ArrayInitPolicy policy, Allocator_private::BulkAllocator<T> *allocator) const; 00889 // If the current allocator is NewDelAllocator<T>, BulkAllocator for DefaultAllocator<T> is returned, 00890 // otherwise BulkAllocator for the current allocator is returned. 00891 Allocator_private::BulkAllocator<T> *nonNewDelAllocator() const; 00892 protected: 00893 static ArrayInitPolicy defaultArrayInitPolicy() { 00894 return Block<T>::init_anyway() ? ArrayInitPolicy::INIT : ArrayInitPolicy::NO_INIT; 00895 } 00896 // pre/post processing hook of takeStorage() for subclasses. 00897 virtual void preTakeStorage(const IPosition &) {} 00898 virtual void postTakeStorage() {} 00899 static void copyToContiguousStorage(T *dst, Array<T> const & src, ArrayInitPolicy policy); 00900 00901 // Remove the degenerate axes from the Array object. 00902 // This is the implementation of the nonDegenerate functions. 00903 // It has a different name to be able to make it virtual without having 00904 // the "hide virtual function" message when compiling derived classes. 00905 virtual void doNonDegenerate(const Array<T> &other, 00906 const IPosition &ignoreAxes); 00907 00908 00909 // Reference counted block that contains the storage. 00910 CountedPtr<Block<T> > data_p; 00911 00912 // This pointer is adjusted to point to the first element of the array. 00913 // It is not necessarily the same thing as data->storage() since 00914 // this array might be a section, e.g. have a blc which shifts us forward 00915 // into the block. 00916 T *begin_p; 00917 00918 // The end for an STL-style iteration. 00919 T* end_p; 00920 00921 00922 // Fill the steps and the end for a derived class. 00923 void makeSteps() 00924 { baseMakeSteps(); this->setEndIter(); } 00925 00926 // Set the end iterator. 00927 void setEndIter() 00928 { end_p = (nels_p==0 ? 0 : (contiguous_p ? begin_p + nels_p : 00929 begin_p + size_t(length_p(ndim()-1)) * steps_p(ndim()-1))); } 00930 }; 00931 00932 00933 //# Declare extern templates for often used types. 00934 #ifdef AIPS_CXX11 00935 extern template class Array<Bool>; 00936 extern template class Array<Char>; 00937 extern template class Array<uChar>; 00938 extern template class Array<Short>; 00939 extern template class Array<uShort>; 00940 extern template class Array<Int>; 00941 extern template class Array<uInt>; 00942 extern template class Array<Int64>; 00943 extern template class Array<Float>; 00944 extern template class Array<Double>; 00945 extern template class Array<Complex>; 00946 extern template class Array<DComplex>; 00947 extern template class Array<String>; 00948 #endif 00949 00950 }//#End casa namespace 00951 00952 00953 #ifndef CASACORE_NO_AUTO_TEMPLATES 00954 #include <casacore/casa/Arrays/Array.tcc> 00955 #endif //# CASACORE_NO_AUTO_TEMPLATES 00956 #endif