 expr.txi 20180419 19:16:54 0700
+++ expr_.txi 20180420 14:33:06 +0200
@@ 50,42 +50,87 @@
@opindex :
An @dfn{index expression} allows you to reference or extract selected
elements of a matrix or vector.
+elements of a vector, a matrix (2D), or a higherdimensional array.
Indices may be scalars, vectors, ranges, or the special operator
@samp{:}, which may be used to select entire rows or columns.
+@samp{:}, which may be used to select entire rows, columns or
+higherdimensional slices.
Vectors are indexed using a single index expression. Matrices (2D)
and higher multidimensional arrays are indexed using either one index
or @math{N} indices where @math{N} is the dimension of the array.
When using a single index expression to index 2D or higher data the
elements of the array are taken in columnfirst order (like Fortran).
+An index expression consists of a set of parentheses enclosing @math{M}
+expressions for the index values in the respective dimensions, separated by
+commas, which subsequently will be called components of the index expression,
+with @math{M} the dimensionality of the index expression.
+
+In the simplest case, the dimensionality of the index expression @math{M} is
+equal to the dimensionality of the object it is applied to, and the
+components are all scalars. For example:
The output from indexing assumes the dimensions of the index
expression. For example:
+@example
+A = reshape (1:8, 2, 2, 2) # Create 3D array
+A =
+
+ans(:,:,1) =
+
+ 1 3
+ 2 4
+
+ans(:,:,2) =
+
+ 5 7
+ 6 8
+
+A(2, 1, 2) #second row, first column of second slice
+ #in third dimension: ans = 6
+@end example
+
+For the case of the index expression dimensionality @math{M > 1}, the size of
+the returned object in the respective dimensions is equal to the number of
+elements in the corresponding components of the index expression. When
+some of the components of the index expression are vectors or ranges,
+the returned object entries are those that correspond to the Cartesian
+product of the indices in the respective dimensions. That is, indexing into
+an array works as if one first selects the rows according to the first
+component, then the columns according to the second component, and so on.
+To continue in the example:
@example
@group
a(2) # result is a scalar
a(1:2) # result is a row vector
a([1; 2]) # result is a column vector
+A([1, 2], 1, 2) # result is a column vector: ans = [5; 6]
+A(1,[2, 1, 1],1) # result is a row vector: ans = [3, 1, 1]
+A(ones (2, 2), 1, 1) # result is a column vector: ans = [1; 1; 1; 1]
@end group
@end example
As a special case, when a colon is used as a single index, the output
is a column vector containing all the elements of the vector or
matrix. For example:
+The middle line shows that repeating entries in the index expression allows
+to replicate elements in the output, and the last line shows that for
+@math{M > 1}, that is, the index expression having more than one component,
+the shape of the components is irrelevant.
+
+A special case is indexing with a onedimensional index expression. Only in
+this case, the shape of the output is determined by the shape of the
+component of the first (and single) dimension. For example:
@example
@group
a(:) # result is a column vector
a(:)' # result is a row vector
+A([1, 2]) # result is a row vector: ans = [1, 2]
+A([1; 2]) # result is a column vector: ans = [1; 2]
@end group
@end example
The above two code idioms are often used in place of @code{reshape}
when a simple vector, rather than an arbitrarily sized array, is
needed.
+Note that this is also permissible when indexing into a multidimensional
+object (also called linear indexing). In this case, the elements of the
+array are taken in columnfirst order (like Fortran). When a colon is used
+as a single index, the output is thus a column vector containing all the
+elements of the vector or matrix, which can be a more expressive notation
+than the equivalent @code{reshape}operation.
+
+@example
+@group
+A(5) # linear indexing into threedimensional array: ans = 5
+A(:) # result is a column vector: ans = (1:8)'
+A(1:8) # result has shape of index component: ans = (1:8)
+@end group
+@end example
Given the matrix
@@ 116,14 +161,12 @@
@example
@group
a = [1, 2, 3, 4];

a(1:end/2) # first half of a => [1, 2]
a(end + 1) = 5; # append element
a(end) = []; # delete element
a(1:2:end) # odd elements of a => [1, 3]
a(2:2:end) # even elements of a => [2, 4]
a(end:1:1) # reversal of a => [4, 3, 2 , 1]
+a(end:1:1) # reversal of a => [4, 3, 2, 1]
@end group
@end example
@@ 134,24 +177,9 @@
@node Advanced Indexing
@subsection Advanced Indexing
An array with @samp{nd} dimensions can be indexed by a vector @var{idx} which
has from 1 to @samp{nd} elements. If any element of @var{idx} is not a
scalar then the complete set of index tuples will be generated from the
Cartesian product of the index elements.

For the ordinary and most common case, the number of indices
(@code{nidx = numel (@var{idx})}) matches the number of dimensions @samp{nd}.
In this case, each element of @var{idx} corresponds to its respective
dimension, i.e., @code{@var{idx}(1)} refers to dimension 1,
@code{@var{idx}(2)} refers to dimension 2, etc. If @w{@code{nidx < nd}}, and
every index is less than the size of the array in the @math{i^{th}} dimension
(@code{@var{idx}(i) < size (@var{array}, i)}), then the index expression is
padded with @w{@code{nd  nidx}} trailing singleton dimensions. If
@w{@code{nidx < nd}} but one of the indices @code{@var{idx}(i)} is outside the
size of the current array, then the last @w{@code{nd  nidx + 1}} dimensions
are folded into a single dimension with an extent equal to the product of
extents of the original dimensions. This is easiest to understand with an
example.
+When it is necessary to extract subsets of entries out of an array whose
+indices cannot be written as a Cartesian product of components, linear
+indexing together with the function @code{sub2ind} can be used. For example:
@example
A = reshape (1:8, 2, 2, 2) # Create 3D array
@@ 167,16 +195,50 @@
5 7
6 8
A(2,1,2); # Case (nidx == nd): ans = 6
A(2,1); # Case (nidx < nd), idx within array:
 # equivalent to A(2,1,1), ans = 2
A(2,4); # Case (nidx < nd), idx outside array:
 # Dimension 2 & 3 folded into new dimension of size 2x2 = 4
 # Select 2nd row, 4th element of [2, 4, 6, 8], ans = 8
+A(sub2ind (size (A), [1, 2, 1], [1, 1, 2], [1, 2, 1]))
+ # ans = [A(1, 1, 1), A(2, 1, 2), A(1, 2, 1)]
@end example
One advanced use of indexing is to create arrays filled with a single
value. This can be done by using an index of ones on a scalar value.
+An array with @samp{nd} dimensions can be indexed by an index expression which
+has from 1 to @samp{nd} or more components. For the ordinary and most common
+case, the number of components @samp{M} matches the number of dimensions
+@samp{nd}. In this case, each component corresponds to the respective
+dimension of the array. If
+@w{@code{M != nd}}, the behaviour is as if the input object had been
+reshaped so as to merge the last @w{@code{nd  M + 1}} dimensions into one
+(for @w{@code{M < nd}}) or as if trailing singleton dimensions had been
+added (for @w{@code{M > nd}}). Thus, for @w{@code{M > 1}} the
+dimensionality of the output is equal to the dimensionality of the index
+expression (apart from possible elimination of trailing singleton dimensions).
+This is easiest to understand with an example:
+
+@example
+A = reshape (1:8, 2, 2, 2) # Create 3D array
+A =
+
+ans(:,:,1) =
+
+ 1 3
+ 2 4
+
+ans(:,:,2) =
+
+ 5 7
+ 6 8
+
+A(2,1) # Reshape to 2x4matrix, second entry of
+ # first column: ans = 2
+A(2,4) # Reshape to 2x4matrix, second entry of
+ # fourth column: ans = 8
+A(:,:) # ans = reshape(A, size(A, 1), [])
+@end example
+
+@noindent
+Note here the elegant use of the double colon to replace the call to the
+@code{reshape}function.
+
+Another advanced use of linear indexing is to create arrays filled with a
+single value. This can be done by using an index of ones on a scalar value.
The result is an object with the dimensions of the index expression
and every element equal to the original scalar. For example, the
following statements
@@ 202,14 +264,11 @@
@end example
@noindent
create a 2x3 matrix with all elements equal to 13.

The last example could also be written as
+create a 2x3 matrix with all elements equal to 13, which however could have
+also been written as
@example
@group
13(ones (2, 3))
@end group
@end example
It is more efficient to use indexing rather than the code construction
@@ 225,7 +284,7 @@
@end group
@end example
It should be, noted that @code{ones (1, n)} (a row vector of ones)
+It should be noted that @code{ones (1, n)} (a row vector of ones)
results in a range (with zero increment). A range is stored
internally as a starting value, increment, end value, and total number
of values; hence, it is more efficient for storage than a vector or
@@ 247,9 +306,9 @@
which allows Octave to choose a more efficient algorithm to handle the
expression.
A general recommendation, for a user unaware of these subtleties, is
+A general recommendation for users unfamiliar with these techniques is
to use the function @code{repmat} for replicating smaller arrays into
bigger ones.
+bigger ones, which uses such tricks.
A second use of indexing is to speed up code. Indexing is a fast
operation and judicious use of it can reduce the requirement for
@@ 382,9 +441,9 @@
assigns the three result matrices to @code{u}, @code{s}, and @code{v}.
The left side of a multiple assignment expression is itself a list of
expressions, and is allowed to be a list of variable names or index
expressions. See also @ref{Index Expressions}, and @ref{Assignment Ops}.

+expressions, that is, a list of variable names potentially qualified by
+index expressions. See also @ref{Index Expressions}, and
+@ref{Assignment Ops}.
@menu
* Call by Value::
* Recursion::