# HG changeset patch # User Kai T. Ohlhus # Date 1468236058 -7200 # Node ID 67a44207da719596a02bd5f6a006987e82a7c577 # Parent bf5fbf347aafd8e8f808e3ca819569daf357791f ind2sub: Ensure Matlab compatibility and improve documentation (bug #48092). libinterp/corefcn/sub2ind.cc (Fsub2ind): improve documentation. libinterp/corefcn/sub2ind.cc (Find2sub): Fix subscripts, if less subscripts are demanded, than dimensions are specified. Improved documentation. New tests. diff -r bf5fbf347aaf -r 67a44207da71 libinterp/corefcn/sub2ind.cc --- a/libinterp/corefcn/sub2ind.cc Mon Jul 11 09:27:10 2016 +0200 +++ b/libinterp/corefcn/sub2ind.cc Mon Jul 11 13:20:58 2016 +0200 @@ -1,6 +1,6 @@ /* -Copyright (C) 2009-2015 VZLU Prague +Copyright (C) 2009-2016 VZLU Prague This file is part of Octave. @@ -62,16 +62,31 @@ doc: /* -*- texinfo -*- @deftypefn {} {@var{ind} =} sub2ind (@var{dims}, @var{i}, @var{j}) @deftypefnx {} {@var{ind} =} sub2ind (@var{dims}, @var{s1}, @var{s2}, @dots{}, @var{sN}) -Convert subscripts to a linear index. +Convert subscripts to linear indices. -The following example shows how to convert the two-dimensional index -@code{(2,3)} of a 3-by-3 matrix to a linear index. The matrix is linearly -indexed moving from one column to next, filling up all rows in each column. +Assume the following 3-by-3 matrices. The left matrix contains the +subscript tuples for each matrix element. Those are converted to +linear indices shown in the right matrix. The matrices are linearly +indexed moving from one column to next, filling up all rows in each +column. @example @group -linear_index = sub2ind ([3, 3], 2, 3) -@result{} 8 +[(1,1), (1,2), (1,3)] [1, 4, 7] +[(2,1), (2,2), (2,3)] ==> [2, 5, 8] +[(3,1), (3,2), (3,3)] [3, 6, 9] +@end group +@end example + +The following example shows how to convert the two-dimensional indices +@code{(2,1)} and @code{(2,3)} of a 3-by-3 matrix to a linear index. + +@example +@group +s1 = [2, 2]; +s2 = [1, 3]; +ind = sub2ind ([3, 3], s1, s2) +@result{} ind = 2 8 @end group @end example @seealso{ind2sub} @@ -82,10 +97,9 @@ if (nargin < 2) print_usage (); - dim_vector dv = get_dim_vector (args(0), "sub2ind"); + dim_vector dv = get_dim_vector (args(0), "sub2ind").redim (nargin - 1); Array idxa (dim_vector (nargin-1, 1)); - dv = dv.redim (nargin - 1); for (int j = 0; j < nargin - 1; j++) { if (! args(j+1).is_numeric_type ()) @@ -158,17 +172,51 @@ DEFUN (ind2sub, args, nargout, doc: /* -*- texinfo -*- @deftypefn {} {[@var{s1}, @var{s2}, @dots{}, @var{sN}] =} ind2sub (@var{dims}, @var{ind}) -Convert a linear index to subscripts. +Convert linear indices to subscripts. + +Assume the following 3-by-3 matrices. The left matrix contains +the linear indices @var{ind} for each matrix element. Those are +converted to subscript tuples shown in the right matrix. The +matrices are linearly indexed moving from one column to next, +filling up all rows in each column. -The following example shows how to convert the linear index @code{8} -in a 3-by-3 matrix into a subscript. The matrix is linearly indexed -moving from one column to next, filling up all rows in each column. +@example +@group +[1, 4, 7] [(1,1), (1,2), (1,3)] +[2, 5, 8] ==> [(2,1), (2,2), (2,3)] +[3, 6, 9] [(3,1), (3,2), (3,3)] +@end group +@end example + +The following example shows how to convert the linear indices +@code{2} and @code{8} in a 3-by-3 matrix into a subscripts. @example @group -[r, c] = ind2sub ([3, 3], 8) - @result{} r = 2 - @result{} c = 3 +ind = [2, 8]; +[r, c] = ind2sub ([3, 3], ind) + @result{} r = 2 2 + @result{} c = 1 3 +@end group +@end example + +If the number of subscripts exceeds the number of dimensions, the +exceeded dimensions are treated as @code{1}. On the other hand, +if less subscripts than dimensions are provided, the exceeding +dimensions are merged. For clarity see the following examples: + +@example +@group +ind = [2, 8]; +dims = [3, 3]; +% same as dims = [3, 3, 1] +[r, c, s] = ind2sub (dims, ind) + @result{} r = 2 2 + @result{} c = 1 3 + @result{} s = 1 1 +% same as dims = 9 +r = ind2sub (dims, ind) + @result{} r = 2 8 @end group @end example @seealso{sub2ind} @@ -179,23 +227,58 @@ octave_value_list retval; - dim_vector dv = get_dim_vector (args(0), "ind2sub"); + // Redimension to provided number of subscripts. + dim_vector dv = get_dim_vector (args(0), "ind2sub").redim (nargout); try { - idx_vector idx = args(1).index_vector (); - - if (nargout > dv.ndims ()) - dv = dv.redim (nargout); - - retval = Array (ind2sub (dv, idx)); + retval = Array (ind2sub (dv, args(1).index_vector ())); } catch (const index_exception& e) { - std::string idx = e.idx (); - std::string msg = e.details (); - error ("ind2sub: Invalid index %s. %s", idx.c_str (), msg.c_str ()); + error ("ind2sub: Invalid index %s. %s", e.idx ().c_str (), + e.details ().c_str ()); } return retval; } + +/* +## Examples +%!test +%! [r, c] = ind2sub ([3, 3], [2, 8]); +%! assert (r, [2, 2]); +%! assert (c, [1, 3]); + +%!test +%! [r, c, s] = ind2sub ([3, 3], [2, 8]); +%! assert (r, [2, 2]); +%! assert (c, [1, 3]); +%! assert (s, [1, 1]); +%! [r, c, s] = ind2sub ([3, 3, 1], [2, 8]); +%! assert (r, [2, 2]); +%! assert (c, [1, 3]); +%! assert (s, [1, 1]); + +%!test +%! r = ind2sub ([3, 3], [2, 8]); +%! assert (r, [2, 8]); +%! r = ind2sub (9, [2, 8]); +%! assert (r, [2, 8]); + +## 3-dimensional test +%!test +%! [r, c, s] = ind2sub ([2, 2, 2], 1:8); +%! assert (r, [1, 2, 1, 2, 1, 2, 1, 2]); +%! assert (c, [1, 1, 2, 2, 1, 1, 2, 2]); +%! assert (s, [1, 1, 1, 1, 2, 2, 2, 2]); +%! [r, c] = ind2sub ([2, 2, 2], 1:8); +%! assert (r, [1, 2, 1, 2, 1, 2, 1, 2]); +%! assert (c, [1, 1, 2, 2, 3, 3, 4, 4]); +%! r = ind2sub ([2, 2, 2], 1:8); +%! assert (r, 1:8); + +%!error ind2sub ([2, -2], 3); +%!error ind2sub ([2, 2, 2], 1:9); +%!error ind2sub ([2, 2, 2], -1:8); +*/