|
|
| MDArray () |
| Default constructor. More...
|
|
| MDArray (const Teuchos::ArrayView< dim_type > &dims) |
| Constructor with dimensions only. More...
|
|
| MDArray (const Teuchos::ArrayView< dim_type > &dims, const T &value, const Layout layout=DEFAULT_ORDER) |
| Constructor with dimensions and default value, with optional storage order. More...
|
|
| MDArray (const Teuchos::ArrayView< dim_type > &dims, const Layout layout, const T &value=value_type()) |
| Constructor with dimensions and storage order, with optional default value. More...
|
|
| MDArray (const MDArray< T > &source) |
| Copy constructor. More...
|
|
| MDArray (const MDArrayView< T > &source) |
| Copy constructor from MDArrayView More...
|
|
| ~MDArray () |
| Destructor.
|
|
|
int | numDims () const |
| Return the number of dimensions.
|
|
const Teuchos::Array< dim_type > & | dimensions () const |
| Return an array of dimensions.
|
|
dim_type | dimension (int axis) const |
| Return the dimension of the given axis. More...
|
|
size_type | size () const |
| Return the total size of the MDArray
|
|
const Teuchos::Array< size_type > & | strides () const |
| Return the indexing strides.
|
|
const Teuchos::Array< T > & | array () const |
| Return the underlying Teuchos::Array
|
|
const Layout | layout () const |
| Return the storage order.
|
|
|
MDArrayView< T > | mdArrayView () |
| Perform an explicit conversion to a non-const MDArrayView<T>
|
|
const MDArrayView< T > | mdArrayView () const |
| Perform an explicit conversion to a const MDArrayView<T>
|
|
MDArrayView< const T > | mdArrayViewConst () |
| Perform an explicit conversion to a non-const MDArrayView<const T>
|
|
const MDArrayView< const T > | mdArrayViewConst () const |
| Perform an explicit conversion to a const MDArrayView<const T>
|
|
| operator MDArrayView< T > () const |
| Perform an implicit conversion to a non-const MDArrayView
|
|
| operator MDArrayView< const T > () const |
| Perform an implicit conversion to a const MDArrayView
|
|
|
MDArrayView< T > | operator[] (dim_type i) |
| Sub-array access operator. The returned MDArrayView object will have one fewer dimensions than the calling MDArray . More...
|
|
const MDArrayView< T > | operator[] (dim_type i) const |
| Sub-array const access operator. The returned MDArrayView object will have one fewer dimensions than the calling MDArray . More...
|
|
MDArrayView< T > | operator[] (Slice s) |
| Sub-array access operator. The returned MDArrayView object will have the same number of dimensions as the calling MDArray . More...
|
|
const MDArrayView< T > | operator[] (Slice s) const |
| Sub-array const access operator. The returned MDArrayView object will have the same number of dimensions as the calling MDArray . More...
|
|
MDArrayView< T > | operator() () |
| Conversion to non-const MDArrayView
|
|
const MDArrayView< T > | operator() () const |
| Conversion to const MDArrayView
|
|
|
|
T & | operator() (dim_type i) |
| Non-const 1D element access operator. More...
|
|
T & | operator() (dim_type i, dim_type j) |
| Non-const 2D element access operator. More...
|
|
T & | operator() (dim_type i, dim_type j, dim_type k) |
| Non-const 3D element access operator. More...
|
|
T & | operator() (dim_type i, dim_type j, dim_type k, dim_type m) |
| Non-const 4D element access operator. More...
|
|
T & | operator() (dim_type i, dim_type j, dim_type k, dim_type m, dim_type n) |
| Non-const 5D element access operator. More...
|
|
T & | operator() (dim_type i, dim_type j, dim_type k, dim_type m, dim_type n, dim_type p,...) |
| Non-const 6D and higher element access operator. More...
|
|
const T & | operator() (dim_type i) const |
| Const 1D element access operator. More...
|
|
const T & | operator() (dim_type i, dim_type j) const |
| Const 2D element access operator. More...
|
|
const T & | operator() (dim_type i, dim_type j, dim_type k) const |
| Const 3D element access operator. More...
|
|
const T & | operator() (dim_type i, dim_type j, dim_type k, dim_type m) const |
| Const 4D element access operator. More...
|
|
const T & | operator() (dim_type i, dim_type j, dim_type k, dim_type m, dim_type n) const |
| Const 5D element access operator. More...
|
|
const T & | operator() (dim_type i, dim_type j, dim_type k, dim_type m, dim_type n, dim_type p,...) const |
| Const 6D and higher element access operator. More...
|
|
template<typename T>
class Domi::MDArray< T >
Memory-safe templated multi-dimensional array class.
MDArray Design Discussion
The purpose of the MDArray
class is to provide multi-dimensional array storage for an arbitrary number of dimensions. It stores a Teuchos::Array
as member data to provide its data buffer and so adopts all of the memory safety of the Teuchos::Array
class. Storage order can be set by the user to be "C" ordering or "Fortran" ordering (C-ordering is also known as row-major or last-index-fastest; Fortran-ordering is also known as column-major or first-index-fastest). If not specified, the default is Fortran ordering.
The MDArray
class also provides efficient indexing of the form a(i,j,k,...)
, regardless of storage order. Here, i,j,k
must all be ordinals of type dim_type
, and the return type is T &
, where T
is the type of data stored in the array.
The square bracket operator, for which the C++ standard requires one and only one argument, can take a dim_type
ordinal or a Slice
struct and always returns an MDArrayView
object. Providing a Slice
argument (where a Slice
contains a start index, a stop index, and a step interval) will return an MDArrayView
object with the same number of dimensions. Providing a dim_type
argument will return an MDArrayView
object with one fewer dimensions. It is possible to mix ordinal indexes and slice indexes by repeatedly using the square bracket operator. For example, if MDArray a
is 3-dimensional, a[Slice()][5][4]
would return a 1-dimensional MDArrayView
which is all values of index i
at j
=5 and k
=4. Note that the default Slice()
object represents a full range. Note also that since the square bracket operator always returns an MDArrayView
, that a[i][j][k]
would return an MDArrayView<T>
of one dimension of length 1, not a T&
. So in this case, what is probably desired is a(i,j,k)
.
MDArray Construction
All MDArray
constructors allocate new memory. (To construct an array that points to a view of existing memory, use the MDArrayView
class.) Each constructor needs to know the number of dimensions and the length of each dimension. This is provided by a Teuchos::ArrayView
object whose size is the number of dimensions and whose values are the lengths of each of those dimensions. A common and convenient way to provide a Teuchos::ArrayView
object to MDArray
constructors is with the overloaded Teuchos::tuple
non-member constructor functions. For example, to construct an integer array with dimensions (5,6,7), you can use
MDArray<int> a(Teuchos::tuple(5,6,7));
There are various other optional arguments that can be passed to the MDArray
constructors. These include a flag for storage order, of enumerated type Layout
, and a default fill value of type T
.
MDArray Indexing
An introductory discussion of the indexing is provided above. Here we provide more details to help users and developers understand some of the mechanics.
Since the compiler does not know the dimension of any given MDArray
, the operators to access a single element of the MDArray
originally took the following forms:
Functions and methods that take arbitrary arguments denoted by the ellipsis ("...") are called "variadic", and unfortunately, they reduce the amount of error checking that can be done, even with HAVE_DOMI_ARRAY_BOUNDSCHECK
defined. The reason for this is that the macros provided in C/C++ to handle variadic arguments do not provide a way to count the number of arguments provided. If you provide too many indexes, the excess are just ignored. If you provide too few, the behavior is undefined. Processing the variadic arguments also introduces computational overhead, so operator()
has been overloaded to accept concrete numbers of indexes:
T &
operator()(dim_type i, dim_type j, dim_type k);
const T &
operator()(dim_type i, dim_type j, dim_type k);
These specific overloads are provided for up to five dimensions. For six dimensions and higher, a variadic argument is used. This provides both greater efficiency and bounds checking (when enebaled) for five dimensions or less. If bounds checking is off, or an array has more than five dimensions, the expectation is that if you construct an MDArray
of n
dimensions, then you will call operator() with n
indexes, because no error wll be reported.
The offset represented by a set of indexes is computed by maintaining an internal array of stride lengths, called _strides
. These are initialized such that (say, for the case of a three dimensional array) a(i,j,k)
will compute offset
i * _strides[0] + j * _strides[1] + k * _strides[2]
This supplies sufficient flexibility to support both C and Fortran storage orders, simply by computing the stride lengths correctly. It also allows for correct indexing into sub-arrays. The stride values cannot be changed external to the class, but you can request a reference to their values with the
const Teuchos::Array< size_type > &
strides() const
method.
The remaining operator[]
indexing operators each return an MDArrayView
object with a view into the calling MDArray
. The operator[](dim_type)
operator returns an MDArrayView
object with one fewer dimensions. The operator[](Slice)
operator returns an MDArrayView
object with the same number of dimensions, but with a sub-view into the calling MDArray
. Which axis provides the sub-view requires a little explanation.
Suppose we set b = a[Slice]
. We expect b
to be an MDArrayView
with the same number of dimensions as a
, but with a sub-view of the first axis. Logically, we would expect b[Slice]
to also be a subview of the first axis. However, this is equivalent to a[Slice][Slice]
, and in this case we would expect that the second square brack would reference a sub-view of the second axis. In order to make a[Slice][Slice]
work the way we would expect, we have to store a private "next axis" data member, and update it appropriately as square bracket operators are applied. This means that the b[Slice]
example above would actually refer to the second axis, not the first. For this reason, it is strongly suggested that when indexing an n-dimensional MDArray
with the square bracket operator, always chain together n
square brackets, which will reset the internal "next
axis" data member to the expected value of zero.