//# 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:
//
// - axesAreCursor=true means that the axes form the cursor axes.
// The remaining axes will form the iteration axes.
// This is the default.
//
- 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