Indexing Arrays, Matrices, and Vectors
|
About Indexing
|
|
•
|
Indexing refers to the act of putting an index (or subscript) on a variable assigned to an Array, Matrix, or Vector. For example, if M is a Matrix, then a simple indexing operation is M[1,2], which will extract the element in the first row and second column of M. More complicated indexing operations involve selecting or assigning multiple entries.
|
•
|
Maple understands two distinct notations for indexing. Mathematical indexing is achieved via square brackets, M[index], and Programmer indexing is achieved via round brackets, M(index). Only rtable subtypes (Array, Matrix, Vector) understand programmer indexing. In other contexts this is understood as invoking a function call. The distinctions between mathematical and programmer indexing are outlined below.
|
|
|
Selecting Elements: Fully Specified Index
|
|
•
|
In the most basic case, N integers are supplied in the index for a given N-dimensional Array. Provided the Array's dimensions all begin at 1, both mathematical and programmer indexing will return the same single element.
|
>
|
M := Matrix(3,3,(i,j)->3*i+j-3);
|
| (1) |
| (2) |
| (3) |
•
|
Unlike Matrices and Vectors, Arrays can have dimensions beginning with values other than 1. Indexing with square brackets respects the actual index, while using round brackets normalizes the dimensions to begin with 1.
|
>
|
A := Array(10..12,-43..-42,(i,j)->i*j):
|
| (4) |
| (5) |
•
|
When an Array has dimensions beginning at one, negative integer indices can be used to count backwards from the end of a dimension.
|
>
|
V := Vector([1,2,3,4]):
|
| (6) |
| (7) |
•
|
Because programmer indexing is always relative to 1, negative indices can be used for any Array. Mathematical indexing will raise an exception when it sees a negative index unless that value is actually within the Array's specified bounds.
|
>
|
A := Array(5..9,[5,6,7,8,9]):
|
| (8) |
•
|
Referencing an out-of-bounds index always raises an error.
|
|
|
Selecting Elements: Overspecified Index
|
|
•
|
With mathematical indexing, an exception is raised when more integers are specified in an index than there are dimensions in the given array. Programmer indexing allows any Array to be treated as any-dimensional. Thus, a 2x2 Array can be indexed as if it was 2x2x1, which is conceptually the same. Additionally, row vectors can be treated as 1xN arrays.
|
>
|
V := Vector[row]([1,2,3,4]);
|
| (9) |
| (10) |
>
|
V := Vector[column]([1,2,3,4]);
|
| (11) |
| (12) |
| (13) |
| (14) |
|
|
Selecting Elements: Underspecified Index
|
|
•
|
When an index contains fewer elements than there are dimensions in the array being indexed, square-bracket indexing returns the sub-array implicitly specified with the full range of each missing dimension.
|
|
Programmer indexing instead takes a view of the array as if it contained the same number of dimensions as specified indices, where the last dimension is the size of the product of all remaining dimensions. Practically, this is the same as computing the Fortran-order offset into the array data-block, which is part of the reason for classifying round-bracket indexing as "programmer" indexing. Programmer indexing allows you to access each element in an array with a single integer.
|
>
|
A := Array([[1,2],[3,4]]);
|
| (15) |
| (16) |
| (17) |
>
|
for i from 1 to ArrayNumElems(A,'All') do
A(i) := 2*A(i);
end do:
A;
|
| (18) |
•
|
The order of elements returned corresponds to the actual order in which they are stored in the underlying data structure. Therefore, underspecified indexing of C_order arrays will yield a different order than Fortran_order arrays.
|
>
|
A := Array([[1,2],[3,4]],order=Fortran_order);
|
| (19) |
>
|
C := Array([[1,2],[3,4]],order=C_order);
|
| (20) |
>
|
A(1), A(2), A(3), A(4);
|
| (21) |
>
|
C(1), C(2), C(3), C(4);
|
| (22) |
•
|
Sparse arrays, and arrays with other special storage and/or indexing functions, behave as if they were dense Fortran_order. In this way zeros can be fetched from sparse arrays, and indexing functions always get an equivalent fully-specified index.
|
>
|
M := Matrix(10,10,storage=sparse):
|
| (23) |
| (24) |
| (25) |
>
|
A := LinearAlgebra:-IdentityMatrix(4);
|
| (26) |
| (27) |
| (28) |
•
|
When the empty index is specified, the entire array is returned.
|
>
|
A := Array([[1,2],[3,4]]):
|
| (29) |
| (30) |
|
|
Selecting Elements: Extracting Subblocks
|
|
•
|
Ranges and lists can be used in an index to extract sub-blocks. Within round brackets, arrays can be used in place of lists.
|
•
|
The result of subselection on an N-dimensional array will have 1 dimension per non-integer index. So, if i2 is a range, and i1, i3, .., iN are all integers, the resulting sub-array will be 1-dimensional. The width of that dimension will be the number of elements in the given list, or the number of elements in the span of the given range.
|
>
|
A := Array(1..2,1..2,1..2,fill=3):
|
| (31) |
| (32) |
•
|
The result of subselection on an N-dimensional array is not the same as the indexing with square brackets. In this case, the number of dimensions of the result will correspond to the location of the last non-singleton index. That is, if the ith index is the last non-integer index then the result will have i dimensions.
|
>
|
A := Array(1..2,1..2,1..2,fill=3):
|
| (33) |
| (34) |
•
|
The result is formed conceptually by iterating through all permutations of supplied indices and performing simple integer index extractions from the source array in order.
|
>
|
M := Matrix(3,3,(i,j)->3*i+j-3);
|
| (35) |
| (36) |
| (37) |
•
|
The result of subselection on an M-dimensional array will raise an exception if N > M. When N < M, the index is under-specified. The result will behave as if iN+1, .., iM were specified as the full range of the corresponding dimension.
|
>
|
M := Matrix(3,3,(i,j)->3*i+j-3);
|
| (38) |
| (39) |
| (40) |
•
|
Using round brackets with an under-specified or over-specified index is not the same as using square brackets. The result of subselection on an M-dimensional array will raise an exception if N > M when iN+1 and higher are non-singleton. When N < M, the result will behave as if the array being indexed only had N dimensions as in the case of a simple all-integer under-specified index.
|
>
|
M := Matrix(3,3,(i,j)->3*i+j-3);
|
| (41) |
| (42) |
| (43) |
| (44) |
| (45) |
| (46) |
| (47) |
|
|
Modifying Elements: Assigning Subblocks
|
|
•
|
Regions of an array can be specified inside an index on the left side of an assignment statement. Using the same rules for selection to denote which elements will be affected, the specified subblock will be updated with the value on the right side of the assignment statement. If the right side is an rtable-based Array, Matrix, or Vector the assignment will basically insert the elements of the value array into the subblock of the array being assigned to. If the right side is not an rtable-based Array, Matrix, or Vector, every element specified in the array being assigned to will be updated with the whole value.
|
| (48) |
| (49) |
| (50) |
>
|
A[1..2,1..2] := Matrix(2,2,fill=3): A;
|
| (51) |
>
|
A([1,2],2..3) := Matrix(2,2,fill=4);
|
| (52) |
•
|
When the value array is smaller than the specified region to be assigned to, square bracket indexing fills in the missing elements with zeros. This zero expansion is not done with round bracket indexing.
|
>
|
A := Array(1..3,1..3,fill=1);
|
| (53) |
>
|
A[1..2,1..-1] := Matrix(1,2,fill=2): A;
|
| (54) |
•
|
Normally the dimensions of the right and left side of the assignment must match. A special case exists with round-bracket indexing when the left side selection specifies only one dimension. In that case the right side of the assignment is flattened. More precisely, round-bracket indexing is used to extract the elements from the value array.
|
| (55) |
>
|
A(1..6) := < 1, 2, 3; 4, 5, 6 >;
|
| (56) |
>
|
A(1..6) := < <1, 2, 3> | < 4, 5, 6> >;
|
| (57) |
|
|
Modifying Elements: Resizing
|
|
•
|
Attempting to assign to an element outside the bounds of the given array will result in an out-of-bounds exception with square-bracket indexing. This provides protection from accidentally assigning to an element outside your initial boundaries. Using round-brackets, assigning to an out-of-bounds element will cause the array to grow so that it can hold that element.
|
| (58) |
|
|
Examples
|
|
>
|
|
| (59) |
|
|