### 2.6 Member functions ¶

#### 2.6.1 A note about dimension parameters ¶

Several of the member functions take a dimension parameter which is an integer in the range 0 .. `N_rank`-1. For example, the method `extent(int n)` returns the extent (or length) of the array in dimension `n`.

These parameters are problematic:

- They make the code cryptic. Someone unfamiliar with the `reverse()` member function won’t stand a chance of understanding what `A.reverse(2)` does.
- Some users are used to dimensions being 1 .. `N_rank`, rather than 0 .. `N_rank`-1. This makes dimension numbers inherently error-prone. Even though I’m a experienced C/C++ programmer, I still want to think of the first dimension as 1 – it doesn’t make sense to talk about the “zeroth” dimension.

As a solution to this problem, Blitz++ provides a series of symbolic constants which you can use to refer to dimensions:

    const int firstDim    = 0;
    const int secondDim   = 1;
    const int thirdDim    = 2;
       .
       .
    const int eleventhDim = 10;

These symbols should be used in place of the numerals 0, 1, ... `N_rank`-1. For example:

    A.reverse(thirdDim);

This code is clearer: you can see that the parameter refers to a dimension, and it isn’t much of a leap to realize that it’s reversing the element ordering in the third dimension.

If you find `firstDim`, `secondDim`, ... aesthetically unpleasing, there are equivalent symbols `firstRank`, `secondRank`, `thirdRank`, ..., `eleventhRank`.

#### Why stop at eleven? ¶

The symbols had to stop somewhere, and eleven seemed an appropriate place to stop. Besides, if you’re working in more than eleven dimensions your code is going to be confusing no matter what help Blitz++ provides.

#### 2.6.2 Member function descriptions ¶

    const TinyVector<int, N_rank>&    base() const;
    int                               base(int dimension) const;

The base of a dimension is the first valid index value. A typical C-style array will have base of zero; a Fortran-style array will have base of one. The base can be different for each dimension, but only if you deliberately use a Range-argument constructor or design a custom storage ordering.

The first version returns a reference to the vector of base values. The second version returns the base for just one dimension; it’s equivalent to the `lbound()` member function. See the note on dimension parameters such as `firstDim` above.

    Array<T,N>::iterator              begin();
    Array<T,N>::const_iterator        begin() const;

These functions return STL-style forward and input iterators, respectively, positioned at the first element of the array. Note that the array data is traversed in memory order (i.e. by rows for C-style arrays, and by columns for Fortran-style arrays). The `Array<T,N>::const_iterator` has these methods:

    const_iterator(const Array<T,N>&);
    T operator*() const;
    const T* [restrict] operator->() const;
    const_iterator& operator++();
    void operator++(int);
    bool operator==(const const_iterator<T,N>&) const;
    bool operator!=(const const_iterator<T,N>&) const;
    const TinyVector<int,N>& position() const;

Note that postfix ++ returns void (this is not STL-compliant, but is done for efficiency). The method `position()` returns a vector containing current index positions of the iterator. The `Array<T,N>::iterator` has the same methods as `const_iterator`, with these exceptions: `iterator& operator++(); T& operator*(); T* [restrict] operator->();` The `iterator` type may be used to modify array elements. To obtain iterator positioned at the end of the array, use the `end()` methods.

    int                               cols() const;
    int                               columns() const;

Both of these functions return the extent of the array in the second dimension. Equivalent to `extent(secondDim)`. See also `rows()` and `depth()`.

    Array<T_numtype, N_rank>          copy() const;

This method creates a copy of the array’s data, using the same storage ordering as the current array. The returned array is guaranteed to be stored contiguously in memory, and to be the only object referring to its memory block (i.e. the data isn’t shared with any other array object).

    const T_numtype* [restrict]       data() const;
          T_numtype* [restrict]       data();
    const T_numtype* [restrict]       dataZero() const;
          T_numtype* [restrict]       dataZero();
    const T_numtype* [restrict]       dataFirst() const;
          T_numtype* [restrict]       dataFirst();

These member functions all return pointers to the array data. The NCEG `restrict` qualifier is used only if your compiler supports it. If you’re working with the default storage order (C-style arrays with base zero), you’ll only need to use `data()`. Otherwise, things get complicated:

`data()` returns a pointer to the element whose indices are equal to the array base. With a C-style array, this means the element (0,0,...,0); with a Fortran-style array, this means the element (1,1,...,1). If `A` is an array object, `A.data()` is equivalent to (&A(A.base(firstDim), A.base(secondDim), ...)). If any of the dimensions are stored in reverse order, `data()` will not refer to the element which comes first in memory.

`dataZero()` returns a pointer to the element (0,0,...,0), even if such an element does not exist in the array. What’s the point of having such a pointer? Say you want to access the element (i,j,k). If you add to the pointer the dot product of (i,j,k) with the stride vector (`A.stride()`), you get a pointer to the element (i,j,k).

`dataFirst()` returns a pointer to the element of the array which comes first in memory. Note however, that under some circumstances (e.g. subarrays), the data will not be stored contiguously in memory. You have to be very careful when meddling directly with an array’s data.

Other relevant functions are: `isStorageContiguous()` and `zeroOffset()`.

    int                               depth() const;

Returns the extent of the array in the third dimension. This function is equivalent to `extent(thirdDim)`. See also `rows()` and `columns()`.

    int                               dimensions() const;

Returns the number of dimensions (rank) of the array. The return value is the second template parameter (`N_rank`) of the `Array` object. Same as `rank()`.

    RectDomain<N_rank>                domain() const;

Returns the domain of the array. The domain consists of a vector of lower bounds and a vector of upper bounds for the indices. NEEDS_WORK– need a section to explain methods of `RectDomain<N>`.

    Array<T,N>::iterator              end();
    Array<T,N>::const_iterator        end() const;

Returns STL-style forward and input iterators (respectively) for the array, positioned at the end of the array.

    int                               extent(int dimension) const;

The first version the extent (length) of the array in the specified dimension. See the note about dimension parameters such as `firstDim` in the previous section.

    Array<T_numtype2,N_rank>          extractComponent(T_numtype2,
                                      int componentNumber, int numComponents);

This method returns an array view of a single component of a multicomponent array. In a multicomponent array, each element is a tuple of fixed size. The components are numbered 0, 1, ..., `numComponents-1`. Example:

    Array<TinyVector<int,3>,2> A(128,128);  // A 128x128 array of int[3]

    Array<int,2> B = A.extractComponent(int(), 1, 3);

Now the B array refers to the 2nd component of every element in A. Note: for complex arrays, special global functions `real(A)` and `imag(A)` are provided to obtain real and imaginary components of an array. See the Global Functions section.

    void                              free();

This method resizes an array to zero size. If the array data is not being shared with another array object, then it is freed.

    bool                              isMajorRank(int dimension) const;

Returns true if the dimension has the largest stride. For C-style arrays (the default), the first dimension always has the largest stride. For Fortran-style arrays, the last dimension has the largest stride. See also `isMinorRank()` below and the note about dimension parameters such as `firstDim` in the previous section.

    bool                              isMinorRank(int dimension) const;

Returns true if the dimension does not have the largest stride. See also `isMajorRank()`.

    bool                              isRankStoredAscending(int dimension) const;

Returns true if the dimension is stored in ascending order in memory. This is the default. It will only return false if you have reversed a dimension using `reverse()` or have created a custom storage order with a descending dimension.

    bool                              isStorageContiguous() const;

Returns true if the array data is stored contiguously in memory. If you slice the array or work on subarrays, there can be skips – the array data is interspersed with other data not part of the array. See also the various `data..()` functions. If you need to ensure that the storage is contiguous, try `reference(copy())`.

    int                               lbound(int dimension) const;
    TinyVector<int,N_rank>            lbound() const;

The first version returns the lower bound of the valid index range for a dimension. The second version returns a vector of lower bounds for all dimensions. The lower bound is the first valid index value. If you’re using a C-style array (the default), the lbound will be zero; Fortran-style arrays have lbound equal to one. The lbound can be different for each dimension, but only if you deliberately set them that way using a Range constructor or a custom storage ordering. This function is equivalent to `base(dimension)`. See the note about dimension parameters such as `firstDim` in the previous section.

    void                              makeUnique();

If the array’s data is being shared with another Blitz++ array object, this member function creates a copy so the array object has a unique view of the data.

    int                               numElements() const;

Returns the total number of elements in the array, calculated by taking the product of the extent in each dimension. Same as `size()`.

    const TinyVector<int, N_rank>&    ordering() const;
    int                               ordering(int storageRankIndex) const;

These member functions return information about how the data is ordered in memory. The first version returns the complete ordering vector; the second version returns a single element from the ordering vector. The argument for the second version must be in the range 0 .. `N_rank`-1. The ordering vector is a list of dimensions in increasing order of stride; `ordering(0)` will return the dimension number with the smallest stride, and `ordering(N_rank-1)` will return the dimension number with largest stride. For a C-style array, the ordering vector contains the elements (`N_rank`-1, `N_rank`-2, ..., 0). For a Fortran-style array, the ordering vector is (0, 1, ..., `N_rank`-1). See also the description of custom storage orders in section Array storage orders.

    int                               rank() const;

Returns the rank (number of dimensions) of the array. The return value is equal to `N_rank`. Equivalent to `dimensions()`.

    void                              reference(Array<T_numtype,N_rank>& A);

This causes the array to adopt another array’s data as its own. After this member function is used, the array object and the array `A` are indistinguishable – they have identical sizes, index ranges, and data. The data is shared between the two arrays.

    void                              reindexSelf(const TinyVector<int,N_rank>&);
    Array<T,N>                        reindex(const TinyVector<int,N_rank>&);

These methods reindex an array to use a new base vector. The first version reindexes the array, and the second just returns a reindexed view of the array, leaving the original array unmodified.

    void                              resize(int extent1, ...);
    void                              resize(const TinyVector<int,N_rank>&);

These functions resize an array to the specified size. If the array is already the size specified, then no memory is allocated. After resizing, the contents of the array are garbage. See also `resizeAndPreserve()`.

    void                              resizeAndPreserve(int extent1, ...);
    void                              resizeAndPreserve(const TinyVector<int,N_rank>&);

These functions resize an array to the specified size. If the array is already the size specified, then no change occurs (the array is not reallocated and copied). The contents of the array are preserved whenever possible; if the new array size is smaller, then some data will be lost. Any new elements created by resizing the array are left uninitialized.

    Array<T,N>                        reverse(int dimension);
    void                              reverseSelf(int dimension);

This method reverses the array in the specified dimension. For example, if `reverse(firstDim)` is invoked on a 2-dimensional array, then the ordering of rows in the array will be reversed; `reverse(secondDim)` would reverse the order of the columns. Note that this is implemented by twiddling the strides of the array, and doesn’t cause any data copying. The first version returns a reversed “view” of the array data; the second version applies the reversal to the array itself.

    int                               rows() const;

Returns the extent (length) of the array in the first dimension. This function is equivalent to `extent(firstDim)`. See also `columns()`, and `depth()`.

    int                               size() const;

Returns the total number of elements in the array, calculated by taking the product of the extent in each dimension. Same as `numElements()`.

    const TinyVector<int, N_rank>&    shape() const;

Returns the vector of extents (lengths) of the array.

    const TinyVector<int, N_rank>&    stride() const;
    int                               stride(int dimension) const;

The first version returns the stride vector; the second version returns the stride associated with a dimension. A stride is the distance between pointers to two array elements which are adjacent in a dimension. For example, `A.stride(firstDim)` is equal to `&A(1,0,0) - &A(0,0,0)`. The stride for the second dimension, `A.stride(secondDim)`, is equal to `&A(0,1,0) - &A(0,0,0)`, and so on. For more information about strides, see the description of custom storage formats in Section Array storage orders. See also the description of parameters like `firstDim` and `secondDim` in the previous section.

    Array<T,N>                        transpose(int dimension1,
                                                int dimension2, ...);
    void                              transposeSelf(int dimension1,
                                                    int dimension2, ...);

These methods permute the dimensions of the array. The dimensions of the array are reordered so that the first dimension is `dimension1`, the second is `dimension2`, and so on. The arguments should be a permutation of the symbols `firstDim, secondDim, ...`. Note that this is implemented by twiddling the strides of the array, and doesn’t cause any data copying. The first version returns a transposed “view” of the array data; the second version transposes the array itself.

    int                               ubound(int dimension) const;
    TinyVector<int,N_rank>            ubound() const;

The first version returns the upper bound of the valid index range for a dimension. The second version returns a vector of upper bounds for all dimensions. The upper bound is the last valid index value. If you’re using a C-style array (the default), the ubound will be equal to the `extent(dimension)-1`. Fortran-style arrays will have ubound equal to `extent(dimension)`. The ubound can be different for each dimension. The return value of `ubound(dimension)` will always be equal to `lbound(dimension)+extent(dimension)-1`. See the note about dimension parameters such as `firstDim` in the previous section.

    int                               zeroOffset() const;

This function has to do with the storage of arrays in memory. You may want to refer to the description of the `data..()` member functions and of custom storage orders in Section Array storage orders for clarification. The return value of `zeroOffset()` is the distance from the first element in the array to the (possibly nonexistant) element `(0,0,...,0)`. In this context, “first element” returns to the element `(base(firstDim),base(secondDim),...)`.