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	Sun Dec 11 21:32:59 2011 -0800
+++ b/doc/interpreter/expr.txi	Sun Dec 11 22:15:48 2011 -0800
@@ -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)
 
--- a/doc/interpreter/octave.texi	Sun Dec 11 21:32:59 2011 -0800
+++ b/doc/interpreter/octave.texi	Sun Dec 11 22:15:48 2011 -0800
@@ -383,6 +383,10 @@
 * Increment Ops::               
 * Operator Precedence::         
 
+Index Expressions
+
+* Advanced Indexing::           
+
 Calling Functions
 
 * Call by Value::