ArrayAccessor.h

Classes

Axis -- Class to enumerate compile-time axis numeration (full description)
AxisN -- Class to specify run-time axis values (full description)
ArrayBaseAccessor -- Axis independent base for the ArrayAccessor classes (full description)
ArrayAccessor -- Fast 1D accessor/iterator for nD array classes (full description)
ArrayAccessor_RT -- Specialization for run-time axes (full description)

template <uInt AX> struct Axis

Types

enum

N = AX
Specify the constant axis

Interface

Description

Member Description

enum


struct AxisN

Interface

explicit AxisN(const uInt n) : N(n)

Description

Member Description

explicit AxisN(const uInt n) : N(n)

Construct the run-time axis number

template <class T> class ArrayBaseAccessor

Interface

Protected Members
ArrayBaseAccessor() : arrayPtr_p(0), axis_p(0), ptr_p(0), step_p(0), begin_p(0), end_p(0)
explicit ArrayBaseAccessor(const Array<T> &arr) : arrayPtr_p(&arr), axis_p(0), ptr_p(const_cast<T*>(arrayPtr_p->data())), step_p(0), begin_p(0), end_p(0)
ArrayBaseAccessor(const Array<T> &arr, const uInt ax) : arrayPtr_p(&arr), axis_p(ax), ptr_p(const_cast<T*>(arrayPtr_p->data())), step_p(0), begin_p(0), end_p(0)
ArrayBaseAccessor(const ArrayBaseAccessor<T> &other) : arrayPtr_p(other.arrayPtr_p), axis_p(other.axis_p), ptr_p(other.ptr_p), step_p(other.step_p), begin_p(other.begin_p), end_p(other.end_p)
ArrayBaseAccessor(const ArrayBaseAccessor<T> &other, const uInt ax) : arrayPtr_p(other.arrayPtr_p), axis_p(ax), ptr_p(other.ptr_p), step_p(other.step_p), begin_p(other.begin_p), end_p(other.end_p)
~ArrayBaseAccessor()
ArrayBaseAccessor &operator=(const ArrayBaseAccessor<T> &other)
void init(const Array<T> &arr)
void init(const Array<T> &arr, const uInt ax)
void init(const uInt ax)
Public Members
void operator+=(const uInt ix)
void operator-=(const uInt ix)
void operator++()
void operator++(int)
void operator--()
void operator--(int)
const T &operator*() const
T &operator*()
T *data()
const Array<T> &baseArray()
uInt step()
const T &operator[](const Int ix) const
T &operator[](const Int ix)
const T *end()
const T *end(const Int n)
const T *begin()
const T *begin(const Int n)
const T *rend()
const T *rend(const Int n)
const T *rbegin()
const T *rbegin(const Int n)

Description

Synopsis

The ArrayBaseAccessor class implements the axis independent parts of the ArrayAccessor class. It can only be used from the ArrayAccessor class.

Member Description

ArrayBaseAccessor() : arrayPtr_p(0), axis_p(0), ptr_p(0), step_p(0), begin_p(0), end_p(0)

Default constructor (for use in e.g. containers)

explicit ArrayBaseAccessor(const Array<T> &arr) : arrayPtr_p(&arr), axis_p(0), ptr_p(const_cast<T*>(arrayPtr_p->data())), step_p(0), begin_p(0), end_p(0)
ArrayBaseAccessor(const Array<T> &arr, const uInt ax) : arrayPtr_p(&arr), axis_p(ax), ptr_p(const_cast<T*>(arrayPtr_p->data())), step_p(0), begin_p(0), end_p(0)

Construct from an Array

ArrayBaseAccessor(const ArrayBaseAccessor<T> &other) : arrayPtr_p(other.arrayPtr_p), axis_p(other.axis_p), ptr_p(other.ptr_p), step_p(other.step_p), begin_p(other.begin_p), end_p(other.end_p)
ArrayBaseAccessor(const ArrayBaseAccessor<T> &other, const uInt ax) : arrayPtr_p(other.arrayPtr_p), axis_p(ax), ptr_p(other.ptr_p), step_p(other.step_p), begin_p(other.begin_p), end_p(other.end_p)

Copy constructor (copy semantics)

~ArrayBaseAccessor()

ArrayBaseAccessor &operator=(const ArrayBaseAccessor<T> &other)

Assignment (copy semantics)

void init(const Array<T> &arr)
void init(const Array<T> &arr, const uInt ax)
void init(const uInt ax)

(Re-)initialize from Array

void operator+=(const uInt ix)
void operator-=(const uInt ix)
void operator++()
void operator++(int)
void operator--()
void operator--(int)

Iterator-like operations.

const T &operator*() const
T &operator*()
T *data()
const Array<T> &baseArray()
uInt step()

Dereferencing.

const T &operator[](const Int ix) const
T &operator[](const Int ix)

Index along current axis

const T *end()
const T *end(const Int n)

End of index on line

const T *begin()
const T *begin(const Int n)

Start of index on line

const T *rend()
const T *rend(const Int n)

End when reverse indexing

const T *rbegin()
const T *rbegin(const Int n)

Begin when reverse indexing


template <class T, uInt U> class ArrayAccessor<T, Axis<U> > :public ArrayBaseAccessor<T>

Interface

ArrayAccessor() : ArrayBaseAccessor<T>()
explicit ArrayAccessor(const Array<T> &arr) : ArrayBaseAccessor<T>(arr)
ArrayAccessor(const ArrayAccessor<T, Axis<U> > &other) : U<T>(other)
template <uInt X> explicit ArrayAccessor(const ArrayAccessor<T, Axis<X> > &other) : ArrayBaseAccessor<T>(other)
explicit ArrayAccessor(const ArrayAccessor<T, T > &other) : ArrayBaseAccessor<T>(other)
~ArrayAccessor()
ArrayAccessor &operator=(const ArrayAccessor<T, Axis<U> > &other)
template <uInt X> ArrayAccessor &operator=(const ArrayAccessor<T, T<X> > &other)
ArrayAccessor &operator=(const ArrayAccessor<T, AxisN> &other)
void init(const Array<T> &arr)
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 AxisN ax) const
T &index(const Int ix, const AxisN ax)
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
Private Members
Int initOff(Int x, uInt ax)
void initStep()

Description

Prerequisite

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): 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.

Tip 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))
	}}
Tip 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)

Template Type Argument Requirements (U)

Thrown Exceptions

To Do

Member Description

ArrayAccessor() : ArrayBaseAccessor<T>()

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).

~ArrayAccessor()

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

void initStep()

Initialize some internal values


template <class T> class ArrayAccessor_RT<T, AxisN> :public ArrayBaseAccessor<T>

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()

Description

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

~ArrayAccessor_RT()

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

void initStep()

Initialize some internal values