GNU Octave  4.0.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-2015 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 "Array-util.h"
28 #include "oct-locbuf.h"
29 #include "quit.h"
30 
31 #include "defun.h"
32 #include "error.h"
33 #include "gripes.h"
34 #include "oct-obj.h"
35 
36 
37 static dim_vector
38 get_dim_vector (const octave_value& val, const char *name)
39 {
40  RowVector dimsv = val.row_vector_value (false, true);
41  dim_vector dv;
42  octave_idx_type n = dimsv.length ();
43 
44  if (n < 1)
45  error ("%s: dimension vector DIMS must not be empty", name);
46  else
47  {
48  dv.resize (std::max (n, static_cast<octave_idx_type> (2)));
49  dv(1) = 1;
50  for (octave_idx_type i = 0; i < n; i++)
51  {
52  octave_idx_type ii = dimsv(i);
53  if (ii == dimsv(i) && ii >= 0)
54  dv(i) = ii;
55  else
56  {
57  error ("%s: dimension vector DIMS must contain integers", name);
58  break;
59  }
60  }
61  }
62 
63  return dv;
64 }
65 
66 DEFUN (sub2ind, args, ,
67  "-*- texinfo -*-\n\
68 @deftypefn {Function File} {@var{ind} =} sub2ind (@var{dims}, @var{i}, @var{j})\n\
69 @deftypefnx {Function File} {@var{ind} =} sub2ind (@var{dims}, @var{s1}, @var{s2}, @dots{}, @var{sN})\n\
70 Convert subscripts to a linear index.\n\
71 \n\
72 The following example shows how to convert the two-dimensional index\n\
73 @code{(2,3)} of a 3-by-3 matrix to a linear index. The matrix is linearly\n\
74 indexed moving from one column to next, filling up all rows in each column.\n\
75 \n\
76 @example\n\
77 @group\n\
78 linear_index = sub2ind ([3, 3], 2, 3)\n\
79 @result{} 8\n\
80 @end group\n\
81 @end example\n\
82 @seealso{ind2sub}\n\
83 @end deftypefn")
84 {
85  int nargin = args.length ();
86  octave_value retval;
87 
88  if (nargin < 2)
89  print_usage ();
90  else
91  {
92  dim_vector dv = get_dim_vector (args(0), "sub2ind");
93  Array<idx_vector> idxa (dim_vector (nargin-1, 1));
94 
95  if (! error_state)
96  {
97  dv = dv.redim (nargin - 1);
98  for (int j = 0; j < nargin - 1; j++)
99  {
100  if (args(j+1).is_numeric_type ())
101  {
102  idxa(j) = args(j+1).index_vector ();
103  if (error_state)
104  break;
105  else if (j > 0 && args(j+1).dims () != args(1).dims ())
106  error ("sub2ind: all subscripts must be of the same size");
107  }
108  else
109  error ("sub2ind: subscripts must be numeric");
110 
111  if (error_state)
112  break;
113  }
114  }
115 
116  if (! error_state)
117  {
118  idx_vector idx = sub2ind (dv, idxa);
119  retval = idx;
120  }
121  }
122 
123  return retval;
124 }
125 
126 /*
127 ## Test evaluation
128 %!test
129 %! s1 = [ 1 1 1 1 ; 2 2 2 2 ];
130 %! s2 = [ 1 1 2 2 ; 1 1 2 2 ];
131 %! s3 = [ 1 2 1 2 ; 1 2 1 2 ];
132 %! in = [ 1 101 11 111 ; 2 102 12 112 ];
133 %! assert (sub2ind ([10 10 10], s1, s2, s3), in);
134 
135 # Test low index
136 %!assert (sub2ind ([10 10 10], 1, 1, 1), 1)
137 %!error <subscript indices> sub2ind ([10 10 10], 0, 1, 1)
138 %!error <subscript indices> sub2ind ([10 10 10], 1, 0, 1)
139 %!error <subscript indices> sub2ind ([10 10 10], 1, 1, 0)
140 
141 # Test high index
142 %!assert (sub2ind ([10 10 10], 10, 10, 10), 1000)
143 %!error <index out of range> sub2ind ([10 10 10], 11, 10, 10)
144 %!error <index out of range> sub2ind ([10 10 10], 10, 11, 10)
145 %!error <index out of range> sub2ind ([10 10 10], 10, 10, 11)
146 
147 # Test high index in the trailing dimensions
148 %!assert (sub2ind ([10, 1], 2, 1, 1), 2)
149 %!error <index out of range> sub2ind ([10, 1], 1, 2, 1)
150 %!error <index out of range> sub2ind ([10, 1], 1, 1, 2)
151 %!assert (sub2ind ([10 10], 2, 2, 1), 12)
152 %!error <index out of range> sub2ind ([10 10], 2, 1, 2)
153 %!error <index out of range> sub2ind ([10 10], 1, 2, 2)
154 
155 # Test handling of empty arguments
156 %!assert (sub2ind ([10 10], zeros (0,0), zeros (0,0)), zeros (0,0))
157 %!assert (sub2ind ([10 10], zeros (2,0), zeros (2,0)), zeros (2,0))
158 %!assert (sub2ind ([10 10], zeros (0,2), zeros (0,2)), zeros (0,2))
159 %!error <all subscripts .* same size> sub2ind ([10 10 10], zeros (0,2), zeros (2,0))
160 
161 # Test handling of arguments of different size
162 %!error <all subscripts .* same size> sub2ind ([10 10], ones (1,2), ones (1,3))
163 %!error <all subscripts .* same size> sub2ind ([10 10], ones (1,2), ones (2,1))
164 
165 ## Test input validation
166 %!error <dimension vector> sub2ind ([10 10.5], 1, 1)
167 %!error <subscript indices> sub2ind ([10 10], 1.5, 1)
168 %!error <subscript indices> sub2ind ([10 10], 1, 1.5)
169 */
170 
171 DEFUN (ind2sub, args, nargout,
172  "-*- texinfo -*-\n\
173 @deftypefn {Function File} {[@var{s1}, @var{s2}, @dots{}, @var{sN}] =} ind2sub (@var{dims}, @var{ind})\n\
174 Convert a linear index to subscripts.\n\
175 \n\
176 The following example shows how to convert the linear index @code{8}\n\
177 in a 3-by-3 matrix into a subscript. The matrix is linearly indexed\n\
178 moving from one column to next, filling up all rows in each column.\n\
179 \n\
180 @example\n\
181 @group\n\
182 [r, c] = ind2sub ([3, 3], 8)\n\
183  @result{} r = 2\n\
184  @result{} c = 3\n\
185 @end group\n\
186 @end example\n\
187 @seealso{sub2ind}\n\
188 @end deftypefn")
189 {
190  int nargin = args.length ();
191  octave_value_list retval;
192 
193  if (nargin != 2)
194  print_usage ();
195  else
196  {
197  dim_vector dv = get_dim_vector (args(0), "ind2sub");
198  idx_vector idx = args(1).index_vector ();
199  if (! error_state)
200  {
201  if (nargout > dv.length ())
202  dv = dv.redim (nargout);
203 
204  Array<idx_vector> idxa = ind2sub (dv, idx);
205  retval = Array<octave_value> (idxa);
206  }
207  }
208 
209  return retval;
210 }
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
void resize(int n, int fill_value=0)
Definition: dim-vector.h:287
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
void error(const char *fmt,...)
Definition: error.cc:476
static dim_vector get_dim_vector(const octave_value &val, const char *name)
Definition: sub2ind.cc:38
idx_vector sub2ind(const dim_vector &dv, const Array< idx_vector > &idxa)
Definition: Array-util.cc:530
int error_state
Definition: error.cc:101
dim_vector redim(int n) const
Definition: dim-vector.cc:266
Handles the reference counting for all the derived classes.
Definition: Array.h:45
Array< idx_vector > ind2sub(const dim_vector &dv, const idx_vector &idx)
Definition: Array-util.cc:603
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
RowVector row_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
Definition: ov.cc:1674
int length(void) const
Definition: dim-vector.h:281