18.4 Multiple indexes with vectors and matrices
Multiple indexes can be supplied to vectors and matrices as well as arrays of vectors and matrices.
Vectors and row vectors behave exactly the same way as arrays with
multiple indexes. If
v is a vector, then
v is a
scalar real value, whereas
v[2:4] is a vector of size 3
containing the elements
The only subtlety with vectors is in inferring the return type when there are multiple indexes. For example, consider the following minimal example.
array vector v; array int idxs; // ... vector u; u = v[2, idxs]; array real w; w = v[idxs, 2];
The key is understanding that a single index always reduces
dimensionality, whereas a multiple index never does. The dimensions
with multiple indexes (and unindexed dimensions) determine the indexed
expression’s type. In the example above, because
v is an array
v[2, idxs] reduces the array dimension but doesn’t
reduce the vector dimension, so the result is a vector. In contrast,
v[idxs, 2] does not reduce the array dimension, but does reduce
the vector dimension (to a scalar), so the result type for
an array of reals. In both cases, the size of the multiple index
(here, 7) determines the size of the result.
Matrices are a bit trickier because they have two dimensions, but the underlying principle of type inference is the same—multiple indexes leave dimensions in place, whereas single indexes reduce them. The following code shows how this works for multiple indexing of matrices.
matrix[5, 7] m; // ... row_vector rv; rv = m[4, 3:5]; // result is 1 x 3 // ... vector v; v = m[2:5, 3]; // result is 3 x 1 // ... matrix[3, 4] m2; m2 = m[1:3, 2:5]; // result is 3 x 4
The key is realizing that any position with a multiple index or bounded index remains in play in the result, whereas any dimension with a single index is replaced with 1 in the resulting dimensions. Then the type of the result can be read off of the resulting dimensionality as indicated in the comments above.
Matrices with one multiple index
If matrices receive a single multiple index, the result is a matrix.
m is a matrix, so is
m[2:4]. In contrast,
supplying a single index,
m, produces a row vector result.
m produces the same result as
Arrays of vectors or matrices
With arrays of matrices, vectors, and row vectors, the basic access rules remain exactly the same: single indexes reduce dimensionality and multiple indexes redirect indexes. For example, consider the following example.
array[5, 7] matrix[3, 4] m; // ... array matrix[3, 4] a; a = m[1, 2:3]; // knock off first array dimension a = m[3:4, 5]; // knock off second array dimension
In both assignments, the multiple index knocks off an array dimension,
but it’s different in both cases. In the first case,
a[i] == m[1, i + 1], whereas in the second case,
a[i] == m[i + 2, 5].
Continuing the previous example, consider the following.
// ... vector b; b = a[1, 3, 2:3, 2];
Here, the two array dimensions are reduced as is the column dimension
of the matrix, leaving only a row dimension index, hence the result is
a vector. In this case,
b[j] == a[1, 3, 1 + j, 2].
This last example illustrates an important point: if there is a
lower-bounded index, such as
2:3, with lower bound 2, then the
lower bound minus one is added to the index, as seen in the
1 + j expression above.
Continuing further, consider continuing with the following.
// ... array row_vector c; c = a[4:5, 3, 1, 2: ];
Here, the first array dimension is reduced, leaving a single array
dimension, and the row index of the matrix is reduced, leaving a row
vector. For indexing, the values are given by
c[i, j] == a[i + 3, 3, 1, j + 1]
Block, row, and column extraction for matrices
Matrix slicing can also be performed using the
block function. For
matrix[20, 20] a = ...; matrix[3, 2] b = block(a, 5, 9, 3, 2);
b equal to the submatrix of
a starting at index [5, 9]
and extending 3 rows and 2 columns. Thus
block(a, 5, 9, 3, 2) is
sub_col function extracts a slice of a column of a matrix as a
vector. For example,
matrix[10, 10] a = ...; vector b = sub_col(a, 2, 3, 5);
b equal to the vector
a[2:6, 3], taking the element
starting at [2, 3], then extending for a total of 5 rows. The
sub_row works the same way for extracting a slice of a row
as a row vector. For example,
sub_row(a, 2, 3, 5) is equal to
the row vector
a[2, 3:7], which also starts at position [2, 3] then
extends for a total of 5 columns.