Default constructor (for use in e.g. containers)
Private Members
- Int initOff(Int x, uInt ax)
- void initStep()
Review Status
- Reviewed By:
- diepen@astron.nl
- Date Reviewed:
- 2002/12/01
- Programs:
- Demos:
- Tests:
Prerequisite
- Array indexing and access methods
(Array)
Etymology
Array and access, rather than Iterator, which would suggest more
standard-like interfaces
Synopsis
Accessing a large multi-dimensional array by varying the indices of the
array can be a slow process. Timing indications are that for a cube
indexing with 3 indices was about seven times slower than using a
standard 1D C-like index into an array of basic Int types.
Improvements have made this less, partly due to some pre-calculation
necessary for this class, but can still be a factor of more than 3
slower. There are a variety of ways to access elements
cube(i,j,k):
- Complete random access in all dimensions will need the
use of the indexing: cube(i,j,k); or
cube(IPosition(3)) as described in the
Array and
Cube classes
- Ordered access of all (or most) elements in an Array
(in memory order) can be best achieved by the use of Array's
STLIterator classes.
This is the fastest way for non-contiguous arrays, and only slightly
slower than the use of getStorage for contiguous arrays.
- Ordered access along memory order can also be achieved by the use
of the
getStorage() method.
For contiguous arrays this could be slightly faster than the use of
the STLIterator (about 10% faster), but slower for
non-contiguous arrays. In addition it needs additional memory
resources, which will lead to extra overhead. The general use of
getStorage is discouraged with the introduction of the STLIterator.
It should only be used when an interface to routines in
other languages is needed (like Fortran), or when a large Array is
known to be contiguous, and the data have to be referenced many times.
- Access along one or more axes of a (large) multi-dimensional array
is best achieved using the
ArrayAccessor class. Its total
access time is about 2 times faster than indexing (for cubes,
more for more indices),
- Special iteration (like in chunks) are catered for by the
ArrayIterator,
MatrixIterator,
VectorIterator classes.
The ArrayAccessor class is an iterator like pointer to the data
in the array. It is a 1-dimensional accessor. It is created with either
a constant (at compile time) axis indicator, or with a run-time
axis selector. ArrayAccessor constructor accepts a const Array<>.
However, the underlying Array class can be modified at this moment. In
future a ConstArrayAccessor class is foreseen.
Matrix<Double> mat(1000,500); // A 1000*500 matrix
// Fill Matrix ...
// Loop over index 1, than index 0:
for (ArrayAccessor<Double, Axis<1> > i(mat); i != i.end(); ++i) {
for (ArrayAccessor<Double, Axis<0> > j(i); j |= j.end(); ++j) {
// Actions on *j (which points to mat(j,i)) or j[n]
// (which points to mat(j+n,i))
}}
For run-time indices it would look like:
Matrix<Double> mat(1000,500); // A 1000*500 matrix
// Fill Matrix ...
// Loop over index 1, than index 0:
for (ArrayAccessor<Double, AxisN> i(mat, AxisN(1));
i != i.end(); ++i) {
for (ArrayAccessor<Double, AxisN> j(i,AxisN(0)); j |= j.end(); ++j) {
// Actions on *j (which points to mat(j,i)) or j[n]
// (which points to mat(j+n,i))
}}
Compile-time and run-time axes can be mixed in constructors and assignments.
Like in all comparable situations, memory allocation
within a loop can slow down processes. For that reason the example above
can be better written (about 25% faster) as:
Matrix<Double> mat(1000,500); // A 1000*500 matrix
ArrayAccessor<Double, Axis<0> > j; // accessor pre-allocated
// Fill Matrix ...
// Loop over index 1, than index 0:
for (ArrayAccessor<Double, Axis<1> > i(mat); i != i.end(); ++i) {
for (j=i; j |= j.end(); ++j) {
// Actions on *j (which points to mat(j,i)) or j[n]
// (which points to mat(j+n,i))
}}
The underlying Array classes are structured with the
first index varying fastest. This means that in general (due to caching and
swapping) operations are fastest when Axis<0> > is in the
innermost loop (if possible of course).
The demonstrator and test programs have more examples.
The accessors can be dereferenced by the dereference operator (*)
and by the index operator ([Int]), which can handle negative
values.
Points around the accessor in any axis direction can be addressed
along any axis by the templated methods next(),
prev() and index(Int). Either run-time or
compile-time axes can be used (see example).
An accessor can be re-initialized with the init() function. It can also
be reset() to any pointer value. Mthods end(),
begin(), rbegin() and rend() are available
for loop control (like in the STL iterators). In addition each of these
can have an optional integer argument, specifying an offset (in points
along the current axis).
Operations ++ -- += -= are available.
This class is available for Axis<n> and AxisN
specializations only.
Example
// get a cube and fill it
Cube<Double> cub(5,2,4);
indgen(cub);
// Loop over axes 2-0 and use index() over axis 1
for (ArrayAccessor<Double, Axis<2> > i(cub); i != i.end() ; ++i) {
for (ArrayAccessor<Double, Axis<0> > j(i);
j != j.end(); ++j) {
// show result
cout << *j << ", " << j.index<Axis<1> >(1) << endl;
};
};
See the demonstrator program in
aips/implement/Arrays/test/dArrayAccessor.cc and the
test program tArrayAccessor for more examples.
Motivation
To speed up especially interpolation code
Template Type Argument Requirements (T)
- Any valid Array templating argument
Template Type Argument Requirements (U)
- A class Axis<n>
- Class AxisN
Thrown Exceptions
- Exceptions created in the Array class
- Addressing errors
To Do
- add a ConstArrayAccessor class
Member Description
Constructors
Default ctor. Note only available to accommodate containers of
ArrayAccessors. Use init() to initialize.
explicit ArrayAccessor(const Array<T> &arr) : ArrayBaseAccessor<T>(arr)
Constructors
Construct an accessor from specified Array along the selected axis.
The accessor will point to the first element along the axis (i.e.
at (0,0,...)).
ArrayAccessor(const ArrayAccessor<T, Axis<U> > &other) : U<T>(other)
Constructors
Construct from an ArrayAccessor along same axis. The accessor will point
at the same element as the originator.
template <uInt X> explicit ArrayAccessor(const ArrayAccessor<T, Axis<X> > &other) : ArrayBaseAccessor<T>(other)
explicit ArrayAccessor(const ArrayAccessor<T, T > &other) : ArrayBaseAccessor<T>(other)
Constructors
Construct from accessor along another (or run-time) axis.
The accessor will point to the same element (but will be oriented
along another axis).
Constructors
template <uInt X> ArrayAccessor &operator=(const ArrayAccessor<T, T<X> > &other)
Assignment (copy semantics)
Assign from other compile-time accessor along another axis
ArrayAccessor &operator=(const ArrayAccessor<T, AxisN> &other)
Assignment (copy semantics)
Assign from run-time accessor along any axis
ArrayAccessor &operator=(const ArrayAccessor<T, Axis<U> > &other)
Assignment (copy semantics)
void init(const Array<T> &arr)
(Re-)initialization to start of array (i.e. element (0,0,0,...))
void reset()
void reset(const T * p)
Indexing operations along another axis than the one of the current
object. See for the indexing and iterator operations along the
object's axis ArrayBaseAccessor
Reset to start of dimension or to specified pointer
template <class X> const T &next() const
template <class X> T &next()
Indexing operations along another axis than the one of the current
object. See for the indexing and iterator operations along the
object's axis ArrayBaseAccessor
Get the value 'next' along the specified axis (e.g. with
a.next<Axis<2> >())
template <class X> const T &prev() const
template <class X> T &prev()
Indexing operations along another axis than the one of the current
object. See for the indexing and iterator operations along the
object's axis ArrayBaseAccessor
Get the value 'previous' along the specified axis (e.g. with
a.prev<Axis<2> >())
const T &next(const AxisN ax) const
T &next(const AxisN ax)
const T &prev(const AxisN ax) const
T &prev(const AxisN ax)
Indexing operations along another axis than the one of the current
object. See for the indexing and iterator operations along the
object's axis ArrayBaseAccessor
Get the next or previous along the specified run-time axis. E.g.
a.prev(AxisN(2)).
template <class X> const T &index(const Int ix) const
template <class X> T &index(const Int ix)
const T &index(const Int ix, const AxisN ax) const
T &index(const Int ix, const AxisN ax)
Indexing operations along another axis than the one of the current
object. See for the indexing and iterator operations along the
object's axis ArrayBaseAccessor
Bool operator==(const ArrayAccessor<T, Axis<U> > &other) const
Bool operator!=(const ArrayAccessor<T, Axis<U> > &other) const
Bool operator==(const T *other) const
Bool operator!=(const T *other) const
Comparison. The comparisons are done for the accessor pointer
value. They can be used to control loops.
Int initOff(Int x, uInt ax)
Get proper offset
Initialize some internal values
Interface
Public Members
- explicit ArrayAccessor_RT(const AxisN ax=AxisN(0)) : ax<T>()
- explicit ArrayAccessor_RT(Array<T> &arr, const T ax=T(0)) : ArrayBaseAccessor<T>(arr, ax.N)
- ArrayAccessor_RT(ArrayAccessor_RT<T, AxisN> &other) : ArrayBaseAccessor<T>(other)
- explicit ArrayAccessor_RT(ArrayAccessor_RT<T, T> &other, const T ax) : other<T>(other, ax.N)
- template <uInt X> explicit ArrayAccessor_RT(ArrayAccessor_RT<T, Axis<X> > &other, const AxisN ax=AxisN(0)) : other<T>(other, ax.N)
- ArrayAccessor_RT &operator=(const ArrayAccessor_RT<T, AxisN> &other)
- template <uInt X> ArrayAccessor_RT &operator=(const ArrayAccessor_RT<T, T<X> > &other)
- ~ArrayAccessor_RT()
- void init(const Array<T> &arr, const AxisN ax)
- void init(const AxisN ax)
- void reset()
- void reset(const T *p)
- template <class X> const T &next() const
- template <class X> T &next()
- template <class X> const T &prev() const
- template <class X> T &prev()
- const T &next(const AxisN ax) const
- T &next(const AxisN ax)
- const T &prev(const AxisN ax) const
- T &prev(const AxisN ax)
- template <class X> const T &index(const Int ix) const
- template <class X> T &index(const Int ix)
- const T &index(const Int ix, const ix(ax)) const
- T &index(const Int ix, const ix(ax))
- Bool operator==(const ArrayAccessor_RT<T, AxisN> &other) const
- Bool operator!=(const ArrayAccessor_RT<T, AxisN> &other) const
- Bool operator==(const T *other) const
- Bool operator!=(const T *other) const
Private Members
- Int initOff(Int x, uInt ax)
- void initStep()
Synopsis
This class is a specialization for run-time axis selection within the
array accessor. The axis is specified in the constructors and in the
special indexing operators (prev, next, index) with
a parameter AxisN(n) in stead of a template parameter
<Axis<n> >.
Note that the name of the class is ArrayAccessor. The special
name is only to bypass cxx2html problems with duplicate class names.
Member Description
explicit ArrayAccessor_RT(const AxisN ax=AxisN(0)) : ax<T>()
explicit ArrayAccessor_RT(Array<T> &arr, const T ax=T(0)) : ArrayBaseAccessor<T>(arr, ax.N)
ArrayAccessor_RT(ArrayAccessor_RT<T, AxisN> &other) : ArrayBaseAccessor<T>(other)
explicit ArrayAccessor_RT(ArrayAccessor_RT<T, T> &other, const T ax) : other<T>(other, ax.N)
template <uInt X> explicit ArrayAccessor_RT(ArrayAccessor_RT<T, Axis<X> > &other, const AxisN ax=AxisN(0)) : other<T>(other, ax.N)
ArrayAccessor_RT &operator=(const ArrayAccessor_RT<T, AxisN> &other)
template <uInt X> ArrayAccessor_RT &operator=(const ArrayAccessor_RT<T, T<X> > &other)
Constructors
Destructor
void init(const Array<T> &arr, const AxisN ax)
void init(const AxisN ax)
(Re-)initialization to start of array (i.e. element (0,0,0,...)) or
re-initialize to an axis.
void reset()
void reset(const T *p)
Reset to start of dimension or to specified pointer
template <class X> const T &next() const
template <class X> T &next()
template <class X> const T &prev() const
template <class X> T &prev()
const T &next(const AxisN ax) const
T &next(const AxisN ax)
const T &prev(const AxisN ax) const
T &prev(const AxisN ax)
template <class X> const T &index(const Int ix) const
template <class X> T &index(const Int ix)
const T &index(const Int ix, const ix(ax)) const
T &index(const Int ix, const ix(ax))
Indexing operations along another axis than the one of the current
object. See for the indexing and iterator operations along the
object's axis ArrayBaseAccessor
Bool operator==(const ArrayAccessor_RT<T, AxisN> &other) const
Bool operator!=(const ArrayAccessor_RT<T, AxisN> &other) const
Bool operator==(const T *other) const
Bool operator!=(const T *other) const
Comparisons
Int initOff(Int x, uInt ax)
Get proper offset
Initialize some internal values