Bug Summary

File:libinterp/corefcn/find.cc
Location:line 241, column 7
Description:Value stored to 'n_to_find' is never read

Annotated Source Code

1/*
2
3Copyright (C) 1996-2013 John W. Eaton
4
5This file is part of Octave.
6
7Octave is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12Octave is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with Octave; see the file COPYING. If not, see
19<http://www.gnu.org/licenses/>.
20
21*/
22
23#ifdef HAVE_CONFIG_H1
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// Find at most N_TO_FIND nonzero elements in NDA. Search forward if
35// DIRECTION is 1, backward if it is -1. NARGOUT is the number of
36// output arguments. If N_TO_FIND is -1, find all nonzero elements.
37
38template <typename T>
39octave_value_list
40find_nonzero_elem_idx (const Array<T>& nda, int nargout,
41 octave_idx_type n_to_find, int direction)
42{
43 octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ());
44
45 Array<octave_idx_type> idx;
46 if (n_to_find >= 0)
47 idx = nda.find (n_to_find, direction == -1);
48 else
49 idx = nda.find ();
50
51 // The maximum element is always at the end.
52 octave_idx_type iext = idx.is_empty () ? 0 : idx.xelem (idx.numel () - 1) + 1;
53
54 switch (nargout)
55 {
56 default:
57 case 3:
58 retval(2) = Array<T> (nda.index (idx_vector (idx)));
59 // Fall through!
60
61 case 2:
62 {
63 Array<octave_idx_type> jdx (idx.dims ());
64 octave_idx_type n = idx.length (), nr = nda.rows ();
65 for (octave_idx_type i = 0; i < n; i++)
66 {
67 jdx.xelem (i) = idx.xelem (i) / nr;
68 idx.xelem (i) %= nr;
69 }
70 iext = -1;
71 retval(1) = idx_vector (jdx, -1);
72 }
73 // Fall through!
74
75 case 1:
76 case 0:
77 retval(0) = idx_vector (idx, iext);
78 break;
79 }
80
81 return retval;
82}
83
84template <typename T>
85octave_value_list
86find_nonzero_elem_idx (const Sparse<T>& v, int nargout,
87 octave_idx_type n_to_find, int direction)
88{
89 octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ());
90
91
92 octave_idx_type nc = v.cols ();
93 octave_idx_type nr = v.rows ();
94 octave_idx_type nz = v.nnz ();
95
96 // Search in the default range.
97 octave_idx_type start_nc = -1;
98 octave_idx_type end_nc = -1;
99 octave_idx_type count;
100
101 // Search for the range to search
102 if (n_to_find < 0)
103 {
104 start_nc = 0;
105 end_nc = nc;
106 n_to_find = nz;
107 count = nz;
108 }
109 else if (direction > 0)
110 {
111 for (octave_idx_type j = 0; j < nc; j++)
112 {
113 OCTAVE_QUIToctave_quit ();
114 if (v.cidx (j) == 0 && v.cidx (j+1) != 0)
115 start_nc = j;
116 if (v.cidx (j+1) >= n_to_find)
117 {
118 end_nc = j + 1;
119 break;
120 }
121 }
122 }
123 else
124 {
125 for (octave_idx_type j = nc; j > 0; j--)
126 {
127 OCTAVE_QUIToctave_quit ();
128 if (v.cidx (j) == nz && v.cidx (j-1) != nz)
129 end_nc = j;
130 if (nz - v.cidx (j-1) >= n_to_find)
131 {
132 start_nc = j - 1;
133 break;
134 }
135 }
136 }
137
138 count = (n_to_find > v.cidx (end_nc) - v.cidx (start_nc) ?
139 v.cidx (end_nc) - v.cidx (start_nc) : n_to_find);
140
141 // If the original argument was a row vector, force a row vector of
142 // the overall indices to be returned. But see below for scalar
143 // case...
144
145 octave_idx_type result_nr = count;
146 octave_idx_type result_nc = 1;
147
148 bool scalar_arg = false;
149
150 if (v.rows () == 1)
151 {
152 result_nr = 1;
153 result_nc = count;
154
155 scalar_arg = (v.columns () == 1);
156 }
157
158 Matrix idx (result_nr, result_nc);
159
160 Matrix i_idx (result_nr, result_nc);
161 Matrix j_idx (result_nr, result_nc);
162
163 Array<T> val (dim_vector (result_nr, result_nc));
164
165 if (count > 0)
166 {
167 // Search for elements to return. Only search the region where
168 // there are elements to be found using the count that we want
169 // to find.
170 for (octave_idx_type j = start_nc, cx = 0; j < end_nc; j++)
171 for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++ )
172 {
173 OCTAVE_QUIToctave_quit ();
174 if (direction < 0 && i < nz - count)
175 continue;
176 i_idx(cx) = static_cast<double> (v.ridx (i) + 1);
177 j_idx(cx) = static_cast<double> (j + 1);
178 idx(cx) = j * nr + v.ridx (i) + 1;
179 val(cx) = v.data(i);
180 cx++;
181 if (cx == count)
182 break;
183 }
184 }
185 else if (scalar_arg)
186 {
187 idx.resize (0, 0);
188
189 i_idx.resize (0, 0);
190 j_idx.resize (0, 0);
191
192 val.resize (dim_vector (0, 0));
193 }
194
195 switch (nargout)
196 {
197 case 0:
198 case 1:
199 retval(0) = idx;
200 break;
201
202 case 5:
203 retval(4) = nc;
204 // Fall through
205
206 case 4:
207 retval(3) = nr;
208 // Fall through
209
210 case 3:
211 retval(2) = val;
212 // Fall through!
213
214 case 2:
215 retval(1) = j_idx;
216 retval(0) = i_idx;
217 break;
218
219 default:
220 panic_impossible ()panic ("impossible state reached in file '%s' at line %d", "corefcn/find.cc"
, 220)
;
221 break;
222 }
223
224 return retval;
225}
226
227octave_value_list
228find_nonzero_elem_idx (const PermMatrix& v, int nargout,
229 octave_idx_type n_to_find, int direction)
230{
231 // There are far fewer special cases to handle for a PermMatrix.
232 octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ());
233
234 octave_idx_type nc = v.cols ();
235 octave_idx_type start_nc, count;
236
237 // Determine the range to search.
238 if (n_to_find < 0 || n_to_find >= nc)
239 {
240 start_nc = 0;
241 n_to_find = nc;
Value stored to 'n_to_find' is never read
242 count = nc;
243 }
244 else if (direction > 0)
245 {
246 start_nc = 0;
247 count = n_to_find;
248 }
249 else
250 {
251 start_nc = nc - n_to_find;
252 count = n_to_find;
253 }
254
255 bool scalar_arg = (v.rows () == 1 && v.cols () == 1);
256
257 Matrix idx (count, 1);
258 Matrix i_idx (count, 1);
259 Matrix j_idx (count, 1);
260 // Every value is 1.
261 Array<double> val (dim_vector (count, 1), 1.0);
262
263 if (count > 0)
264 {
265 const octave_idx_type* p = v.data ();
266 if (v.is_col_perm ())
267 {
268 for (octave_idx_type k = 0; k < count; k++)
269 {
270 OCTAVE_QUIToctave_quit ();
271 const octave_idx_type j = start_nc + k;
272 const octave_idx_type i = p[j];
273 i_idx(k) = static_cast<double> (1+i);
274 j_idx(k) = static_cast<double> (1+j);
275 idx(k) = j * nc + i + 1;
276 }
277 }
278 else
279 {
280 for (octave_idx_type k = 0; k < count; k++)
281 {
282 OCTAVE_QUIToctave_quit ();
283 const octave_idx_type i = start_nc + k;
284 const octave_idx_type j = p[i];
285 // Scatter into the index arrays according to
286 // j adjusted by the start point.
287 const octave_idx_type koff = j - start_nc;
288 i_idx(koff) = static_cast<double> (1+i);
289 j_idx(koff) = static_cast<double> (1+j);
290 idx(koff) = j * nc + i + 1;
291 }
292 }
293 }
294 else if (scalar_arg)
295 {
296 // Same odd compatibility case as the other overrides.
297 idx.resize (0, 0);
298 i_idx.resize (0, 0);
299 j_idx.resize (0, 0);
300 val.resize (dim_vector (0, 0));
301 }
302
303 switch (nargout)
304 {
305 case 0:
306 case 1:
307 retval(0) = idx;
308 break;
309
310 case 5:
311 retval(4) = nc;
312 // Fall through
313
314 case 4:
315 retval(3) = nc;
316 // Fall through
317
318 case 3:
319 retval(2) = val;
320 // Fall through!
321
322 case 2:
323 retval(1) = j_idx;
324 retval(0) = i_idx;
325 break;
326
327 default:
328 panic_impossible ()panic ("impossible state reached in file '%s' at line %d", "corefcn/find.cc"
, 328)
;
329 break;
330 }
331
332 return retval;
333}
334
335DEFUN (find, args, nargout,octave_value_list Ffind (const octave_value_list& args, int
nargout)
336 "-*- texinfo -*-\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
337@deftypefn {Built-in Function} {@var{idx} =} find (@var{x})\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
338@deftypefnx {Built-in Function} {@var{idx} =} find (@var{x}, @var{n})\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
339@deftypefnx {Built-in Function} {@var{idx} =} find (@var{x}, @var{n}, @var{direction})\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
340@deftypefnx {Built-in Function} {[i, j] =} find (@dots{})\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
341@deftypefnx {Built-in Function} {[i, j, v] =} find (@dots{})\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
342Return a vector of indices of nonzero elements of a matrix, as a row if\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
343@var{x} is a row vector or as a column otherwise. To obtain a single index\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
344for each matrix element, Octave pretends that the columns of a matrix form\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
345one long vector (like Fortran arrays are stored). For example:\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
346\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
347@example\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
348@group\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
349find (eye (2))\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
350 @result{} [ 1; 4 ]\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
351@end group\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
352@end example\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
353\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
354If two outputs are requested, @code{find} returns the row and column\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
355indices of nonzero elements of a matrix. For example:\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
356\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
357@example\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
358@group\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
359[i, j] = find (2 * eye (2))\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
360 @result{} i = [ 1; 2 ]\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
361 @result{} j = [ 1; 2 ]\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
362@end group\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
363@end example\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
364\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
365If three outputs are requested, @code{find} also returns a vector\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
366containing the nonzero values. For example:\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
367\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
368@example\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
369@group\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
370[i, j, v] = find (3 * eye (2))\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
371 @result{} i = [ 1; 2 ]\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
372 @result{} j = [ 1; 2 ]\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
373 @result{} v = [ 3; 3 ]\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
374@end group\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
375@end example\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
376\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
377If two inputs are given, @var{n} indicates the maximum number of\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
378elements to find from the beginning of the matrix or vector.\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
379\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
380If three inputs are given, @var{direction} should be one of\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
381@qcode{\"first\"} or @qcode{\"last\"}, requesting only the first or last\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
382@var{n} indices, respectively. However, the indices are always returned in\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
383ascending order.\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
384\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
385Note that this function is particularly useful for sparse matrices, as\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
386it extracts the non-zero elements as vectors, which can then be used to\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
387create the original matrix. For example:\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
388\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
389@example\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
390@group\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
391sz = size (a);\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
392[i, j, v] = find (a);\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
393b = sparse (i, j, v, sz(1), sz(2));\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
394@end group\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
395@end example\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
396@seealso{nonzeros}\n\octave_value_list Ffind (const octave_value_list& args, int
nargout)
397@end deftypefn")octave_value_list Ffind (const octave_value_list& args, int
nargout)
398{
399 octave_value_list retval;
400
401 int nargin = args.length ();
402
403 if (nargin > 3 || nargin < 1)
404 {
405 print_usage ();
406 return retval;
407 }
408
409 // Setup the default options.
410 octave_idx_type n_to_find = -1;
411 if (nargin > 1)
412 {
413 double val = args(1).scalar_value ();
414
415 if (error_state || (val < 0 || (! xisinf (val) && val != xround (val))))
416 {
417 error ("find: N must be a non-negative integer");
418 return retval;
419 }
420 else if (! xisinf (val))
421 n_to_find = val;
422 }
423
424 // Direction to do the searching (1 == forward, -1 == reverse).
425 int direction = 1;
426 if (nargin > 2)
427 {
428 direction = 0;
429
430 std::string s_arg = args(2).string_value ();
431
432 if (! error_state)
433 {
434 if (s_arg == "first")
435 direction = 1;
436 else if (s_arg == "last")
437 direction = -1;
438 }
439
440 if (direction == 0)
441 {
442 error ("find: DIRECTION must be \"first\" or \"last\"");
443 return retval;
444 }
445 }
446
447 octave_value arg = args(0);
448
449 if (arg.is_bool_type ())
450 {
451 if (arg.is_sparse_type ())
452 {
453 SparseBoolMatrix v = arg.sparse_bool_matrix_value ();
454
455 if (! error_state)
456 retval = find_nonzero_elem_idx (v, nargout,
457 n_to_find, direction);
458 }
459 else if (nargout <= 1 && n_to_find == -1 && direction == 1)
460 {
461 // This case is equivalent to extracting indices from a logical
462 // matrix. Try to reuse the possibly cached index vector.
463 retval(0) = arg.index_vector ().unmask ();
464 }
465 else
466 {
467 boolNDArray v = arg.bool_array_value ();
468
469 if (! error_state)
470 retval = find_nonzero_elem_idx (v, nargout,
471 n_to_find, direction);
472 }
473 }
474 else if (arg.is_integer_type ())
475 {
476#define DO_INT_BRANCH(INTT)else if (arg.is_INTT_type ()) { INTTNDArray v = arg.INTT_array_value
(); if (! error_state) retval = find_nonzero_elem_idx (v, nargout
, n_to_find, direction); }
\
477 else if (arg.is_ ## INTT ## _type ()) \
478 { \
479 INTT ## NDArray v = arg.INTT ## _array_value (); \
480 \
481 if (! error_state) \
482 retval = find_nonzero_elem_idx (v, nargout, \
483 n_to_find, direction);\
484 }
485
486 if (false)
487 ;
488 DO_INT_BRANCH (int8)else if (arg.is_int8_type ()) { int8NDArray v = arg.int8_array_value
(); if (! error_state) retval = find_nonzero_elem_idx (v, nargout
, n_to_find, direction); }
489 DO_INT_BRANCH (int16)else if (arg.is_int16_type ()) { int16NDArray v = arg.int16_array_value
(); if (! error_state) retval = find_nonzero_elem_idx (v, nargout
, n_to_find, direction); }
490 DO_INT_BRANCH (int32)else if (arg.is_int32_type ()) { int32NDArray v = arg.int32_array_value
(); if (! error_state) retval = find_nonzero_elem_idx (v, nargout
, n_to_find, direction); }
491 DO_INT_BRANCH (int64)else if (arg.is_int64_type ()) { int64NDArray v = arg.int64_array_value
(); if (! error_state) retval = find_nonzero_elem_idx (v, nargout
, n_to_find, direction); }
492 DO_INT_BRANCH (uint8)else if (arg.is_uint8_type ()) { uint8NDArray v = arg.uint8_array_value
(); if (! error_state) retval = find_nonzero_elem_idx (v, nargout
, n_to_find, direction); }
493 DO_INT_BRANCH (uint16)else if (arg.is_uint16_type ()) { uint16NDArray v = arg.uint16_array_value
(); if (! error_state) retval = find_nonzero_elem_idx (v, nargout
, n_to_find, direction); }
494 DO_INT_BRANCH (uint32)else if (arg.is_uint32_type ()) { uint32NDArray v = arg.uint32_array_value
(); if (! error_state) retval = find_nonzero_elem_idx (v, nargout
, n_to_find, direction); }
495 DO_INT_BRANCH (uint64)else if (arg.is_uint64_type ()) { uint64NDArray v = arg.uint64_array_value
(); if (! error_state) retval = find_nonzero_elem_idx (v, nargout
, n_to_find, direction); }
496 else
497 panic_impossible ()panic ("impossible state reached in file '%s' at line %d", "corefcn/find.cc"
, 497)
;
498 }
499 else if (arg.is_sparse_type ())
500 {
501 if (arg.is_real_type ())
502 {
503 SparseMatrix v = arg.sparse_matrix_value ();
504
505 if (! error_state)
506 retval = find_nonzero_elem_idx (v, nargout,
507 n_to_find, direction);
508 }
509 else if (arg.is_complex_type ())
510 {
511 SparseComplexMatrix v = arg.sparse_complex_matrix_value ();
512
513 if (! error_state)
514 retval = find_nonzero_elem_idx (v, nargout,
515 n_to_find, direction);
516 }
517 else
518 gripe_wrong_type_arg ("find", arg);
519 }
520 else if (arg.is_perm_matrix ())
521 {
522 PermMatrix P = arg.perm_matrix_value ();
523
524 if (! error_state)
525 retval = find_nonzero_elem_idx (P, nargout, n_to_find, direction);
526 }
527 else if (arg.is_string ())
528 {
529 charNDArray chnda = arg.char_array_value ();
530
531 if (! error_state)
532 retval = find_nonzero_elem_idx (chnda, nargout, n_to_find, direction);
533 }
534 else if (arg.is_single_type ())
535 {
536 if (arg.is_real_type ())
537 {
538 FloatNDArray nda = arg.float_array_value ();
539
540 if (! error_state)
541 retval = find_nonzero_elem_idx (nda, nargout, n_to_find,
542 direction);
543 }
544 else if (arg.is_complex_type ())
545 {
546 FloatComplexNDArray cnda = arg.float_complex_array_value ();
547
548 if (! error_state)
549 retval = find_nonzero_elem_idx (cnda, nargout, n_to_find,
550 direction);
551 }
552 }
553 else if (arg.is_real_type ())
554 {
555 NDArray nda = arg.array_value ();
556
557 if (! error_state)
558 retval = find_nonzero_elem_idx (nda, nargout, n_to_find, direction);
559 }
560 else if (arg.is_complex_type ())
561 {
562 ComplexNDArray cnda = arg.complex_array_value ();
563
564 if (! error_state)
565 retval = find_nonzero_elem_idx (cnda, nargout, n_to_find, direction);
566 }
567 else
568 gripe_wrong_type_arg ("find", arg);
569
570 return retval;
571}
572
573/*
574%!assert (find (char ([0, 97])), 2)
575%!assert (find ([1, 0, 1, 0, 1]), [1, 3, 5])
576%!assert (find ([1; 0; 3; 0; 1]), [1; 3; 5])
577%!assert (find ([0, 0, 2; 0, 3, 0; -1, 0, 0]), [3; 5; 7])
578
579%!test
580%! [i, j, v] = find ([0, 0, 2; 0, 3, 0; -1, 0, 0]);
581%!
582%! assert (i, [3; 2; 1]);
583%! assert (j, [1; 2; 3]);
584%! assert (v, [-1; 3; 2]);
585
586%!assert (find (single ([1, 0, 1, 0, 1])), [1, 3, 5])
587%!assert (find (single ([1; 0; 3; 0; 1])), [1; 3; 5])
588%!assert (find (single ([0, 0, 2; 0, 3, 0; -1, 0, 0])), [3; 5; 7])
589
590%!test
591%! [i, j, v] = find (single ([0, 0, 2; 0, 3, 0; -1, 0, 0]));
592%!
593%! assert (i, [3; 2; 1]);
594%! assert (j, [1; 2; 3]);
595%! assert (v, single ([-1; 3; 2]));
596
597%!test
598%! pcol = [5 1 4 3 2];
599%! P = eye (5) (:, pcol);
600%! [i, j, v] = find (P);
601%! [ifull, jfull, vfull] = find (full (P));
602%! assert (i, ifull);
603%! assert (j, jfull);
604%! assert (all (v == 1));
605
606%!test
607%! prow = [5 1 4 3 2];
608%! P = eye (5) (prow, :);
609%! [i, j, v] = find (P);
610%! [ifull, jfull, vfull] = find (full (P));
611%! assert (i, ifull);
612%! assert (j, jfull);
613%! assert (all (v == 1));
614
615%!assert (find ([2 0 1 0 5 0], 1), 1)
616%!assert (find ([2 0 1 0 5 0], 2, "last"), [3, 5])
617
618%!assert (find ([2 0 1 0 5 0], Inf), [1, 3, 5])
619%!assert (find ([2 0 1 0 5 0], Inf, "last"), [1, 3, 5])
620
621%!error find ()
622*/