IPosition.h

Go to the documentation of this file.
00001 //# IPosition.h: A vector of integers, used to index into arrays.
00002 //# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001,2002
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$
00027 
00028 #ifndef CASA_IPOSITION_H
00029 #define CASA_IPOSITION_H
00030 
00031 //# Includes
00032 #include <casa/aips.h>
00033 #include <casa/iosfwd.h>
00034 
00035 namespace casa { //# NAMESPACE CASA - BEGIN
00036 
00037 //# Forward Declarations
00038 class AipsIO;
00039 class LogIO;
00040 template<class T> class Array;
00041 template<class T> class Vector;
00042 
00043 // <summary> A Vector of integers, for indexing into Array<T> objects. </summary>
00044 
00045 // <use visibility=export>
00046 
00047 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="">
00048 // </reviewed>
00049 
00050 //# <prerequisite>
00051 //# Classes you should understand before using this one.
00052 //# </prerequisite>
00053 
00054 // <etymology>
00055 // IPosition is an Index Position in an n-dimensional array.
00056 // </etymology>
00057 
00058 // <synopsis> 
00059 // IPosition is "logically" a Vector<Int> constrained so that it's origin
00060 // is zero-based, and in fact that used to be the way it was implemented.
00061 // It was split out into a separate class to make the inheritance from
00062 // Arrays simpler (since Arrays use IPositions). The
00063 // template instantiation mechanism is complicated enough that this
00064 // simplification was felt to be a good idea.
00065 // <p>
00066 // IPosition objects are normally used to index into, and define the shapes
00067 // of, multi-dimensional arrays. For example, if you have a 5 dimensional
00068 // array, you need an IPosition of length 5 to index into the array (or
00069 // to define its shape, etc.).
00070 // <p>
00071 // Unlike Vectors, IPositions always use copy semantics.
00072 // <srcblock>
00073 // IPosition ip1(5);                         // An IPosition of length 5
00074 // ip1(0) = 11; ip1(1) = 5; ... ip1(4) = 6;  // Indices 0-based
00075 // IPosition ip2(ip1);                       // Copy constructor; a COPY
00076 // </srcblock>
00077 //
00078 // Binary operations must take place either with a conformnat (same size)
00079 // IPosition or with an integer, which behaves as if it was an IPosition
00080 // of the same size (i.e., length). All the usual binary arithmetic
00081 // operations are available, as well as logical operations, which return
00082 // Booleans. These all operate "element-by-element".
00083 // <p>
00084 // All non-inlined member functions of IPosition check invariants if the
00085 // preprocessor symbol AIPS_DEBUG is defined.
00086 // That is, the member functions check that ok() is true (constructors
00087 // check after construction, other functions on entry to the function).
00088 // If these tests fail, an AipsError exception is thrown; its message
00089 // contains the line number and source file of the failure (it is thrown
00090 // by the lAssert macro defined in aips/Assert.h).
00091 //
00092 // <example>
00093 // <srcblock>
00094 // IPosition blc(5), trc(5,1,2,3,4,5);
00095 // blc = 0;            // OR IPosition blc(5,0);
00096 // //...
00097 // if (blc > trc) {
00098 //    IPosition tmp;
00099 //    tmp = trc;       // Swap
00100 //    trc = blc;
00101 //    blc = tmp;
00102 // }
00103 // //...
00104 // trc += 5;           // make the box 5 larger in all dimensions
00105 // </srcblock>
00106 // </example>
00107 
00108 
00109 class IPosition
00110 {
00111 public:
00112     enum {MIN_INT = -2147483647};
00113     // A zero-length IPosition.
00114     IPosition();
00115 
00116     // An IPosition of size "length." The values in the object are undefined.
00117     explicit IPosition(uInt length);
00118 
00119     // An IPosition of size "length." The values in the object get
00120     // initialized to val.
00121     IPosition(uInt length, Int val);
00122 
00123     // An IPosition of size "length" with defined values. You need to supply
00124     // a value for each element of the IPosition (up to 10). [Unfortunately
00125     // varargs might not be sufficiently portable.]
00126     IPosition (uInt length, Int val0, Int val1, Int val2=MIN_INT, 
00127                Int val3=MIN_INT, Int val4=MIN_INT, Int val5=MIN_INT,
00128                Int val6=MIN_INT, Int val7=MIN_INT, Int val8=MIN_INT, 
00129                Int val9=MIN_INT);
00130 
00131     // Makes a copy (copy, NOT reference, semantics) of other.
00132     IPosition(const IPosition& other);
00133     
00134     ~IPosition();
00135 
00136     // Makes this a copy of other. "this" and "other" must either be conformant
00137     // (same size) or this must be 0-length, in which case it will
00138     // resize itself to be the same length as other.
00139     IPosition& operator=(const IPosition& other);
00140 
00141     // Copy "value" into every position of this IPosition.
00142     IPosition& operator=(Int value);
00143 
00144     // Construct a default axis path consisting of the values 0 .. nrdim-1.
00145     static IPosition makeAxisPath (uInt nrdim);
00146 
00147     // Construct a full axis path from a (partially) given axis path.
00148     // It fills the path with the non-given axis.
00149     // It is checked if the given axis path is valid (i.e. if the axis are
00150     // < nrdim and if they are not doubly defined).
00151     // E.g.: in the 4D case an axis path [0,2] is returned as [0,2,1,3].
00152     static IPosition makeAxisPath (uInt nrdim, const IPosition& partialPath);
00153 
00154     // Make a list of axes which are the axes not given in <src>axes</src>
00155     // up to the given dimension
00156     static IPosition otherAxes (uInt nrdim, const IPosition& axes);
00157 
00158     // Convert an IPosition to and from an Array<Int>. In either case, the
00159     // array must be one dimensional.
00160     // <group>
00161     IPosition(const Array<Int>& other);
00162     Vector<Int> asVector() const;
00163     // </group>
00164 
00165     // This member functions return an IPosition which has
00166     // degenerate (length==1) axes removed and the dimensionality reduced 
00167     // appropriately.
00168     // Only axes greater than startingAxis are considered (normally one 
00169     // wants to remove trailing axes.
00170     // <br>
00171     // The functions with argument <src>ignoreAxes</src> do
00172     // not consider the axes given in that argument..
00173     // <group>
00174     IPosition nonDegenerate(uInt startingAxis=0) const;
00175     IPosition nonDegenerate(const IPosition& ignoreAxes) const;
00176     // </group>
00177 
00178     // Old values are copied on resize if copy==True..
00179     // If the size increases, values beyond the former size are undefined.
00180     void resize(uInt newSize, Bool copy=True);
00181 
00182     // Index into the IPosition. Indices are zero-based. If the preprocessor
00183     // symbol AIPS_ARRAY_INDEX_CHECK is defined, operator() will check
00184     // "index" to ensure it is not out of bounds. If this check fails, an
00185     // AipsError will be thrown.
00186     // <group>
00187     Int& operator[] (uInt index);
00188     Int operator[]  (uInt index) const;
00189     Int& operator() (uInt index);
00190     Int operator()  (uInt index) const;
00191     // </group>
00192 
00193     // Get the storage.
00194     const Int *storage() const;
00195 
00196     // Append this IPosition with another one (causing a resize).
00197     void append (const IPosition& other);
00198 
00199     // Prepend this IPosition with another one (causing a resize).
00200     void prepend (const IPosition& other);
00201 
00202     // Return an IPosition as the concetanation of this and another IPosition.
00203     IPosition concatenate (const IPosition& other) const;
00204 
00205     // Set the first values of this IPosition to another IPosition.
00206     // An exception is thrown if the other IPosition is too long.
00207     void setFirst (const IPosition& other);
00208 
00209     // Set the last values of this IPosition to another IPosition.
00210     // An exception is thrown if the other IPosition is too long.
00211     void setLast (const IPosition& other);
00212 
00213     // Construct an IPosition from the first <src>n</src> values of this
00214     // IPosition.
00215     // An exception is thrown if <src>n</src> is too high.
00216     IPosition getFirst (uInt n) const;
00217 
00218     // Construct an IPosition from the last <src>n</src> values of this
00219     // IPosition.
00220     // An exception is thrown if <src>n</src> is too high.
00221     IPosition getLast (uInt n) const;
00222 
00223     // The number of elements in this IPosition. Since IPosition
00224     // objects use zero-based indexing, the maximum available index is
00225     // nelements() - 1.
00226     // <group>
00227     uInt nelements() const;
00228     uInt size() const;
00229     // </group>
00230 
00231     // conform returns true if nelements() == other.nelements().
00232     Bool conform(const IPosition& other) const;
00233 
00234     // Element-by-element arithmetic.
00235     // <group>
00236     void operator += (const IPosition& other);
00237     void operator -= (const IPosition& other);
00238     void operator *= (const IPosition& other);
00239     void operator /= (const IPosition& other);
00240     void operator += (Int val);
00241     void operator -= (Int val);
00242     void operator *= (Int val);
00243     void operator /= (Int val);
00244     // </group>
00245 
00246     // Returns 0 if nelements() == 0, otherwise it returns the product of
00247     // its elements.
00248     Int product() const;
00249 
00250     // Element-by-element comparison for equality.
00251     // It returns True if the lengths and all elements are equal.
00252     // <br>
00253     // Note that an important difference between this function and operator==()
00254     // is that if the two IPositions have different lengths, this function
00255     // returns False, instead of throwing an exception as operator==() does.
00256     Bool isEqual (const IPosition& other) const;
00257 
00258     // Element-by-element comparison for equality.
00259     // It returns True if all elements are equal.
00260     // When <src>skipDegeneratedAxes</src> is True, axes with
00261     // length 1 are skipped in both operands.
00262     Bool isEqual (const IPosition& other, Bool skipDegeneratedAxes) const;
00263 
00264     // Element-by-element comparison for (partial) equality.
00265     // It returns True if the lengths and the first <src>nrCompare</src>
00266     // elements are equal.
00267     Bool isEqual (const IPosition& other, uInt nrCompare) const;
00268 
00269     // Is the other IPosition a subset of (or equal to) this IPosition?
00270     // It is a subset if zero or more axes of this IPosition do not occur
00271     // or are degenerated in the other and if the remaining axes are
00272     // in the same order.
00273     Bool isSubSet (const IPosition& other) const;
00274 
00275     // Write an IPosition to an ostream in a simple text form.
00276     friend std::ostream& operator<<(std::ostream& os, const IPosition& ip);
00277 
00278     // Write an IPosition to an AipsIO stream in a binary format.
00279     friend AipsIO& operator<<(AipsIO& aio, const IPosition& ip);
00280 
00281     // Write an IPosition to a LogIO stream.
00282     friend LogIO& operator<<(LogIO& io, const IPosition& ip);
00283 
00284     // Read an IPosition from an AipsIO stream in a binary format.
00285     // Will throw an AipsError if the current IPosition Version does not match
00286     // that of the one on disk.
00287     friend AipsIO& operator>>(AipsIO& aio, IPosition& ip);
00288 
00289     // Is this IPosition consistent?
00290     Bool ok() const;
00291 
00292     // Define the STL-style iterators.
00293     // It makes it possible to iterate through all data elements.
00294     // <srcblock>
00295     //  IPosition shp(2,0);
00296     //  for (IPosition::iterator iter=shp.begin(); iter!=shp.end(); iter++) {
00297     //    *iter += 1;
00298     //  }
00299     // </srcblock>
00300     // <group name=STL-iterator>
00301     // STL-style typedefs.
00302     // <group>
00303     typedef Int               value_type;
00304     typedef Int*              iterator;
00305     typedef const Int*        const_iterator;
00306     typedef value_type*       pointer;
00307     typedef const value_type* const_pointer; 
00308     typedef value_type&       reference;
00309     typedef const value_type& const_reference;
00310     typedef size_t            size_type;
00311     typedef ptrdiff_t         difference_type;
00312     // </group>
00313     // Get the begin and end iterator object for this object.
00314     // <group>
00315     iterator begin()
00316       { return data_p; }
00317     const_iterator begin() const
00318       { return data_p; }
00319     iterator end()
00320       { return data_p + size_p; }
00321     const_iterator end() const
00322       { return data_p + size_p; }
00323     // </group>
00324 
00325     // </group>
00326 
00327 private:
00328     // Allocate a buffer with length size_p.
00329     void allocateBuffer();
00330 
00331     // Throw an index error exception.
00332     void throwIndexError() const;
00333 
00334     enum { IPositionVersion = 1, BufferLength = 4 };
00335     uInt size_p;
00336     Int buffer_p[BufferLength];
00337     // When the iposition is length BufferSize or less data is just buffer_p,
00338     // avoiding calls to new and delete.
00339     Int *data_p;
00340 };
00341 
00342 // <summary>Arithmetic Operations for IPosition's</summary>
00343 // Element by element arithmetic on IPositions.
00344 // <group name="IPosition Arithmetic">
00345 // Each operation is done on corresponding elements of the IPositions. The
00346 // two IPositions must have the same number of elements otherwise an
00347 // exception (ArrayConformanceError) will be thrown.
00348 // <group>
00349 IPosition operator + (const IPosition& left, const IPosition& right);
00350 IPosition operator - (const IPosition& left, const IPosition& right);
00351 IPosition operator * (const IPosition& left, const IPosition& right);
00352 IPosition operator / (const IPosition& left, const IPosition& right);
00353 // </group>
00354 // Each operation is done by appliying the integer argument to all elements
00355 // of the IPosition argument. 
00356 // <group>
00357 IPosition operator + (const IPosition& left, Int val);
00358 IPosition operator - (const IPosition& left, Int val);
00359 IPosition operator * (const IPosition& left, Int val);
00360 IPosition operator / (const IPosition& left, Int val);
00361 // </group>
00362 // Same functions as above but with with the Int argument on the left side.
00363 // <group>
00364 IPosition operator + (Int val, const IPosition& right);
00365 IPosition operator - (Int val, const IPosition& right);
00366 IPosition operator * (Int val, const IPosition& right);
00367 IPosition operator / (Int val, const IPosition& right);
00368 // </group>
00369 
00370 // Returns the element by element minimum or maximum.
00371 // <group>
00372 IPosition max (const IPosition& left, const IPosition& right);
00373 IPosition min (const IPosition& left, const IPosition& right);
00374 // </group>
00375 // </group>
00376 
00377 // <summary>Logical operations for IPosition's</summary>
00378 // Element by element boolean operations on IPositions. The result is true
00379 // only if the operation yields true for every element of the IPosition.
00380 // <group name="IPosition Logical">
00381 // Each operation is done on corresponding elements of the IPositions. The
00382 // two IPositions must have the same number of elements otherwise an
00383 // exception (ArrayConformanceError) will be thrown.
00384 // <group>
00385 Bool operator == (const IPosition& left, const IPosition& right);
00386 Bool operator != (const IPosition& left, const IPosition& right);
00387 Bool operator <  (const IPosition& left, const IPosition& right);
00388 Bool operator <= (const IPosition& left, const IPosition& right);
00389 Bool operator >  (const IPosition& left, const IPosition& right);
00390 Bool operator >= (const IPosition& left, const IPosition& right);
00391 // </group>
00392 // Each operation is done by appliying the integer argument to all elements
00393 // <group>
00394 Bool operator == (const IPosition& left, Int val);
00395 Bool operator != (const IPosition& left, Int val);
00396 Bool operator <  (const IPosition& left, Int val);
00397 Bool operator <= (const IPosition& left, Int val);
00398 Bool operator >  (const IPosition& left, Int val);
00399 Bool operator >= (const IPosition& left, Int val);
00400 // </group>
00401 // Same functions as above but with with the Int argument on the left side.
00402 // <group>
00403 Bool operator == (Int val, const IPosition& right);
00404 Bool operator != (Int val, const IPosition& right);
00405 Bool operator <  (Int val, const IPosition& right);
00406 Bool operator <= (Int val, const IPosition& right);
00407 Bool operator >  (Int val, const IPosition& right);
00408 Bool operator >= (Int val, const IPosition& right);
00409 // </group>
00410 // </group>
00411 
00412 // <summary>Indexing functions for IPosition's</summary>
00413 // Convert between IPosition and offset in an array.
00414 //
00415 // The offset of an element in an array is the number of elements from the
00416 // origin that the element would be if the array were arranged linearly.
00417 // The origin of the array has an offset equal to 0, while the
00418 // "top right corner" of the array has an offset equal to one less than the
00419 // total number of elements in the array.
00420 //
00421 // Two examples of offset would be the index in a carray and the seek position
00422 // in a file.
00423 
00424 // <group name="IPosition Indexing">
00425 // Convert from offset to IPosition in an array. The second of these
00426 // functions requires that type T have shape and origin members which return
00427 // IPositions.
00428 IPosition toIPositionInArray (const uInt offset, const IPosition& shape);
00429 
00430 // Convert from IPosition to offset in an array. The second of these
00431 // functions requires that type T have shape and origin members which return
00432 // IPositions.
00433 uInt toOffsetInArray (const IPosition& iposition, const IPosition& shape);
00434 
00435 // Determine if the given offset or IPosition is inside the array. Returns
00436 // True if it is inside the Array. The second and fourth of these functions
00437 // require that type T have shape and origin members which return
00438 // IPositions.
00439 // <thrown>
00440 //   <li> ArrayConformanceError: If all the IPositions are not the same length
00441 // </thrown>
00442 // <group>
00443 Bool isInsideArray (const uInt offset, const IPosition& shape);
00444 Bool isInsideArray (const IPosition& iposition, const IPosition& shape);
00445 // </group>
00446 // </group>
00447 
00448 
00449     
00450 //# Inlined member functions for IPosition
00451 
00452 inline IPosition::IPosition()
00453 : size_p (0),
00454   data_p (buffer_p)
00455 {}
00456 inline IPosition::IPosition (uInt length)
00457 : size_p (length),
00458   data_p (buffer_p)
00459 {
00460     if (length > BufferLength) {
00461         allocateBuffer();
00462     }
00463 }
00464 
00465 inline IPosition::~IPosition()
00466 {
00467     if (data_p != &buffer_p[0]) {
00468         delete [] data_p;
00469     }
00470 }
00471 
00472 inline IPosition IPosition::makeAxisPath (uInt nrdim)
00473 {
00474     return makeAxisPath (nrdim, IPosition());
00475 }
00476 
00477 inline uInt IPosition::nelements() const
00478 {
00479     return size_p;
00480 }
00481 inline uInt IPosition::size() const
00482 {
00483     return size_p;
00484 }
00485 
00486 inline Int& IPosition::operator[](uInt index)
00487 {
00488     return data_p[index];
00489 }
00490 
00491 inline Int IPosition::operator[](uInt index) const
00492 {
00493     return data_p[index];
00494 }
00495 
00496 inline Int& IPosition::operator()(uInt index)
00497 {
00498 #if defined(AIPS_ARRAY_INDEX_CHECK)
00499     if (index >= nelements()) {
00500         throwIndexError();
00501     }
00502 #endif
00503     return data_p[index];
00504 }
00505 
00506 inline Int IPosition::operator()(uInt index) const
00507 {
00508 #if defined(AIPS_ARRAY_INDEX_CHECK)
00509     if (index >= nelements()) {
00510         throwIndexError();
00511     }
00512 #endif
00513     return data_p[index];
00514 }
00515 
00516 inline const Int *IPosition::storage() const
00517 {
00518     return data_p;
00519 }
00520 
00521 inline Bool IPosition::conform(const IPosition& other) const
00522 {
00523     return  (size_p == other.size_p);
00524 }
00525 
00526 } //# NAMESPACE CASA - END
00527 
00528 #endif

Generated on Mon Sep 1 22:33:35 2008 for NRAOCASA by  doxygen 1.5.1