Array.h

Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1