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 Ndimensional 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+j3);

 (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 outofbounds 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 anydimensional. 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, squarebracket indexing returns the subarray 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 Fortranorder offset into the array datablock, which is part of the reason for classifying roundbracket 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 fullyspecified 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 subblocks. Within round brackets, arrays can be used in place of lists.

•

The result of subselection on an Ndimensional array will have 1 dimension per noninteger index. So, if i2 is a range, and i1, i3, .., iN are all integers, the resulting subarray will be 1dimensional. 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 Ndimensional 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 nonsingleton index. That is, if the ith index is the last noninteger 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+j3);

 (35) 
 (36) 
 (37) 
•

The result of subselection on an Mdimensional array will raise an exception if N > M. When N < M, the index is underspecified. 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+j3);

 (38) 
 (39) 
 (40) 
•

Using round brackets with an underspecified or overspecified index is not the same as using square brackets. The result of subselection on an Mdimensional array will raise an exception if N > M when iN+1 and higher are nonsingleton. When N < M, the result will behave as if the array being indexed only had N dimensions as in the case of a simple allinteger underspecified index.

>

M := Matrix(3,3,(i,j)>3*i+j3);

 (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 rtablebased 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 rtablebased 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 roundbracket indexing when the left side selection specifies only one dimension. In that case the right side of the assignment is flattened. More precisely, roundbracket 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 outofbounds exception with squarebracket indexing. This provides protection from accidentally assigning to an element outside your initial boundaries. Using roundbrackets, assigning to an outofbounds element will cause the array to grow so that it can hold that element.

 (58) 
 (59) 

