NAME
ArrayGenSimplest(Type) - general array with variable no. of
indices
INCLUDE
include "ArrayGenSimplest_Type.h"
SYNTAX
class ArrayGenSimplest(Type) : public virtual VecSimplest(Type)
{
protected:
int ndim; // number of dimensions
Ptv(int) nm; // length of each dimensions, multiple index
Ptv(int) bm; // base of each dimensions, multiple index
int nm1; // length of 1D
int nm1nm2; // length 1D multiplied with length 2D
int bm0; // for increasing operator() efficiency
int local_index; // relative subscripting parameter
int current_iterator_index; // for iterating over the array entries
int totalLength (const Ptv(int)& n);
void init (int n1);
void init (int n1, int n2);
void init (int n1, int n2, int n3);
void init (const Ptv(int)& n);
// avoid function "hiding" warnings:
bool redim (Type* a, int n, int base = 0);
bool compatible (const VecSimplest(Type)& X) const;
// called by the subscript functions having a Ptv(int) argument:
int elmNo (const Ptv(int)& index, int base) const;
public:
ArrayGenSimplest(Type) ();
ArrayGenSimplest(Type) (int n1);
ArrayGenSimplest(Type) (int n1, int n2);
ArrayGenSimplest(Type) (int n1, int n2, int n3);
ArrayGenSimplest(Type) (const Ptv(int)& n); // multiple index
~ArrayGenSimplest(Type) () {}
bool redim (int n1); // one-dim. array
bool redim (int n1, int n2); // two-dim. array
bool redim (int n1, int n2, int n3); // three-dim. array
bool redim (const Ptv(int)& n); // multiple index
// (arbitrary-dim.)
bool compatible (const ArrayGenSimplest(Type)& a, bool error_message = true);
void setBase (int b1);
void setBase (int b1, int b2);
void setBase (int b1, int b2, int b3);
void setBase (const Ptv(int)& b);
// with getBase and getMaxI one can easily determine lower and
// upper bounds on loops involving ArrayGenSimplest objects, while
// getDim finds the length of the loops
// lower index:
void getBase (int& b1) const;
void getBase (int& b1, int& b2) const;
void getBase (int& b1, int& b2, int& b3) const;
void getBase (Ptv(int)& b) const;
// upper index:
void getMaxI (int& n1) const;
void getMaxI (int& n1, int& n2) const;
void getMaxI (int& n1, int& n2, int& n3) const;
void getMaxI (Ptv(int)& n) const;
int getNoIndices () const;
// length of each dimension:
void getDim (int& n1) const; // length of 1D array
void getDim (int& n1, int& n2) const; // length of 2D array
void getDim (int& n1, int& n2, int& n3) const; // length of 3D array
void getDim (Ptv(int)& n) const; // length of general dD
// array
void indexOk1 (int i, const char* message = NULL) const; // for singleIndex1
void indexOk (int i, const char* message = NULL) const;
void indexOk (int i, int j, const char* message = NULL) const;
void indexOk (int i, int j, int k, const char* message = NULL) const;
void indexOk (const Ptv(int)& index, const char* message = NULL) const;
String arraySize () const;
Type& singleIndex1 (int i); // single index, 1 to total length
const Type& singleIndex1 (int i) const;
// return the single index element number:
int multiple2single (int i) const;
int multiple2single (int i,int j) const;
int multiple2single (int i,int j,int k) const;
int multiple2single (const Ptv(int)& index) const;
int length1D() const { return nm1; }
int length1Dx2D() const { return nm1nm2;}
// set a local reference index :
void setLocalIndex (int i) const;
void setLocalIndex (int i,int j) const;
void setLocalIndex (int i,int j,int k) const;
void setLocalIndex (const Ptv(int)& index) const;
// the single index of the local element:
int getLocalIndex() const { return local_index; }
// subscript the neighbors of the local index :
Type& local (int i);
Type& local (int i, int j);
Type& local (int i, int j, int k);
Type& local (const Ptv(int)& index);
const Type& local (int i) const;
const Type& local (int i, int j) const;
const Type& local (int i, int j, int k) const;
const Type& local (const Ptv(int)& index) const;
Type& operator () (int i);
Type& operator () (int i, int j);
Type& operator () (int i, int j, int k);
Type& operator () (const Ptv(int)& index);
const Type& operator () (int i) const;
const Type& operator () (int i, int j) const;
const Type& operator () (int i, int j, int k) const;
const Type& operator () (const Ptv(int)& index) const;
void startIterator ();
bool nextEntry (); // is there a next entry?
// if yes, move to it
Type& thisEntry (); // enables assignment
const Type& thisEntry () const; // enables reading only
// illegal functions (included here with just an error message):
ArrayGenSimplest(Type) (const ArrayGenSimplest(Type)& v);
void operator = (const ArrayGenSimplest(Type)& v);
};
KEYWORDS
array, general array, multi-dimensional array
DESCRIPTION
The class implements a multi-dimensional array in terms of a
standard, one-dimensional C array. The multi-dimensional feature
is created by offering subscript operators for one, two, three
and Ptv(int) indices. The bases of the indices can be arbitrary
(see the example below). The array is parameterized and can con
tain any built-in or user defined type, cf. class VecSim
plest(Type). Further features, such as arithmetic operations,
are enabled in the derived class ArrayGen(Type).
CONSTRUCTORS AND INITIALIZATION
There are several constructors. All constructors allocate the
proper amount of memory and initialize the various internal data
structure needed for administrating the multi-dimensional array.
The base of each index must be set manually. The default base is
1. The only user required initialization is to assign values to
the entries in the array.
There is a default constructor which coincides with the default
constructor of the base class VecSimplest(Type). The other con
structors take the number of entries in each dimension of the
array as arguments. If there are more than 3 dimensions, a
Ptv(int) object is given as argument.
MEMBER FUNCTIONS
If the documentation of class VecSimplest is known and the exam
ple below is studied, most of the member functions should be
self-explanatory.
redim - redimensions the array. With this function one can change
the dimension of the array, and the number of entries of each
dimension. The base is set to 1.
setBase - enables the programmer to choose an arbitrary base for
the index of each dimension.
getBase - returns the base of the index of each dimension.
getMaxI - returns the upper index value of each dimension. If one
wants a loop over the array entries and need to extract the lower
and upper loop limits, getBase will give the lower limits, while
getMaxI will give the correct upper limits.
getNoIndices - returns the number of dimensions (or indices) of
the array.
getDim - returns the number of array entries in each dimension.
Note that if the base is unity, the number of entries equals the
return values of getMaxI. To redimension another array, getDim
extracts the correct size. If the bases should also coicide, one
must extract the bases (getBase) and set them in the new array
(setBase) after the declaration.
singleIndex1 - enables the programmer to index the possibly
multi-dimensional array by using a single index. This is conve
nient if the programmer wants to avoid separate loops over each
dimension (hence there is no need for getBase or getMaxI or
knowledge of the number of dimensions).
arraySize - returns a string containing the array size, e.g., for
a 2-dimensional array [0:3]x[-1:4] it simply returns the string
"[0:3]x[-1:4]".
operator() - enables subscripting of the array. There are several
overloaded versions. If the number if indices is less than or
equal to three, one can apply the operator() functions that have
integer arguments. These are much more efficient than the opera
tor()(Ptv) function, but the latter is more general since one can
work with a single index object, regardless of the number of
space dimensions. For two and higher dimensional arrays in
ArrayGenSimplest it is important to know that the first index
varies most rapidly. In other words, the "storage" is column-ori
ented like in Fortran arrays. This makes it easy to interface
ArrayGenSimplest to Fortran code (simply send the pointer
returned from getPtr0 to the Fortran routine). Note that MatSim
plest has a row by row storage that must be transposed before
calling Fortran code. Interchange of matrices (that is, two
dimensional arrays) between C++ and Fortran is then easier to
perform if the C++ representation of the matrix is in terms of an
ArrayGenSimplest object and not a MatSimplest object.
setLocalIndex - ables subscripting relative to the local index
set by this member function. The local index will always have the
index (0,0,).
local - subscripting relative to the index set by setLocalIndex.
For example: local(0) refers to the array entry set by the last
call to setLocalIndex, local(-1) is the previous entry and so on.
When working with 2D finite difference methods, one can call
local(-1,0), local(0,1) and so on (similarly in 3D with triple
indices). Alternatively, one can call setLocalIndex right before
the innermost loop and then run through the fastest varying index
(the first index) using local(i), where i starts at 0. A sepa
rate report on the efficiency of various indexing strategies for
finite difference methods treats this topic in detail.
getLocalIndex - returns the single index of the local index, set
by the last call to setLocalIndex, that is the index correspond
ing to the element number in VecSimplest(Type).
startIterator - starts an iteration over all the array entries.
nextEntry - moves a pointer to the next entry in the array.
Returns a true value of there is a next entry, if not, a false
value is returned.
thisEntry - returns the value of the current entry. Actually, a
reference is returned so that the function can be used for
assigning values to entries (only true for a const object).
Be aware that ArrayGenSimplest does not require the Type class to
have an operator=. Hence, the copy constructor or the assignment
operator has no meaning for ArrayGenSimplest. Since C++ automati
cally makes such functions if they are not explicitly declared
(and such automatically generated functions lead to serious
errors in the present case), the functions are declared, but the
content is just an error message.
EXAMPLES
Below we show a few call statements using the ArrayGenSimplest
class. More examples are found in the verification program that
is used to verify the implementation. That program is found in
the directory
$DPR/src/app/class-verify/category1/ArrayGenSimplest
Study the source file, compile it and study the output. An exam
ple on how the program is run is found in the script in the ver
ify subdirectory (the script has extension .sh).
// two-dimensional array with each index starting at 0:
ArrayGenSimplest(real) v (10, 10);
v.setBase (0, 0);
// valid indices: v(i,j), where 0 <= i,j <= 9
// four-dimensional array with first index starting at 0, the
others
// starting at 1:
Ptv(int) b(4), n(4), i(4);
n(1) = 10; n(2) = 5; n(3) = n(4) = 8; // dimensions
b(1) = 0; b(2) = b(3) = b(4) = 1; // base
ArrayGenSimplest(real) w (n);
w.setBase (b);
i(1) = 1; i(2) = i(3) = i(4) = 3; // 4-tuple index
w(i) = 6; // assignment, one
entry
// three-dimensional array of class Thing objects, each index
base
// equals -1, each dimension of the array equals 3:
ArrayGenSimplest(Thing) t (3,3,3);
t.setBase (-1,-1,-1);
t(0,-1,1).scan (cin);
// copy a to b manually (ArrayGenSimplest(Type) has no opera
tor=
// function, cf. class VecSimplest(Type):
int n1, n2; a.getDim (n1,n2);
ArrayGenSimplest(real) b(n1,n2);
int j,k,j1,k1,jn,kn;
a.getBase (j1,k1); a.getMaxI (jn,kn);
for (j=j1; j<=jn; j++)
for (k=k1; k<=kn; k++)
b(j,k) = a(j,k);
SEE ALSO
class ArrayGen(Type), class VecSimplest(Type)
DEVELOPED BY
SINTEF Applied Mathematics, Oslo, Norway, and University of Oslo,
Dept. of Mathematics, Norway
AUTHOR
Hans Petter Langtangen, SINTEF/UiO. Improvements by Johan Berge,
SINTEF.