GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
sub2ind.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2009-2013 VZLU Prague
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include "quit.h"
28 
29 #include "defun.h"
30 #include "error.h"
31 #include "gripes.h"
32 #include "oct-obj.h"
33 
34 
35 static dim_vector
36 get_dim_vector (const octave_value& val, const char *name)
37 {
38  RowVector dimsv = val.row_vector_value (false, true);
39  dim_vector dv;
40  octave_idx_type n = dimsv.length ();
41 
42  if (n < 1)
43  error ("%s: dimension vector DIMS must not be empty", name);
44  else
45  {
46  dv.resize (std::max (n, static_cast<octave_idx_type> (2)));
47  dv(1) = 1;
48  for (octave_idx_type i = 0; i < n; i++)
49  {
50  octave_idx_type ii = dimsv(i);
51  if (ii == dimsv(i) && ii >= 0)
52  dv(i) = ii;
53  else
54  {
55  error ("%s: dimension vector DIMS must contain integers", name);
56  break;
57  }
58  }
59  }
60 
61  return dv;
62 }
63 
64 DEFUN (sub2ind, args, ,
65  "-*- texinfo -*-\n\
66 @deftypefn {Function File} {@var{ind} =} sub2ind (@var{dims}, @var{i}, @var{j})\n\
67 @deftypefnx {Function File} {@var{ind} =} sub2ind (@var{dims}, @var{s1}, @var{s2}, @dots{}, @var{sN})\n\
68 Convert subscripts to a linear index.\n\
69 \n\
70 The following example shows how to convert the two-dimensional\n\
71 index @code{(2,3)} of a 3-by-3 matrix to a linear index. The matrix\n\
72 is linearly indexed moving from one column to next, filling up\n\
73 all rows in each column.\n\
74 \n\
75 @example\n\
76 @group\n\
77 linear_index = sub2ind ([3, 3], 2, 3)\n\
78 @result{} 8\n\
79 @end group\n\
80 @end example\n\
81 @seealso{ind2sub}\n\
82 @end deftypefn")
83 {
84  int nargin = args.length ();
85  octave_value retval;
86 
87  if (nargin < 2)
88  print_usage ();
89  else
90  {
91  dim_vector dv = get_dim_vector (args(0), "sub2ind");
92  Array<idx_vector> idxa (dim_vector (nargin-1, 1));
93 
94  if (! error_state)
95  {
96  dv = dv.redim (nargin - 1);
97  for (int j = 0; j < nargin - 1; j++)
98  {
99  if (args(j+1).is_numeric_type ())
100  {
101  idxa(j) = args(j+1).index_vector ();
102  if (error_state)
103  break;
104  else if (j > 0 && args(j+1).dims () != args(1).dims ())
105  error ("sub2ind: all subscripts must be of the same size");
106  }
107  else
108  error ("sub2ind: subscripts must be numeric");
109 
110  if (error_state)
111  break;
112  }
113  }
114 
115  if (! error_state)
116  {
117  idx_vector idx = sub2ind (dv, idxa);
118  retval = idx;
119  }
120  }
121 
122  return retval;
123 }
124 
125 /*
126 ## Test evaluation
127 %!test
128 %! s1 = [ 1 1 1 1 ; 2 2 2 2 ];
129 %! s2 = [ 1 1 2 2 ; 1 1 2 2 ];
130 %! s3 = [ 1 2 1 2 ; 1 2 1 2 ];
131 %! in = [ 1 101 11 111 ; 2 102 12 112 ];
132 %! assert (sub2ind ([10 10 10], s1, s2, s3), in);
133 
134 # Test low index
135 %!assert (sub2ind ([10 10 10], 1, 1, 1), 1)
136 %!error <subscript indices> sub2ind ([10 10 10], 0, 1, 1)
137 %!error <subscript indices> sub2ind ([10 10 10], 1, 0, 1)
138 %!error <subscript indices> sub2ind ([10 10 10], 1, 1, 0)
139 
140 # Test high index
141 %!assert (sub2ind ([10 10 10], 10, 10, 10), 1000)
142 %!error <index out of range> sub2ind ([10 10 10], 11, 10, 10)
143 %!error <index out of range> sub2ind ([10 10 10], 10, 11, 10)
144 %!error <index out of range> sub2ind ([10 10 10], 10, 10, 11)
145 
146 # Test high index in the trailing dimensions
147 %!assert (sub2ind ([10, 1], 2, 1, 1), 2)
148 %!error <index out of range> sub2ind ([10, 1], 1, 2, 1)
149 %!error <index out of range> sub2ind ([10, 1], 1, 1, 2)
150 %!assert (sub2ind ([10 10], 2, 2, 1), 12)
151 %!error <index out of range> sub2ind ([10 10], 2, 1, 2)
152 %!error <index out of range> sub2ind ([10 10], 1, 2, 2)
153 
154 # Test handling of empty arguments
155 %!assert (sub2ind ([10 10], zeros (0,0), zeros (0,0)), zeros (0,0))
156 %!assert (sub2ind ([10 10], zeros (2,0), zeros (2,0)), zeros (2,0))
157 %!assert (sub2ind ([10 10], zeros (0,2), zeros (0,2)), zeros (0,2))
158 %!error <all subscripts .* same size> sub2ind ([10 10 10], zeros (0,2), zeros (2,0))
159 
160 # Test handling of arguments of different size
161 %!error <all subscripts .* same size> sub2ind ([10 10], ones (1,2), ones (1,3))
162 %!error <all subscripts .* same size> sub2ind ([10 10], ones (1,2), ones (2,1))
163 
164 ## Test input validation
165 %!error <dimension vector> sub2ind ([10 10.5], 1, 1)
166 %!error <subscript indices> sub2ind ([10 10], 1.5, 1)
167 %!error <subscript indices> sub2ind ([10 10], 1, 1.5)
168 */
169 
170 DEFUN (ind2sub, args, nargout,
171  "-*- texinfo -*-\n\
172 @deftypefn {Function File} {[@var{s1}, @var{s2}, @dots{}, @var{sN}] =} ind2sub (@var{dims}, @var{ind})\n\
173 Convert a linear index to subscripts.\n\
174 \n\
175 The following example shows how to convert the linear index @code{8}\n\
176 in a 3-by-3 matrix into a subscript. The matrix is linearly indexed\n\
177 moving from one column to next, filling up all rows in each column.\n\
178 \n\
179 @example\n\
180 @group\n\
181 [r, c] = ind2sub ([3, 3], 8)\n\
182  @result{} r = 2\n\
183  @result{} c = 3\n\
184 @end group\n\
185 @end example\n\
186 @seealso{sub2ind}\n\
187 @end deftypefn")
188 {
189  int nargin = args.length ();
190  octave_value_list retval;
191 
192  if (nargin != 2)
193  print_usage ();
194  else
195  {
196  dim_vector dv = get_dim_vector (args(0), "ind2sub");
197  idx_vector idx = args(1).index_vector ();
198  if (! error_state)
199  {
200  if (nargout > dv.length ())
201  dv = dv.redim (nargout);
202 
203  Array<idx_vector> idxa = ind2sub (dv, idx);
204  retval = Array<octave_value> (idxa);
205  }
206  }
207 
208  return retval;
209 }