Indexing Arrays, Matrices, and Vectors
About Indexing
Selecting Elements: Fully Specified Index
Selecting Elements: Overspecified Index
Selecting Elements: Underspecified Index
Selecting Elements: Extracting Subblocks
Modifying Elements: Assigning Subblocks
Modifying Elements: Resizing
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. This can also be acheived using a subscript: M1,2. 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.
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);
M≔123456789
M[2,3];
6
M(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):
A[10,-43];
−430
A(1,1);
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]):
V[-1];
4
V(-2);
3
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]):
A[-1];
Error, Array index out of range
A(-1);
9
Referencing an out-of-bounds index always raises an error.
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]);
V≔1234
V(1,2);
2
V := Vector[column]([1,2,3,4]);
V(2,1);
M := < 1, 2; 3, 4>;
M≔1234
M(1,2,1);
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]]);
A≔1234
A(1);
1
A[1];
12
for i from 1 to ArrayNumElems(A,'All') do A(i) := 2*A(i); end do: A;
2468
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);
C := Array([[1,2],[3,4]],order=C_order);
C≔1234
A(1), A(2), A(3), A(4);
1,3,2,4
C(1), C(2), C(3), C(4);
1,2,3,4
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):
M(1);
0
M(2) := 2;
M⁡2≔0000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
M(2,1);
A := LinearAlgebra:-IdentityMatrix(4);
A≔1000010000100001
A(2);
When the empty index is specified, the entire array is returned.
A := Array([[1,2],[3,4]]):
A();
1234
A[];
Ranges and lists can be used in an index to extract sub-blocks. Within round brackets, arrays can be used in place of lists.
As with most positive integer-indexed sequential data sets in Maple, negative numbers can be used to index relative to the end of an array. For a 1 dimensional array, A, the last element is A−1. Similarly, the second last element is A−2. Applying this to subblocks, A1..−1 is the full range of the array. When referencing from the beginning, or to the end, the range end-points can be omitted. So A.. gives a copy of A, A..n extracts the first n elements of A, and An.. extracts the elements from n to the end of A.
The result of subselection A[i1,i2,...,iN] 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):
a := A[1,1..2,2];
a≔33
rtable_dims(a);
1..2
The result of subselection A⁡i1,i2,…,iN 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 := A(1,1..2,2);
1..1,1..2
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[[1,3],[1,3]];
1379
M[[3,1],[3,1]];
9731
The result of subselection A[i1,i2,...,iN] 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[1..2];
123456
M[1..2,1..-1];
Using round brackets with an under-specified or over-specified index is not the same as using square brackets. The result of subselection A⁡i1,i2,…,iN 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(1..2);
14
M(2);
M(1..2,1..-1);
M(1..2,1..-1,1..1);
M(1..2,1..-1,1);
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.
A := Array(1..3,1..3);
A≔000000000
A(1..2) := 1;
A⁡1..2≔100100000
A[1..2] := 2: A;
222222000
A[1..2,1..2] := Matrix(2,2,fill=3): A;
332332000
A([1,2],2..3) := Matrix(2,2,fill=4);
A⁡1,2,2..3≔344344000
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);
A≔111111111
A[1..2,1..-1] := Matrix(1,2,fill=2): A;
220000111
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.
A(1..6) := < 1, 2, 3; 4, 5, 6 >;
A⁡1..6≔150430260
A(1..6) := < <1, 2, 3> | < 4, 5, 6> >;
A⁡1..6≔140250360
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.
V := Vector([1,2,3]);
V≔123
V[4] := 4;
Error, Vector index out of range
V(4) := 4;
V⁡4≔1234
Resizing will be performed in such a way that it takes only constant time and space on average. This is achieved by reserving extra space whenever the array needs to be grown, and then using this space for subsequent expansions without the need to reallocate memory. Maple always grows the space for the array by at least a fixed percentage, which ensures the average constant time and space usage.
See Also
Array
Matrix
rtable
Vector
Download Help Document