//# ArrayPosIter.h: Iterate an IPosition through the shape of an Array //# Copyright (C) 1993,1994,1995,1998,1999,2004 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #ifndef CASA_ARRAYPOSITER_2_H #define CASA_ARRAYPOSITER_2_H //# Change the following to a forward declare? #include "IPosition.h" namespace casacore { //# NAMESPACE CASACORE - BEGIN //# Forward Declarations class ArrayBase; // Iterate an IPosition through the shape of an Array // // // // ArrayPositionIterator manipulates an IPosition "cursor" through some // volume defined by an origin and shape. This position can in turn be // used to index into, or otherwise define a position in, an Array. Normally // users won't use this class directly, rather they will use an ArrayIterator, // VectorIterator or MatrixIterator object, which in turn uses this class. // ArrayPositionIterator is also used in the implementation of Array. // // // template void verySlowArrayCopy(Array &to, const Array &from) // { // if (! to.conform(from)) { // // throw some error // } // ArrayPositionIterator toiter(to.shape(), to.origin(),0); // ArrayPositionIterator fromiter(from.shape(), from.origin(),0); // // If to.origin() == from.origin() we only need one iterator // // or we could offset positions by the difference in origins. // // The "0" means we are stepping by scalars. // while (! toiter.pastEnd()) { // we know arrays conform // to(toiter.pos()) = fromiter(fromiter.pos()); // toiter.next(); fromiter.next(); // } // } // // // Iteration can be done by any combination of axes, but it can only be // done for full axes. //
The iteration step always "fills up" its dimensionality. // E.g., if we are stepping through a cube by matrices, the matrix completely // fills up the plane. // Casacore class ArrayLattice in the lattices // package can be used to iterate with partial volumes. // //

// ArrayPositionIterator also serves as the base class of ArrayIterator. // Function makeIterator in class ArrayBase can be used to make an // ArrayIterator without having to know the template type. Function // getArray in this class can be used to obtain the current // contents of the cursor as an ArrayBase object. // class ArrayPositionIterator { public: // Define the shape and origin of the volume the cursor will step // through. Also define the dimensionality of the step. byDim==0 implies // we are stepping by scalars (i.e. every element), byDim==1 implies that // we are stepping by vector, ==2 by matrices, and so on. // If uses the first byDim axes as the cursor volume and it steps // through the remaining axes. // ArrayPositionIterator(const IPosition &shape, const IPosition &origin, size_t byDim); ArrayPositionIterator(const IPosition &shape, size_t byDim); // // Step through an array using the given axes. // The axes can be given in two ways: //

    //
  1. axesAreCursor=true means that the axes form the cursor axes. // The remaining axes will form the iteration axes. // This is the default. //
  2. axesAreCursor=false means the opposite. // In this case the iteration axes can be given in any order. //
// E.g. when using iteration axes 2,0 for an array with shape [5,3,7], each // iteration step returns a cursor (containing the data of axis 1). // During the iteration axis 2 will vary most rapidly (as it was // given first). //
E.g. for a shape of [3,4,5,6] and cursor axes [2,0], the cursor size // is [3,5] (axes 0 and 2), while the iteration is done over axes 1 and 3 // (1 the fastest varying one). ArrayPositionIterator(const IPosition &shape, const IPosition &axes, bool axesAreCursor=true); virtual ~ArrayPositionIterator() {}; // Reset the cursor to the beginning of the volume. // virtual void reset(); void origin() { reset(); } // // Returns true of the cursor is at the origin. bool atStart() const; // Returns true if the cursor has moved past the end of its volume. bool pastEnd() const; // Return the position of the cursor. // This include all axes const IPosition &pos() const {return Cursor;} // Return the end position of the cursor. IPosition endPos() const; // Advance the cursor to its next position. virtual void next(); // Set the cursor to the given position. // The position can only contain the iteration axes or it can be the full // position. //
In the first case the position must to be given in the order // of the iteration axes as given in the constructor. // In the latter case the position must be given in natural order // (as given by function pos and only the cursor axes are taken // into account. virtual void set (const IPosition& cursorPos); // What is the dimensionality of the volume we are iterating through? size_t ndim() const; // Return the iteration axes. const IPosition &iterAxes() const {return iterationAxes;} // Return the cursor axes. const IPosition &cursorAxes() const {return cursAxes;} // Get the array in the cursor. // This is only implemented in the derived ArrayIterator class. // By default it throws an exception. virtual ArrayBase& getArray(); protected: // Advance cursor to its next position and tell which dimension stepped. size_t nextStep(); // What is the dimensionality of the "step" the cursor takes, i.e. // 0 for scalars, 1 for vector, .... size_t dimIter() const {return cursAxes.nelements();} private: // Setup the object for the constructor. // void setup(size_t byDim); void setup(const IPosition &axes, bool axesAreCursor); // //# We should probably have mf's for getting at Start,Shape and End. IPosition Start, Shape, End, Cursor; bool atOrBeyondEnd; IPosition cursAxes, iterationAxes; }; // Dimensionality of the array we are iterating through. inline size_t ArrayPositionIterator::ndim() const { return Start.nelements(); } // We are at the "end" if we cannot advance any more. inline bool ArrayPositionIterator::pastEnd() const { return atOrBeyondEnd; } } //# NAMESPACE CASACORE - END #endif