comparison src/DLD-FUNCTIONS/find.cc @ 6002:c5d0490aad55

[project @ 2006-09-26 19:45:42 by jwe]
author jwe
date Tue, 26 Sep 2006 19:45:43 +0000
parents 080c08b192d8
children b4351cfb5659
comparison
equal deleted inserted replaced
6001:d45cb743ff2e 6002:c5d0490aad55
30 #include "defun-dld.h" 30 #include "defun-dld.h"
31 #include "error.h" 31 #include "error.h"
32 #include "gripes.h" 32 #include "gripes.h"
33 #include "oct-obj.h" 33 #include "oct-obj.h"
34 34
35 inline double real (double x) { return x; } 35 // Find at most N_TO_FIND nonzero elements in NDA. Search forward if
36 // DIRECTION is 1, backward if it is -1. NARGOUT is the number of
37 // output arguments. If N_TO_FIND is -1, find all nonzero elements.
36 38
37 template <typename T> 39 template <typename T>
38 octave_value_list 40 octave_value_list
39 find_nonzero_elem_idx (const T& nda, int nargout) 41 find_nonzero_elem_idx (const T& nda, int nargout, octave_idx_type n_to_find,
42 int direction)
40 { 43 {
41 octave_value_list retval (((nargout == 0) ? 1 : nargout), Matrix ()); 44 octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ());
42 45
43 octave_idx_type count = 0; 46 octave_idx_type count = 0;
44 47
45 octave_idx_type nel = nda.nelem (); 48 octave_idx_type nel = nda.nelem ();
46 49
47 for (octave_idx_type i = 0; i < nel; i++) 50 // Set the starting element to the correct value based on the
51 // direction to search.
52 octave_idx_type k = 0;
53 if (direction == -1)
54 k = nel - 1;
55
56 // Search in the default range.
57 octave_idx_type start_el = -1;
58 octave_idx_type end_el = -1;
59
60 // Search for the number of elements to return.
61 while (k < nel && k > -1 && n_to_find != count)
48 { 62 {
49 OCTAVE_QUIT; 63 OCTAVE_QUIT;
50 64
51 if (nda(i) != 0.0) 65 if (nda(k) != 0.0)
52 count++; 66 {
53 } 67 end_el = k;
68 if (start_el == -1)
69 start_el = k;
70 count++;
71 }
72 k = k + direction;
73 }
74
75 // Reverse the range if we're looking backward.
76 if (direction == -1)
77 {
78 octave_idx_type tmp_el = start_el;
79 start_el = end_el;
80 end_el = tmp_el;
81 }
82 // Fix an off by one error.
83 end_el++;
54 84
55 // If the original argument was a row vector, force a row vector of 85 // If the original argument was a row vector, force a row vector of
56 // the overall indices to be returned. But see below for scalar 86 // the overall indices to be returned. But see below for scalar
57 // case... 87 // case...
58 88
83 octave_idx_type nr = nda.rows (); 113 octave_idx_type nr = nda.rows ();
84 114
85 octave_idx_type i = 0; 115 octave_idx_type i = 0;
86 octave_idx_type j = 0; 116 octave_idx_type j = 0;
87 117
88 for (octave_idx_type k = 0; k < nel; k++) 118 // Search for elements to return. Only search the region where
119 // there are elements to be found using the count that we want
120 // to find.
121 for (k = start_el; k < end_el; k++)
89 { 122 {
90 OCTAVE_QUIT; 123 OCTAVE_QUIT;
91 124
92 if (nda(k) != 0.0) 125 if (nda(k) != 0.0)
93 { 126 {
143 } 176 }
144 177
145 return retval; 178 return retval;
146 } 179 }
147 180
148 template octave_value_list find_nonzero_elem_idx (const NDArray&, int); 181 template octave_value_list find_nonzero_elem_idx (const NDArray&, int,
149 182 octave_idx_type, int);
150 template octave_value_list find_nonzero_elem_idx (const ComplexNDArray&, int); 183
184 template octave_value_list find_nonzero_elem_idx (const ComplexNDArray&, int,
185 octave_idx_type, int);
151 186
152 DEFUN_DLD (find, args, nargout, 187 DEFUN_DLD (find, args, nargout,
153 "-*- texinfo -*-\n\ 188 "-*- texinfo -*-\n\
154 @deftypefn {Loadable Function} {} find (@var{x})\n\ 189 @deftypefn {Loadable Function} {} find (@var{x})\n\
190 @deftypefnx {Loadable Function} {} find (@var{x}, @var{n})\n\
191 @deftypefnx {Loadable Function} {} find (@var{x}, @var{n}, @var{direction})\n\
155 Return a vector of indices of nonzero elements of a matrix. To obtain a\n\ 192 Return a vector of indices of nonzero elements of a matrix. To obtain a\n\
156 single index for each matrix element, Octave pretends that the columns\n\ 193 single index for each matrix element, Octave pretends that the columns\n\
157 of a matrix form one long vector (like Fortran arrays are stored). For\n\ 194 of a matrix form one long vector (like Fortran arrays are stored). For\n\
158 example,\n\ 195 example,\n\
159 \n\ 196 \n\
184 @result{} i = [ 1; 2 ]\n\ 221 @result{} i = [ 1; 2 ]\n\
185 @result{} j = [ 1; 2 ]\n\ 222 @result{} j = [ 1; 2 ]\n\
186 @result{} v = [ 3; 3 ]\n\ 223 @result{} v = [ 3; 3 ]\n\
187 @end group\n\ 224 @end group\n\
188 @end example\n\ 225 @end example\n\
226 \n\
227 If two inputs are given, @var{n} indicates the number of elements to\n\
228 find from the beginning of the matrix or vector.\n\
229 \n\
230 If three inputs are given, @var{direction} should be one of \"first\" or\n\
231 \"last\" indicating that it should start counting found elements from the\n\
232 first or last element.\n\
189 @end deftypefn") 233 @end deftypefn")
190 { 234 {
191 octave_value_list retval; 235 octave_value_list retval;
192 236
193 int nargin = args.length (); 237 int nargin = args.length ();
194 238
195 if (nargin != 1 || nargout > 3) 239 if (nargin > 3 || nargin < 1)
196 { 240 {
197 print_usage (); 241 print_usage ();
198 return retval; 242 return retval;
199 } 243 }
200 244
245 // Setup the default options.
246 octave_idx_type n_to_find = -1;
247 if (nargin > 1)
248 {
249 n_to_find = args(1).int_value ();
250 if (error_state)
251 {
252 error ("find: expecting second argument to be an integer");
253 return retval;
254 }
255 }
256
257 // Direction to do the searching (1 == forward, -1 == reverse).
258 int direction = 1;
259 if (nargin > 2)
260 {
261 direction = 0;
262
263 std::string s_arg = args(2).string_value ();
264
265 if (! error_state)
266 {
267 if (s_arg == "first")
268 direction = 1;
269 else if (s_arg == "last")
270 direction = -1;
271 }
272
273 if (direction == 0)
274 {
275 error ("find: expecting third argument to be \"first\" or \"last\"");
276 return retval;
277 }
278 }
279
201 octave_value arg = args(0); 280 octave_value arg = args(0);
202 281
203 if (arg.is_real_type ()) 282 if (arg.is_real_type ())
204 { 283 {
205 NDArray nda = arg.array_value (); 284 NDArray nda = arg.array_value ();
206 285
207 if (! error_state) 286 if (! error_state)
208 retval = find_nonzero_elem_idx (nda, nargout); 287 retval = find_nonzero_elem_idx (nda, nargout, n_to_find, direction);
209 } 288 }
210 else if (arg.is_complex_type ()) 289 else if (arg.is_complex_type ())
211 { 290 {
212 ComplexNDArray cnda = arg.complex_array_value (); 291 ComplexNDArray cnda = arg.complex_array_value ();
213 292
214 if (! error_state) 293 if (! error_state)
215 retval = find_nonzero_elem_idx (cnda, nargout); 294 retval = find_nonzero_elem_idx (cnda, nargout, n_to_find, direction);
216 } 295 }
217 else if (arg.is_string ()) 296 else if (arg.is_string ())
218 { 297 {
219 charNDArray cnda = arg.char_array_value (); 298 charNDArray cnda = arg.char_array_value ();
220 299
221 if (! error_state) 300 if (! error_state)
222 retval = find_nonzero_elem_idx (cnda, nargout); 301 retval = find_nonzero_elem_idx (cnda, nargout, n_to_find, direction);
223 } 302 }
224 else 303 else
225 { 304 {
226 gripe_wrong_type_arg ("find", arg); 305 gripe_wrong_type_arg ("find", arg);
227 } 306 }