Mercurial > octave-nkf
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 } |