Mercurial > hg > octave-lojdl
changeset 14033:dfbf6a49847c stable
doc: Update documentation on indexing expressions
* expr.txi, octave.texi: Update documentation on indexing expressions
author | Rik <octave@nomad.inbox5.com> |
---|---|
date | Sun, 11 Dec 2011 22:15:48 -0800 |
parents | 8497d89a17f1 |
children | 026b44b195b3 |
files | doc/interpreter/expr.txi doc/interpreter/octave.texi |
diffstat | 2 files changed, 148 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/interpreter/expr.txi +++ b/doc/interpreter/expr.txi @@ -55,28 +55,36 @@ Indices may be scalars, vectors, ranges, or the special operator @samp{:}, which may be used to select entire rows or columns. -Vectors are indexed using a single index expression. Matrices may be -indexed using one or two indices. When using a single index -expression, the elements of the matrix are taken in column-first order; -the dimensions of the output match those of the index expression. For -example, +Vectors are indexed using a single index expression. Matrices (2-D) +and higher multi-dimensional 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 2-D or higher data the +elements of the array are taken in column-first order (like Fortran). + +The output from indexing assumes the dimensions of the index +expression. For example, @example @group -a(2) # a scalar -a(1:2) # a row vector -a([1; 2]) # a column vector +a(2) # result is a scalar +a(1:2) # result is a row vector +a([1; 2]) # result is a column vector @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: +is a column vector containing all the elements of the vector or +matrix. For example: @example -a(:) # a column vector +a(:) # result is a column vector +a(:)' # result is a row vector @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. + Given the matrix @example @@ -84,32 +92,91 @@ @end example @noindent -all of the following expressions are equivalent +all of the following expressions are equivalent and select the first +row of the matrix. @example @group -a(1, [1, 2]) -a(1, 1:2) -a(1, :) +a(1, [1, 2]) # row 1, columns 1 and 2 +a(1, 1:2) # row 1, columns in range 1-2 +a(1, :) # row 1, all columns +@end group +@end example + +@cindex @code{end}, indexing +@cindex :end + +In index expressions the keyword @code{end} automatically refers to +the last entry for a particular dimension. This magic index can also +be used in ranges and typically eliminates the needs to call +@code{size} or @code{length} to gather array bounds before indexing. +For example: + +@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] @end group @end example -@noindent -and select the first row of the matrix. +@menu +* Advanced Indexing:: +@end menu + +@node Advanced Indexing +@subsection Advanced Indexing + +An array with @samp{n} dimensions can be indexed using @samp{m} +indices. More generally, the set of index tuples determining the +result is formed by the Cartesian product of the index vectors (or +ranges or scalars). + +For the ordinary and most common case, @w{@code{m == n}}, and each +index corresponds to its respective dimension. If @w{@code{m < n}} +and every index is less than the size of the array in the +@math{i^{th}} dimension, @code{m(i) < n(i)}, then the index expression +is padded with trailing singleton dimensions (@code{[ones (m-n, 1)]}). +If @w{@code{m < n}} but one of the indices @code{m(i)} is outside the +size of the current array, then the last @w{@code{n-m+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. -In general, an array with @samp{n} dimensions can be indexed using @samp{m} -indices. If @code{n == m}, each index corresponds to its respective dimension. -The set of index tuples determining the result is formed by the Cartesian -product of the index vectors (or ranges or scalars). If @code{n < m}, then the -array is padded by trailing singleton dimensions. If @code{n > m}, the last -@code{n-m+1} dimensions are folded into a single dimension with extent equal to -product of extents of the original dimensions. +@example +@group +a = reshape (1:8, 2, 2, 2) # Create 3-D array +a = + +ans(:,:,1) = + + 1 3 + 2 4 + +ans(:,:,2) = + + 5 7 + 6 8 -@c FIXED -- sections on variable prefer_zero_one_indexing were removed +a(2,1,2); # Case (m == n): ans = 6 +a(2,1); # Case (m < n), idx within array: + # equivalent to a(2,1,1), ans = 2 +a(2,4); # Case (m < n), 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 +@end group +@end example -Indexing a scalar with a vector of ones can be used to create a -vector the same size as the index vector, with each element equal to -the value of the original scalar. For example, the following statements +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. +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 @example @group @@ -121,8 +188,8 @@ @noindent produce a vector whose four elements are all equal to 13. -Similarly, indexing a scalar with two vectors of ones can be used to -create a matrix. For example the following statements +Similarly, by indexing a scalar with two vectors of ones it is +possible to create a matrix. The following statements @example @group @@ -132,20 +199,35 @@ @end example @noindent -create a 2 by 3 matrix with all elements equal to 13. +create a 2x3 matrix with all elements equal to 13. The last example could also be written as @example @group -13 (ones (2, 3)) +13(ones (2, 3)) @end group @end example -It should be, noted that @code{ones (1, n)} (a row vector of ones) results in a -range (with zero increment), and is therefore more efficient when used in index -expression than other forms of @dfn{ones}. In particular, when @samp{r} is a -row vector, the expressions +It is more efficient to use indexing rather than the code construction +@code{scalar * ones (N, M, @dots{})} because it avoids the unnecessary +multiplication operation. Moreover, multiplication may not be +defined for the object to be replicated whereas indexing an array is +always defined. The following code shows how to create a 2x3 cell +array from a base unit which is not itself a scalar. + +@example +@group +@{"Hello"@}(ones (2, 3)) +@end group +@end example + +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 +matrix of ones whenever the number of elements is greater than 4. In +particular, when @samp{r} is a row vector, the expressions @example r(ones (1, n), :) @@ -156,17 +238,22 @@ @end example @noindent -will produce identical results, but the first one will be significantly -faster, at least for @samp{r} and @samp{n} large enough. The reason is that -in the first case the index is kept in a compressed form, which allows Octave -to choose a more efficient algorithm to handle the expression. +will produce identical results, but the first one will be +significantly faster, at least for @samp{r} and @samp{n} large enough. +In the first case the index is held in compressed form as a range +which allows Octave to choose a more efficient algorithm to handle the +expression. -In general, for an user unaware of these subtleties, it is best to use -the function @dfn{repmat} for spreading arrays into bigger ones. +A general recommendation, for a user unaware of these subtleties, is +to use the function @code{repmat} for replicating smaller arrays into +bigger ones. -It is also possible to create a matrix with different values. The -following example creates a 10 dimensional row vector @math{a} containing -the values +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 +looping over individual array elements which is a slow operation. + +Consider the following example which creates a 10-element row vector +@math{a} containing the values @tex $a_i = \sqrt{i}$. @end tex @@ -183,20 +270,22 @@ @end example @noindent -Note that it is quite inefficient to create a vector using a loop like -the one shown in the example above. In this particular case, it would -have been much more efficient to use the expression +It is quite inefficient to create a vector using a loop like this. In +this case, it would have been much more efficient to use the +expression @example a = sqrt (1:10); @end example @noindent -thus avoiding the loop entirely. In cases where a loop is still -required, or a number of values must be combined to form a larger -matrix, it is generally much faster to set the size of the matrix first, -and then insert elements using indexing commands. For example, given a -matrix @code{a}, +which avoids the loop entirely. + +In cases where a loop cannot be avoided, or a number of values must be +combined to form a larger matrix, it is generally faster to set the +size of the matrix first (pre-allocate storage), and then insert +elements using indexing commands. For example, given a matrix +@code{a}, @example @group @@ -221,8 +310,8 @@ @end example @noindent -particularly for large matrices because Octave does not have to -repeatedly resize the result. +because Octave does not have to repeatedly resize the intermediate +result. @DOCSTRING(sub2ind)