GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
cellfun.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2005-2018 Mohamed Kamoun
4 Copyright (C) 2006-2018 Bill Denney
5 Copyright (C) 2009 Jaroslav Hajek
6 Copyright (C) 2010 VZLU Prague
7 
8 This file is part of Octave.
9 
10 Octave is free software: you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14 
15 Octave is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with Octave; see the file COPYING. If not, see
22 <https://www.gnu.org/licenses/>.
23 
24 */
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <string>
31 #include <vector>
32 #include <list>
33 #include <memory>
34 
35 #include "lo-mappers.h"
36 #include "oct-locbuf.h"
37 #include "oct-string.h"
38 
39 #include "Cell.h"
40 #include "oct-map.h"
41 #include "defun.h"
42 #include "interpreter.h"
43 #include "parse.h"
44 #include "variables.h"
45 #include "unwind-prot.h"
46 #include "errwarn.h"
47 #include "utils.h"
48 
49 #include "ov-bool.h"
50 #include "ov-class.h"
51 #include "ov-colon.h"
52 #include "ov-complex.h"
53 #include "ov-float.h"
54 #include "ov-flt-complex.h"
55 #include "ov-int16.h"
56 #include "ov-int32.h"
57 #include "ov-int64.h"
58 #include "ov-int8.h"
59 #include "ov-scalar.h"
60 #include "ov-uint16.h"
61 #include "ov-uint32.h"
62 #include "ov-uint64.h"
63 #include "ov-uint8.h"
64 
65 #include "ov-fcn-handle.h"
66 
67 static octave_value_list
69  const octave_value_list& inputlist,
70  octave_value& func,
71  octave_value& error_handler)
72 {
74 
75  bool execution_error = false;
76 
77  try
78  {
79  tmp = octave::feval (func, inputlist, nargout);
80  }
81  catch (const octave::execution_exception& e)
82  {
83  if (error_handler.is_defined ())
84  {
86 
87  execution_error = true;
88  }
89  else
90  throw e;
91  }
92 
93  if (execution_error)
94  {
95  if (error_handler.is_defined ())
96  {
98  msg.assign ("identifier", last_error_id ());
99  msg.assign ("message", last_error_message ());
100  msg.assign ("index",
101  static_cast<double> (count
102  + static_cast<octave_idx_type>(1)));
103 
104  octave_value_list errlist = inputlist;
105  errlist.prepend (msg);
106 
108 
109  tmp = octave::feval (error_handler, errlist, nargout);
110  }
111  else
112  tmp.clear ();
113  }
114 
115  return tmp;
116 }
117 
118 // Templated function because the user can be stubborn enough to request
119 // a cell array as an output even in these cases where the output fits
120 // in an ordinary array
121 template <typename BNDA, typename NDA>
122 static octave_value_list
124 {
126 
127  std::string name = args(0).string_value ();
128 
129  const Cell f_args = args(1).cell_value ();
130 
131  octave_idx_type k = f_args.numel ();
132 
133  if (name == "isempty")
134  {
135  BNDA result (f_args.dims ());
136  for (octave_idx_type count = 0; count < k; count++)
137  result(count) = f_args.elem (count).isempty ();
138  retval(0) = result;
139  }
140  else if (name == "islogical")
141  {
142  BNDA result (f_args.dims ());
143  for (octave_idx_type count= 0; count < k; count++)
144  result(count) = f_args.elem (count).islogical ();
145  retval(0) = result;
146  }
147  else if (name == "isnumeric")
148  {
149  BNDA result (f_args.dims ());
150  for (octave_idx_type count= 0; count < k; count++)
151  result(count) = f_args.elem (count).isnumeric ();
152  retval(0) = result;
153  }
154  else if (name == "isreal")
155  {
156  BNDA result (f_args.dims ());
157  for (octave_idx_type count= 0; count < k; count++)
158  result(count) = f_args.elem (count).isreal ();
159  retval(0) = result;
160  }
161  else if (name == "length")
162  {
163  NDA result (f_args.dims ());
164  for (octave_idx_type count= 0; count < k; count++)
165  result(count) = static_cast<double> (f_args.elem (count).length ());
166  retval(0) = result;
167  }
168  else if (name == "ndims")
169  {
170  NDA result (f_args.dims ());
171  for (octave_idx_type count = 0; count < k; count++)
172  result(count) = static_cast<double> (f_args.elem (count).ndims ());
173  retval(0) = result;
174  }
175  else if (name == "numel" || name == "prodofsize")
176  {
177  NDA result (f_args.dims ());
178  for (octave_idx_type count = 0; count < k; count++)
179  result(count) = static_cast<double> (f_args.elem (count).numel ());
180  retval(0) = result;
181  }
182  else if (name == "size")
183  {
184  if (nargin != 3)
185  error (R"(cellfun: not enough arguments for "size")");
186 
187  int d = args(2).nint_value () - 1;
188 
189  if (d < 0)
190  error ("cellfun: K must be a positive integer");
191 
192  NDA result (f_args.dims ());
193 
194  for (octave_idx_type count = 0; count < k; count++)
195  {
196  dim_vector dv = f_args.elem (count).dims ();
197  if (d < dv.ndims ())
198  result(count) = static_cast<double> (dv(d));
199  else
200  result(count) = 1.0;
201  }
202 
203  retval(0) = result;
204  }
205  else if (name == "isclass")
206  {
207  if (nargin != 3)
208  error (R"(cellfun: not enough arguments for "isclass")");
209 
210  std::string class_name = args(2).string_value ();
211  BNDA result (f_args.dims ());
212  for (octave_idx_type count = 0; count < k; count++)
213  result(count) = (f_args.elem (count).class_name () == class_name);
214 
215  retval(0) = result;
216  }
217 
218  return retval;
219 }
220 
221 static void
223  const octave_value_list& args,
224  int& nargin, bool& uniform_output,
225  octave_value& error_handler)
226 {
227  while (nargin > 3 && args(nargin-2).is_string ())
228  {
229  std::string arg = args(nargin-2).string_value ();
230 
231  size_t compare_len = std::max (arg.length (), static_cast<size_t> (2));
232 
233  if (octave::string::strncmpi (arg, "uniformoutput", compare_len))
234  uniform_output = args(nargin-1).bool_value ();
235  else if (octave::string::strncmpi (arg, "errorhandler", compare_len))
236  {
237  if (args(nargin-1).is_function_handle ()
238  || args(nargin-1).is_inline_function ())
239  {
240  error_handler = args(nargin-1);
241  }
242  else if (args(nargin-1).is_string ())
243  {
244  std::string err_name = args(nargin-1).string_value ();
245 
246  error_handler = symtab.find_function (err_name);
247 
248  if (error_handler.is_undefined ())
249  error ("cellfun: invalid function NAME: %s",
250  err_name.c_str ());
251  }
252  else
253  error ("cellfun: invalid value for 'ErrorHandler' function");
254  }
255  else
256  error ("cellfun: unrecognized parameter %s", arg.c_str ());
257 
258  nargin -= 2;
259  }
260 
261  nargin -= 1;
262 }
263 
264 DEFMETHOD (cellfun, interp, args, nargout,
265  doc: /* -*- texinfo -*-
266 @deftypefn {} {} cellfun (@var{name}, @var{C})
267 @deftypefnx {} {} cellfun ("size", @var{C}, @var{k})
268 @deftypefnx {} {} cellfun ("isclass", @var{C}, @var{class})
269 @deftypefnx {} {} cellfun (@var{func}, @var{C})
270 @deftypefnx {} {} cellfun (@var{func}, @var{C}, @var{D})
271 @deftypefnx {} {[@var{a}, @dots{}] =} cellfun (@dots{})
272 @deftypefnx {} {} cellfun (@dots{}, "ErrorHandler", @var{errfunc})
273 @deftypefnx {} {} cellfun (@dots{}, "UniformOutput", @var{val})
274 
275 Evaluate the function named @var{name} on the elements of the cell array
276 @var{C}.
277 
278 Elements in @var{C} are passed on to the named function individually. The
279 function @var{name} can be one of the functions
280 
281 @table @code
282 @item isempty
283 Return 1 for empty elements.
284 
285 @item islogical
286 Return 1 for logical elements.
287 
288 @item isnumeric
289 Return 1 for numeric elements.
290 
291 @item isreal
292 Return 1 for real elements.
293 
294 @item length
295 Return a vector of the lengths of cell elements.
296 
297 @item ndims
298 Return the number of dimensions of each element.
299 
300 @item numel
301 @itemx prodofsize
302 Return the number of elements contained within each cell element. The
303 number is the product of the dimensions of the object at each cell element.
304 
305 @item size
306 Return the size along the @var{k}-th dimension.
307 
308 @item isclass
309 Return 1 for elements of @var{class}.
310 @end table
311 
312 Additionally, @code{cellfun} accepts an arbitrary function @var{func}
313 in the form of an inline function, function handle, or the name of a
314 function (in a character string). The function can take one or more
315 arguments, with the inputs arguments given by @var{C}, @var{D}, etc.
316 Equally the function can return one or more output arguments. For example:
317 
318 @example
319 @group
320 cellfun ("atan2", @{1, 0@}, @{0, 1@})
321  @result{} [ 1.57080 0.00000 ]
322 @end group
323 @end example
324 
325 The number of output arguments of @code{cellfun} matches the number of
326 output arguments of the function. The outputs of the function will be
327 collected into the output arguments of @code{cellfun} like this:
328 
329 @example
330 @group
331 function [a, b] = twoouts (x)
332  a = x;
333  b = x*x;
334 endfunction
335 [aa, bb] = cellfun (@@twoouts, @{1, 2, 3@})
336  @result{}
337  aa =
338  1 2 3
339  bb =
340  1 4 9
341 @end group
342 @end example
343 
344 Note that per default the output argument(s) are arrays of the same size as
345 the input arguments. Input arguments that are singleton (1x1) cells will be
346 automatically expanded to the size of the other arguments.
347 
348 If the parameter @qcode{"UniformOutput"} is set to true (the default),
349 then the function must return scalars which will be concatenated into the
350 return array(s). If @qcode{"UniformOutput"} is false, the outputs are
351 concatenated into a cell array (or cell arrays). For example:
352 
353 @example
354 @group
355 cellfun ("tolower", @{"Foo", "Bar", "FooBar"@},
356  "UniformOutput", false)
357 @result{} @{"foo", "bar", "foobar"@}
358 @end group
359 @end example
360 
361 Given the parameter @qcode{"ErrorHandler"}, then @var{errfunc} defines a
362 function to call in case @var{func} generates an error. The form of the
363 function is
364 
365 @example
366 function [@dots{}] = errfunc (@var{s}, @dots{})
367 @end example
368 
369 @noindent
370 where there is an additional input argument to @var{errfunc} relative to
371 @var{func}, given by @var{s}. This is a structure with the elements
372 @qcode{"identifier"}, @qcode{"message"}, and @qcode{"index"} giving
373 respectively the error identifier, the error message, and the index into the
374 input arguments of the element that caused the error. For example:
375 
376 @example
377 @group
378 function y = foo (s, x), y = NaN; endfunction
379 cellfun ("factorial", @{-1,2@}, "ErrorHandler", @@foo)
380 @result{} [NaN 2]
381 @end group
382 @end example
383 
384 Use @code{cellfun} intelligently. The @code{cellfun} function is a
385 useful tool for avoiding loops. It is often used with anonymous
386 function handles; however, calling an anonymous function involves an
387 overhead quite comparable to the overhead of an m-file function.
388 Passing a handle to a built-in function is faster, because the
389 interpreter is not involved in the internal loop. For example:
390 
391 @example
392 @group
393 a = @{@dots{}@}
394 v = cellfun (@@(x) det (x), a); # compute determinants
395 v = cellfun (@@det, a); # faster
396 @end group
397 @end example
398 
399 @seealso{arrayfun, structfun, spfun}
400 @end deftypefn */)
401 {
402  int nargin = args.length ();
403 
404  if (nargin < 2)
405  print_usage ();
406 
407  if (! args(1).iscell ())
408  error ("cellfun: C must be a cell array");
409 
411  int nargout1 = (nargout < 1 ? 1 : nargout);
412 
413  octave_value func = args(0);
414 
415  octave::symbol_table& symtab = interp.get_symbol_table ();
416 
417  if (func.is_string ())
418  {
419  retval = try_cellfun_internal_ops<boolNDArray,NDArray> (args, nargin);
420 
421  if (! retval.empty ())
422  return retval;
423 
424  // See if we can convert the string into a function.
425 
426  std::string name = args(0).string_value ();
427 
428  if (! valid_identifier (name))
429  {
430  std::string fcn_name = unique_symbol_name ("__cellfun_fcn__");
431  std::string fname = "function y = " + fcn_name + "(x) y = ";
432 
433  octave_function *ptr_func
434  = extract_function (args(0), "cellfun", fcn_name,
435  fname, "; endfunction");
436 
437  if (ptr_func)
438  func = octave_value (ptr_func, true);
439  }
440  else
441  {
442  func = symtab.find_function (name);
443 
444  if (func.is_undefined ())
445  error ("cellfun: invalid function NAME: %s", name.c_str ());
446  }
447  }
448 
449  if (! func.is_function_handle () && ! func.is_inline_function ()
450  && ! func.is_function ())
451  error ("cellfun: argument NAME must be a string or function handle");
452 
453  bool uniform_output = true;
454  octave_value error_handler;
455 
456  get_mapper_fun_options (symtab, args, nargin, uniform_output, error_handler);
457 
458  // The following is an optimization because the symbol table can give a
459  // more specific function class, so this can result in fewer polymorphic
460  // function calls as the function gets called for each value of the array.
461  {
462  if (func.is_function_handle ())
463  {
465 
466  // Overloaded function handles need to check the type of the
467  // arguments for each element of the array, so they cannot be
468  // optimized this way.
469  if (f -> is_overloaded ())
470  goto nevermind;
471  }
472 
473  std::string name = func.function_value () -> name ();
474  octave_value f = symtab.find_function (name);
475 
476  if (f.is_defined ())
477  {
478  // Except for these two which are special cases...
479  if (name != "size" && name != "class")
480  {
481  // Try first the optimized code path for built-in functions
482  octave_value_list tmp_args = args;
483  tmp_args(0) = name;
484 
485  if (uniform_output)
486  retval =
487  try_cellfun_internal_ops<boolNDArray, NDArray> (tmp_args,
488  nargin);
489  else
490  retval =
491  try_cellfun_internal_ops<Cell, Cell> (tmp_args, nargin);
492 
493  if (! retval.empty ())
494  return retval;
495  }
496 
497  // Okay, we tried, doesn't work, let's do the best we can instead
498  // and avoid polymorphic calls for each element of the array.
499  func = f;
500  }
501  }
502 
503 nevermind:
504 
505  // Extract cell arguments.
506 
507  octave_value_list inputlist (nargin, octave_value ());
508 
509  OCTAVE_LOCAL_BUFFER (Cell, inputs, nargin);
510  OCTAVE_LOCAL_BUFFER (bool, mask, nargin);
511 
512  // This is to prevent copy-on-write.
513  const Cell *cinputs = inputs;
514 
515  octave_idx_type k = 1;
516 
517  dim_vector fdims (1, 1);
518 
519  // Collect arguments. Pre-fill scalar elements of inputlist array.
520 
521  for (int j = 0; j < nargin; j++)
522  {
523  if (! args(j+1).iscell ())
524  error ("cellfun: arguments must be cells");
525 
526  inputs[j] = args(j+1).cell_value ();
527  mask[j] = inputs[j].numel () != 1;
528  if (! mask[j])
529  inputlist(j) = cinputs[j](0);
530  }
531 
532  for (int j = 0; j < nargin; j++)
533  {
534  if (mask[j])
535  {
536  fdims = inputs[j].dims ();
537  k = inputs[j].numel ();
538  for (int i = j+1; i < nargin; i++)
539  {
540  if (mask[i] && inputs[i].dims () != fdims)
541  error ("cellfun: dimensions mismatch");
542  }
543  break;
544  }
545  }
546 
549 
550  if (error_handler.is_defined ())
552 
553  // Apply functions.
554 
555  if (uniform_output)
556  {
557  std::list<octave_value_list> idx_list (1);
558  idx_list.front ().resize (1);
559  std::string idx_type = "(";
560 
561  OCTAVE_LOCAL_BUFFER (octave_value, retv, nargout1);
562 
563  for (octave_idx_type count = 0; count < k; count++)
564  {
565  for (int j = 0; j < nargin; j++)
566  {
567  if (mask[j])
568  inputlist.xelem (j) = cinputs[j](count);
569  }
570 
571  const octave_value_list tmp
572  = get_output_list (count, nargout, inputlist, func,
573  error_handler);
574 
575  if (nargout > 0 && tmp.length () < nargout)
576  error ("cellfun: function returned fewer than nargout values");
577 
578  if (nargout > 0
579  || (nargout == 0
580  && tmp.length () > 0 && tmp(0).is_defined ()))
581  {
582  int num_to_copy = tmp.length ();
583 
584  if (num_to_copy > nargout1)
585  num_to_copy = nargout1;
586 
587  if (count == 0)
588  {
589  for (int j = 0; j < num_to_copy; j++)
590  {
591  if (tmp(j).is_defined ())
592  {
593  octave_value val = tmp(j);
594 
595  if (val.numel () != 1)
596  error ("cellfun: all values must be scalars when UniformOutput = true");
597 
598  retv[j] = val.resize (fdims);
599  }
600  }
601  }
602  else
603  {
604  for (int j = 0; j < num_to_copy; j++)
605  {
606  if (tmp(j).is_defined ())
607  {
608  octave_value val = tmp(j);
609 
610  if (! retv[j].fast_elem_insert (count, val))
611  {
612  if (val.numel () != 1)
613  error ("cellfun: all values must be scalars when UniformOutput = true");
614 
615  idx_list.front ()(0) = count + 1.0;
616  retv[j].assign (octave_value::op_asn_eq,
617  idx_type, idx_list, val);
618  }
619  }
620  }
621  }
622  }
623  }
624 
625  retval.resize (nargout1);
626 
627  for (int j = 0; j < nargout1; j++)
628  {
629  if (nargout > 0 && retv[j].is_undefined ())
630  retval(j) = NDArray (fdims);
631  else
632  retval(j) = retv[j];
633  }
634  }
635  else
636  {
637  OCTAVE_LOCAL_BUFFER (Cell, results, nargout1);
638 
639  for (int j = 0; j < nargout1; j++)
640  results[j].resize (fdims, Matrix ());
641 
642  bool have_some_output = false;
643 
644  for (octave_idx_type count = 0; count < k; count++)
645  {
646  for (int j = 0; j < nargin; j++)
647  {
648  if (mask[j])
649  inputlist.xelem (j) = cinputs[j](count);
650  }
651 
652  const octave_value_list tmp
653  = get_output_list (count, nargout, inputlist, func,
654  error_handler);
655 
656  if (nargout > 0 && tmp.length () < nargout)
657  error ("cellfun: function returned fewer than nargout values");
658 
659  if (nargout > 0
660  || (nargout == 0
661  && tmp.length () > 0 && tmp(0).is_defined ()))
662  {
663  int num_to_copy = tmp.length ();
664 
665  if (num_to_copy > nargout1)
666  num_to_copy = nargout1;
667 
668  if (num_to_copy > 0)
669  have_some_output = true;
670 
671  for (int j = 0; j < num_to_copy; j++)
672  results[j](count) = tmp(j);
673  }
674  }
675 
676  if (have_some_output || fdims.any_zero ())
677  {
678  retval.resize (nargout1);
679 
680  for (int j = 0; j < nargout1; j++)
681  retval(j) = results[j];
682  }
683  }
684 
685  return retval;
686 }
687 
688 /*
689 
690 %!function r = __f11 (x)
691 %! global __cellfun_test_num_outputs__;
692 %! __cellfun_test_num_outputs__ = nargout;
693 %! r = x;
694 %!endfunction
695 
696 %!function __f01 (x)
697 %! global __cellfun_test_num_outputs__;
698 %! __cellfun_test_num_outputs__ = nargout;
699 %!endfunction
700 
701 %!test
702 %! global __cellfun_test_num_outputs__;
703 %! cellfun (@__f11, {1});
704 %! assert (__cellfun_test_num_outputs__, 0);
705 %! x = cellfun (@__f11, {1});
706 %! assert (__cellfun_test_num_outputs__, 1);
707 
708 %!test
709 %! global __cellfun_test_num_outputs__;
710 %! cellfun (@__f01, {1});
711 %! assert (__cellfun_test_num_outputs__, 0);
712 
713 %!error x = cellfun (@__f01, {1, 2})
714 
715 %!test
716 %! assert (cellfun (@__f11, {1, 2}), [1, 2]);
717 %! assert (cellfun (@__f11, {1, 2}, 'uniformoutput', false), {1, 2});
718 
719 %!test
720 %! [a,b] = cellfun (@(x) x, cell (2, 0));
721 %! assert (a, zeros (2, 0));
722 %! assert (b, zeros (2, 0));
723 
724 %!test
725 %! [a,b] = cellfun (@(x) x, cell (2, 0), "uniformoutput", false);
726 %! assert (a, cell (2, 0));
727 %! assert (b, cell (2, 0));
728 
729 ## Test function to check the "Errorhandler" option
730 %!function z = __cellfunerror (S, varargin)
731 %! z = S;
732 %!endfunction
733 
734 ## First input argument can be a string, an inline function,
735 ## a function_handle or an anonymous function
736 %!test
737 %! A = cellfun ("islogical", {true, 0.1, false, i*2});
738 %! assert (A, [true, false, true, false]);
739 %!test
740 %! A = cellfun (inline ("islogical (x)", "x"), {true, 0.1, false, i*2});
741 %! assert (A, [true, false, true, false]);
742 %!test
743 %! A = cellfun (@islogical, {true, 0.1, false, i*2});
744 %! assert (A, [true, false, true, false]);
745 %!test
746 %! A = cellfun (@(x) islogical (x), {true, 0.1, false, i*2});
747 %! assert (A, [true, false, true, false]);
748 
749 ## First input argument can be the special string "isreal",
750 ## "isempty", "islogical", "isnumeric", "length", "ndims" or "prodofsize"
751 %!test
752 %! A = cellfun ("isreal", {true, 0.1, {}, i*2, [], "abc"});
753 %! assert (A, [true, true, false, false, true, true]);
754 %!test
755 %! A = cellfun ("isempty", {true, 0.1, false, i*2, [], "abc"});
756 %! assert (A, [false, false, false, false, true, false]);
757 %!test
758 %! A = cellfun ("islogical", {true, 0.1, false, i*2, [], "abc"});
759 %! assert (A, [true, false, true, false, false, false]);
760 %!test
761 %! A = cellfun ("isnumeric", {true, 0.1, false, i*2, [], "abc"});
762 %! assert (A, [false, true, false, true, true, false]);
763 %!test
764 %! A = cellfun ("length", {true, 0.1, false, i*2, [], "abc"});
765 %! assert (A, [1, 1, 1, 1, 0, 3]);
766 %!test
767 %! A = cellfun ("ndims", {[1, 2; 3, 4]; (cell (1,2,3,4))});
768 %! assert (A, [2; 4]);
769 %!test
770 %! A = cellfun ("prodofsize", {[1, 2; 3, 4], (cell (1,2,3,4))});
771 %! assert (A, [4, 24]);
772 
773 ## Number of input and output arguments may not be limited to one
774 %!test
775 %! A = cellfun (@(x,y,z) x + y + z, {1, 1, 1}, {2, 2, 2}, {3, 4, 5});
776 %! assert (A, [6, 7, 8]);
777 %!test
778 %! A = cellfun (@(x,y,z) x + y + z, {1, 1, 1}, {2, 2, 2}, {3, 4, 5}, ...
779 %! "UniformOutput", false);
780 %! assert (A, {6, 7, 8});
781 %!test # Two input arguments of different types
782 %! A = cellfun (@(x,y) islogical (x) && ischar (y), {false, true}, {"a", 3});
783 %! assert (A, [true, false]);
784 %!test # Pass another variable to the anonymous function
785 %! y = true;
786 %! A = cellfun (@(x) islogical (x) && y, {false, 0.3});
787 %! assert (A, [true, false]);
788 %!test # Three ouptut arguments of different type
789 %! [A, B, C] = cellfun (@find, {10, 11; 0, 12}, "UniformOutput", false);
790 %! assert (isequal (A, {true, true; [], true}));
791 %! assert (isequal (B, {true, true; [], true}));
792 %! assert (isequal (C, {10, 11; [], 12}));
793 
794 ## Input arguments can be of type cell array of logical
795 %!test
796 %! A = cellfun (@(x,y) x == y, {false, true}, {true, true});
797 %! assert (A, [false, true]);
798 %!test
799 %! A = cellfun (@(x,y) x == y, {false; true}, {true; true}, ...
800 %! "UniformOutput", true);
801 %! assert (A, [false; true]);
802 %!test
803 %! A = cellfun (@(x) x, {false, true; false, true}, "UniformOutput", false);
804 %! assert (A, {false, true; false, true});
805 %!test # Three ouptut arguments of same type
806 %! [A, B, C] = cellfun (@find, {true, false; false, true}, ...
807 %! "UniformOutput", false);
808 %! assert (isequal (A, {true, []; [], true}));
809 %! assert (isequal (B, {true, []; [], true}));
810 %! assert (isequal (C, {true, []; [], true}));
811 %!test
812 %! A = cellfun (@(x,y) cell2str (x,y), {true}, {true}, ...
813 %! "ErrorHandler", @__cellfunerror);
814 %! assert (isfield (A, "identifier"), true);
815 %! assert (isfield (A, "message"), true);
816 %! assert (isfield (A, "index"), true);
817 %! assert (isempty (A.message), false);
818 %! assert (A.index, 1);
819 %!test # Overwriting setting of "UniformOutput" true
820 %! A = cellfun (@(x,y) cell2str (x,y), {true}, {true}, ...
821 %! "UniformOutput", true, "ErrorHandler", @__cellfunerror);
822 %! assert (isfield (A, "identifier"), true);
823 %! assert (isfield (A, "message"), true);
824 %! assert (isfield (A, "index"), true);
825 %! assert (isempty (A.message), false);
826 %! assert (A.index, 1);
827 
828 ## Input arguments can be of type cell array of numeric
829 %!test
830 %! A = cellfun (@(x,y) x>y, {1.1, 4.2}, {3.1, 2+3*i});
831 %! assert (A, [false, true]);
832 %!test
833 %! A = cellfun (@(x,y) x>y, {1.1, 4.2; 2, 4}, {3.1, 2; 2, 4+2*i}, ...
834 %! "UniformOutput", true);
835 %! assert (A, [false, true; false, false]);
836 %!test
837 %! A = cellfun (@(x,y) x:y, {1.1, 4}, {3.1, 6}, "UniformOutput", false);
838 %! assert (isequal (A{1}, [1.1, 2.1, 3.1]));
839 %! assert (isequal (A{2}, [4, 5, 6]));
840 %!test # Three ouptut arguments of different type
841 %! [A, B, C] = cellfun (@find, {10, 11; 0, 12}, "UniformOutput", false);
842 %! assert (isequal (A, {true, true; [], true}));
843 %! assert (isequal (B, {true, true; [], true}));
844 %! assert (isequal (C, {10, 11; [], 12}));
845 %!test
846 %! A = cellfun (@(x,y) cell2str (x,y), {1.1, 4}, {3.1, 6}, ...
847 %! "ErrorHandler", @__cellfunerror);
848 %! B = isfield (A(1), "message") && isfield (A(1), "index");
849 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
850 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
851 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
852 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
853 %! assert ([A(1).index, A(2).index], [1, 2]);
854 %!test # Overwriting setting of "UniformOutput" true
855 %! A = cellfun (@(x,y) cell2str (x,y), {1.1, 4}, {3.1, 6}, ...
856 %! "UniformOutput", true, "ErrorHandler", @__cellfunerror);
857 %! B = isfield (A(1), "message") && isfield (A(1), "index");
858 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
859 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
860 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
861 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
862 %! assert ([A(1).index, A(2).index], [1, 2]);
863 
864 ## Input arguments can be of type cell arrays of character or strings
865 %!error # "UniformOutput" false should be used
866 %! A = cellfun (@(x,y) x>y, {"ad", "c", "ghi"}, {"cc", "d", "fgh"});
867 %!test
868 %! A = cellfun (@(x,y) x>y, {"a"; "f"}, {"c"; "d"}, "UniformOutput", true);
869 %! assert (A, [false; true]);
870 %!test
871 %! A = cellfun (@(x,y) x:y, {"a", "d"}, {"c", "f"}, "UniformOutput", false);
872 %! assert (A, {"abc", "def"});
873 %!test
874 %! A = cellfun (@(x,y) cell2str (x,y), {"a", "d"}, {"c", "f"}, ...
875 %! "ErrorHandler", @__cellfunerror);
876 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
877 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
878 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
879 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
880 %! assert ([A(1).index, A(2).index], [1, 2]);
881 %!test # Overwriting setting of "UniformOutput" true
882 %! A = cellfun (@(x,y) cell2str (x,y), {"a", "d"}, {"c", "f"}, ...
883 %! "UniformOutput", true, "ErrorHandler", @__cellfunerror);
884 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
885 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
886 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
887 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
888 %! assert ([A(1).index, A(2).index], [1, 2]);
889 
890 ## Structures cannot be handled by cellfun
891 %!error
892 %! vst1.a = 1.1; vst1.b = 4.2; vst2.a = 3.1; vst2.b = 2;
893 %! A = cellfun (@(x,y) (x.a < y.a) && (x.b > y.b), vst1, vst2);
894 
895 ## Input arguments can be of type cell array of cell arrays
896 %!test
897 %! A = cellfun (@(x,y) x{1} < y{1}, {{1.1}, {4.2}}, {{3.1}, {2}});
898 %! assert (A, [1, 0], 1e-16);
899 %!test
900 %! A = cellfun (@(x,y) x{1} < y{1}, {{1.1}; {4.2}}, {{3.1}; {2}}, ...
901 %! "UniformOutput", true);
902 %! assert (A, [1; 0], 1e-16);
903 %!test
904 %! A = cellfun (@(x,y) x{1} < y{1}, {{1.1}, {4.2}}, {{3.1}, {2}}, ...
905 %! "UniformOutput", false);
906 %! assert (A, {true, false});
907 %!test
908 %! A = cellfun (@(x,y) mat2str (x,y), {{1.1}, {4.2}}, {{3.1}, {2}}, ...
909 %! "ErrorHandler", @__cellfunerror);
910 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
911 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
912 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
913 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
914 %! assert ([A(1).index, A(2).index], [1, 2]);
915 %!test # Overwriting setting of "UniformOutput" true
916 %! A = cellfun (@(x,y) mat2str (x,y), {{1.1}, {4.2}}, {{3.1}, {2}}, ...
917 %! "UniformOutput", true, "ErrorHandler", @__cellfunerror);
918 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
919 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
920 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
921 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
922 %! assert ([A(1).index, A(2).index], [1, 2]);
923 
924 ## Input arguments can be of type cell array of structure arrays
925 %!test
926 %! a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
927 %! A = cellfun (@(x,y) (x.a == y.a) && (x.b < y.b), {a}, {b});
928 %! assert (A, true);
929 %!test
930 %! a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
931 %! A = cellfun (@(x,y) (x.a == y.a) && (x.b < y.b) , {a}, {b}, ...
932 %! "UniformOutput", true);
933 %! assert (A, true);
934 %!test
935 %! a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
936 %! A = cellfun (@(x,y) (x.a == y.a) && (x.b < y.b) , {a}, {b}, ...
937 %! "UniformOutput", false);
938 %! assert (A, {true});
939 %!test
940 %! a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
941 %! A = cellfun (@(x,y) cell2str (x.a, y.a), {a}, {b}, ...
942 %! "ErrorHandler", @__cellfunerror);
943 %! assert (isfield (A, "identifier"), true);
944 %! assert (isfield (A, "message"), true);
945 %! assert (isfield (A, "index"), true);
946 %! assert (isempty (A.message), false);
947 %! assert (A.index, 1);
948 %!test # Overwriting setting of "UniformOutput" true
949 %! a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
950 %! A = cellfun (@(x,y) cell2str (x.a, y.a), {a}, {b}, ...
951 %! "UniformOutput", true, "ErrorHandler", @__cellfunerror);
952 %! assert (isfield (A, "identifier"), true);
953 %! assert (isfield (A, "message"), true);
954 %! assert (isfield (A, "index"), true);
955 %! assert (isempty (A.message), false);
956 %! assert (A.index, 1);
957 
958 ## A lot of other tests
959 %!assert (cellfun (@sin, {0,1}), sin ([0,1]))
960 %!assert (cellfun (inline ("sin (x)"), {0,1}), sin ([0,1]))
961 %!assert (cellfun ("sin", {0,1}), sin ([0,1]))
962 %!assert (cellfun ("isempty", {1,[]}), [false,true])
963 %!assert (cellfun ("islogical", {false,pi}), [true,false])
964 %!assert (cellfun ("isnumeric", {false,pi,struct()}), [false,true,false])
965 %!assert (cellfun ("isreal", {1i,1}), [false,true])
966 %!assert (cellfun ("length", {zeros(2,2),1}), [2,1])
967 %!assert (cellfun ("prodofsize", {zeros(2,2),1}), [4,1])
968 %!assert (cellfun ("ndims", {zeros([2,2,2]),1}), [3,2])
969 %!assert (cellfun ("isclass", {zeros([2,2,2]),"test"}, "double"), [true,false])
970 %!assert (cellfun ("size", {zeros([1,2,3]),1}, 1), [1,1])
971 %!assert (cellfun ("size", {zeros([1,2,3]),1}, 2), [2,1])
972 %!assert (cellfun ("size", {zeros([1,2,3]),1}, 3), [3,1])
973 %!assert (cellfun (@atan2, {1,1}, {1,2}), [atan2(1,1), atan2(1,2)])
974 %!assert (cellfun (@atan2, {1,1}, {1,2},"UniformOutput", false), {atan2(1,1), atan2(1,2)})
975 %!assert (cellfun (@sin, {1,2;3,4}), sin ([1,2;3,4]))
976 %!assert (cellfun (@atan2, {1,1;1,1}, {1,2;1,2}), atan2 ([1,1;1,1],[1,2;1,2]))
977 %!error cellfun (@factorial, {-1,3})
978 %!assert (cellfun (@factorial,{-1,3},"ErrorHandler",@(x,y) NaN), [NaN,6])
979 %!assert (cellfun (@(x) x(2),{[1],[1,2]},"ErrorHandler",@(x,y) NaN), [NaN,2])
980 %!test
981 %! [a,b,c] = cellfun (@fileparts, {fullfile("a","b","c.d"), fullfile("e","f","g.h")}, "UniformOutput", false);
982 %! assert (a, {fullfile("a","b"), fullfile("e","f")});
983 %! assert (b, {"c", "g"});
984 %! assert (c, {".d", ".h"});
985 
986 %!assert <*40467> (cellfun (@isreal, {1 inf nan []}), [true, true, true, true])
987 %!assert <*40467> (cellfun (@isreal, {1 inf nan []}, "UniformOutput", false), {true, true, true, true})
988 %!assert <*40467> (cellfun (@iscomplex, {1 inf nan []}), [false, false, false, false])
989 %!assert <*40467> (cellfun (@iscomplex, {1 inf nan []}, "UniformOutput", false), {false, false, false, false})
990 
991 %!error cellfun (1)
992 %!error cellfun ("isclass", 1)
993 %!error cellfun ("size", 1)
994 %!error cellfun (@sin, {[]}, "BadParam", false)
995 %!error cellfun (@sin, {[]}, "UniformOuput")
996 %!error cellfun (@sin, {[]}, "ErrorHandler")
997 */
998 
999 // Arrayfun was originally a .m file written by Bill Denney and Jaroslav
1000 // Hajek. It was converted to C++ by jwe so that it could properly
1001 // handle the nargout = 0 case.
1002 
1003 DEFMETHOD (arrayfun, interp, args, nargout,
1004  doc: /* -*- texinfo -*-
1005 @deftypefn {} {} arrayfun (@var{func}, @var{A})
1006 @deftypefnx {} {@var{x} =} arrayfun (@var{func}, @var{A})
1007 @deftypefnx {} {@var{x} =} arrayfun (@var{func}, @var{A}, @var{b}, @dots{})
1008 @deftypefnx {} {[@var{x}, @var{y}, @dots{}] =} arrayfun (@var{func}, @var{A}, @dots{})
1009 @deftypefnx {} {} arrayfun (@dots{}, "UniformOutput", @var{val})
1010 @deftypefnx {} {} arrayfun (@dots{}, "ErrorHandler", @var{errfunc})
1011 
1012 Execute a function on each element of an array.
1013 
1014 This is useful for functions that do not accept array arguments. If the
1015 function does accept array arguments it is better to call the function
1016 directly.
1017 
1018 The first input argument @var{func} can be a string, a function
1019 handle, an inline function, or an anonymous function. The input
1020 argument @var{A} can be a logic array, a numeric array, a string
1021 array, a structure array, or a cell array. By a call of the function
1022 @code{arrayfun} all elements of @var{A} are passed on to the named
1023 function @var{func} individually.
1024 
1025 The named function can also take more than two input arguments, with
1026 the input arguments given as third input argument @var{b}, fourth
1027 input argument @var{c}, @dots{} If given more than one array input
1028 argument then all input arguments must have the same sizes, for
1029 example:
1030 
1031 @example
1032 @group
1033 arrayfun (@@atan2, [1, 0], [0, 1])
1034  @result{} [ 1.57080 0.00000 ]
1035 @end group
1036 @end example
1037 
1038 If the parameter @var{val} after a further string input argument
1039 @qcode{"UniformOutput"} is set @code{true} (the default), then the named
1040 function @var{func} must return a single element which then will be
1041 concatenated into the return value and is of type matrix. Otherwise,
1042 if that parameter is set to @code{false}, then the outputs are
1043 concatenated in a cell array. For example:
1044 
1045 @example
1046 @group
1047 arrayfun (@@(x,y) x:y, "abc", "def", "UniformOutput", false)
1048 @result{}
1049  @{
1050  [1,1] = abcd
1051  [1,2] = bcde
1052  [1,3] = cdef
1053  @}
1054 @end group
1055 @end example
1056 
1057 If more than one output arguments are given then the named function
1058 must return the number of return values that also are expected, for
1059 example:
1060 
1061 @example
1062 @group
1063 [A, B, C] = arrayfun (@@find, [10; 0], "UniformOutput", false)
1064 @result{}
1065 A =
1066 @{
1067  [1,1] = 1
1068  [2,1] = [](0x0)
1069 @}
1070 B =
1071 @{
1072  [1,1] = 1
1073  [2,1] = [](0x0)
1074 @}
1075 C =
1076 @{
1077  [1,1] = 10
1078  [2,1] = [](0x0)
1079 @}
1080 @end group
1081 @end example
1082 
1083 If the parameter @var{errfunc} after a further string input argument
1084 @qcode{"ErrorHandler"} is another string, a function handle, an inline
1085 function, or an anonymous function, then @var{errfunc} defines a
1086 function to call in the case that @var{func} generates an error.
1087 The definition of the function must be of the form
1088 
1089 @example
1090 function [@dots{}] = errfunc (@var{s}, @dots{})
1091 @end example
1092 
1093 @noindent
1094 where there is an additional input argument to @var{errfunc}
1095 relative to @var{func}, given by @var{s}. This is a structure with
1096 the elements @qcode{"identifier"}, @qcode{"message"}, and
1097 @qcode{"index"} giving, respectively, the error identifier, the error
1098 message, and the index of the array elements that caused the error. The
1099 size of the output argument of @var{errfunc} must have the same size as the
1100 output argument of @var{func}, otherwise a real error is thrown. For
1101 example:
1102 
1103 @example
1104 @group
1105 function y = ferr (s, x), y = "MyString"; endfunction
1106 arrayfun (@@str2num, [1234],
1107  "UniformOutput", false, "ErrorHandler", @@ferr)
1108 @result{}
1109  @{
1110  [1,1] = MyString
1111  @}
1112 @end group
1113 @end example
1114 
1115 @seealso{spfun, cellfun, structfun}
1116 @end deftypefn */)
1117 {
1118  int nargin = args.length ();
1119 
1120  if (nargin < 2)
1121  print_usage ();
1122 
1124  int nargout1 = (nargout < 1 ? 1 : nargout);
1125  bool symbol_table_lookup = false;
1126  octave_value func = args(0);
1127 
1128  octave::symbol_table& symtab = interp.get_symbol_table ();
1129 
1130  if (func.is_string ())
1131  {
1132  // See if we can convert the string into a function.
1133  std::string name = args(0).string_value ();
1134 
1135  if (! valid_identifier (name))
1136  {
1137  std::string fcn_name = unique_symbol_name ("__arrayfun_fcn__");
1138  std::string fname = "function y = " + fcn_name + "(x) y = ";
1139 
1140  octave_function *ptr_func
1141  = extract_function (args(0), "arrayfun", fcn_name,
1142  fname, "; endfunction");
1143 
1144  if (ptr_func)
1145  func = octave_value (ptr_func, true);
1146  }
1147  else
1148  {
1149  func = symtab.find_function (name);
1150 
1151  if (func.is_undefined ())
1152  error_with_id ("Octave:invalid-input-arg",
1153  "arrayfun: invalid function NAME: %s",
1154  name.c_str ());
1155 
1156  symbol_table_lookup = true;
1157  }
1158  }
1159 
1160  if (func.is_function_handle () || func.is_inline_function ()
1161  || func.is_function ())
1162  {
1163  // The following is an optimization because the symbol table can give a
1164  // more specific function class, so this can result in fewer polymorphic
1165  // function calls as the function gets called for each value of the array.
1166 
1167  if (! symbol_table_lookup)
1168  {
1169  if (func.is_function_handle ())
1170  {
1172 
1173  // Overloaded function handles need to check the type of the
1174  // arguments for each element of the array, so they cannot be
1175  // optimized this way.
1176  if (f -> is_overloaded ())
1177  goto nevermind;
1178  }
1179  octave_value f
1180  = symtab.find_function (func.function_value () -> name ());
1181 
1182  if (f.is_defined ())
1183  func = f;
1184  }
1185 
1186  nevermind:
1187 
1188  bool uniform_output = true;
1189  octave_value error_handler;
1190 
1191  get_mapper_fun_options (symtab, args, nargin, uniform_output,
1192  error_handler);
1193 
1194  octave_value_list inputlist (nargin, octave_value ());
1195 
1197  OCTAVE_LOCAL_BUFFER (bool, mask, nargin);
1198 
1199  octave_idx_type k = 1;
1200 
1201  dim_vector fdims (1, 1);
1202 
1203  // Collect arguments. Pre-fill scalar elements of inputlist array.
1204 
1205  for (int j = 0; j < nargin; j++)
1206  {
1207  inputs[j] = args(j+1);
1208  mask[j] = inputs[j].numel () != 1;
1209 
1210  if (! mask[j])
1211  inputlist(j) = inputs[j];
1212  }
1213 
1214  for (int j = 0; j < nargin; j++)
1215  {
1216  if (mask[j])
1217  {
1218  fdims = inputs[j].dims ();
1219  k = inputs[j].numel ();
1220 
1221  for (int i = j+1; i < nargin; i++)
1222  {
1223  if (mask[i] && inputs[i].dims () != fdims)
1224  error_with_id ("Octave:invalid-input-arg",
1225  "arrayfun: dimensions mismatch");
1226  }
1227  break;
1228  }
1229  }
1230 
1233 
1234  if (error_handler.is_defined ())
1236 
1237  // Apply functions.
1238 
1239  if (uniform_output)
1240  {
1241  std::list<octave_value_list> idx_list (1);
1242  idx_list.front ().resize (1);
1243  std::string idx_type = "(";
1244 
1245  OCTAVE_LOCAL_BUFFER (octave_value, retv, nargout1);
1246 
1247  for (octave_idx_type count = 0; count < k; count++)
1248  {
1249  idx_list.front ()(0) = count + 1.0;
1250 
1251  for (int j = 0; j < nargin; j++)
1252  {
1253  if (mask[j])
1254  inputlist.xelem (j) = inputs[j].do_index_op (idx_list);
1255  }
1256 
1257  const octave_value_list tmp
1258  = get_output_list (count, nargout, inputlist, func,
1259  error_handler);
1260 
1261  if (nargout > 0 && tmp.length () < nargout)
1262  error_with_id ("Octave:invalid-fun-call",
1263  "arrayfun: function returned fewer than nargout values");
1264 
1265  if (nargout > 0
1266  || (nargout == 0
1267  && tmp.length () > 0 && tmp(0).is_defined ()))
1268  {
1269  int num_to_copy = tmp.length ();
1270 
1271  if (num_to_copy > nargout1)
1272  num_to_copy = nargout1;
1273 
1274  if (count == 0)
1275  {
1276  for (int j = 0; j < num_to_copy; j++)
1277  {
1278  if (tmp(j).is_defined ())
1279  {
1280  octave_value val = tmp(j);
1281 
1282  if (val.numel () == 1)
1283  retv[j] = val.resize (fdims);
1284  else
1285  error_with_id ("Octave:invalid-fun-call",
1286  "arrayfun: all values must be scalars when UniformOutput = true");
1287  }
1288  }
1289  }
1290  else
1291  {
1292  for (int j = 0; j < num_to_copy; j++)
1293  {
1294  if (tmp(j).is_defined ())
1295  {
1296  octave_value val = tmp(j);
1297 
1298  if (! retv[j].fast_elem_insert (count, val))
1299  {
1300  if (val.numel () == 1)
1301  {
1302  idx_list.front ()(0) = count + 1.0;
1303  retv[j].assign (octave_value::op_asn_eq,
1304  idx_type, idx_list, val);
1305  }
1306  else
1307  error_with_id ("Octave:invalid-fun-call",
1308  "arrayfun: all values must be scalars when UniformOutput = true");
1309  }
1310  }
1311  }
1312  }
1313  }
1314  }
1315 
1316  retval.resize (nargout1);
1317 
1318  for (int j = 0; j < nargout1; j++)
1319  {
1320  if (nargout > 0 && retv[j].is_undefined ())
1321  retval(j) = NDArray (fdims);
1322  else
1323  retval(j) = retv[j];
1324  }
1325  }
1326  else
1327  {
1328  std::list<octave_value_list> idx_list (1);
1329  idx_list.front ().resize (1);
1330  std::string idx_type = "(";
1331 
1332  OCTAVE_LOCAL_BUFFER (Cell, results, nargout1);
1333 
1334  for (int j = 0; j < nargout1; j++)
1335  results[j].resize (fdims, Matrix ());
1336 
1337  bool have_some_output = false;
1338 
1339  for (octave_idx_type count = 0; count < k; count++)
1340  {
1341  idx_list.front ()(0) = count + 1.0;
1342 
1343  for (int j = 0; j < nargin; j++)
1344  {
1345  if (mask[j])
1346  inputlist.xelem (j) = inputs[j].do_index_op (idx_list);
1347  }
1348 
1349  const octave_value_list tmp
1350  = get_output_list (count, nargout, inputlist, func,
1351  error_handler);
1352 
1353  if (nargout > 0 && tmp.length () < nargout)
1354  error_with_id ("Octave:invalid-fun-call",
1355  "arrayfun: function returned fewer than nargout values");
1356 
1357  if (nargout > 0
1358  || (nargout == 0
1359  && tmp.length () > 0 && tmp(0).is_defined ()))
1360  {
1361  int num_to_copy = tmp.length ();
1362 
1363  if (num_to_copy > nargout1)
1364  num_to_copy = nargout1;
1365 
1366  if (num_to_copy > 0)
1367  have_some_output = true;
1368 
1369  for (int j = 0; j < num_to_copy; j++)
1370  results[j](count) = tmp(j);
1371  }
1372  }
1373 
1374  if (have_some_output || fdims.any_zero ())
1375  {
1376  retval.resize (nargout1);
1377 
1378  for (int j = 0; j < nargout1; j++)
1379  retval(j) = results[j];
1380  }
1381  }
1382  }
1383  else
1384  error_with_id ("Octave:invalid-fun-call",
1385  "arrayfun: argument NAME must be a string or function handle");
1386 
1387  return retval;
1388 }
1389 
1390 /*
1391 %!function r = __f11 (x)
1392 %! global __arrayfun_test_num_outputs__;
1393 %! __arrayfun_test_num_outputs__ = nargout;
1394 %! r = x;
1395 %!endfunction
1396 
1397 %!function __f01 (x)
1398 %! global __arrayfun_test_num_outputs__;
1399 %! __arrayfun_test_num_outputs__ = nargout;
1400 %!endfunction
1401 
1402 %!test
1403 %! global __arrayfun_test_num_outputs__;
1404 %! arrayfun (@__f11, {1});
1405 %! assert (__arrayfun_test_num_outputs__, 0);
1406 %! x = arrayfun (@__f11, {1});
1407 %! assert (__arrayfun_test_num_outputs__, 1);
1408 
1409 %!test
1410 %! global __arrayfun_test_num_outputs__;
1411 %! arrayfun (@__f01, {1});
1412 %! assert (__arrayfun_test_num_outputs__, 0);
1413 
1414 %!error x = arrayfun (@__f01, [1, 2])
1415 
1416 %!test
1417 %! assert (arrayfun (@__f11, [1, 2]), [1, 2]);
1418 %! assert (arrayfun (@__f11, [1, 2], "uniformoutput", false), {1, 2});
1419 %! assert (arrayfun (@__f11, {1, 2}), {1, 2});
1420 %! assert (arrayfun (@__f11, {1, 2}, "uniformoutput", false), {{1}, {2}});
1421 
1422 %!assert (arrayfun (@ones, 1, [2,3], "uniformoutput", false), {[1,1], [1,1,1]})
1423 
1424 ## Test function to check the "Errorhandler" option
1425 %!function z = __arrayfunerror (S, varargin)
1426 %! z = S;
1427 %!endfunction
1428 ## First input argument can be a string, an inline function, a
1429 ## function_handle or an anonymous function
1430 %!test
1431 %! arrayfun (@isequal, [false, true], [true, true]); # No output argument
1432 %!error
1433 %! arrayfun (@isequal); # One or less input arguments
1434 %!test
1435 %! A = arrayfun ("isequal", [false, true], [true, true]);
1436 %! assert (A, [false, true]);
1437 %!test
1438 %! A = arrayfun (inline ("(x == y)", "x", "y"), [false, true], [true, true]);
1439 %! assert (A, [false, true]);
1440 %!test
1441 %! A = arrayfun (@isequal, [false, true], [true, true]);
1442 %! assert (A, [false, true]);
1443 %!test
1444 %! A = arrayfun (@(x,y) isequal (x,y), [false, true], [true, true]);
1445 %! assert (A, [false, true]);
1446 
1447 ## Number of input and output arguments may be greater than one
1448 %!test
1449 %! A = arrayfun (@(x) islogical (x), false);
1450 %! assert (A, true);
1451 %!test
1452 %! A = arrayfun (@(x,y,z) x + y + z, [1, 1, 1], [2, 2, 2], [3, 4, 5]);
1453 %! assert (A, [6, 7, 8], 1e-16);
1454 %!test # Two input arguments of different types
1455 %! A = arrayfun (@(x,y) islogical (x) && ischar (y), false, "a");
1456 %! assert (A, true);
1457 %!test # Pass another variable to the anonymous function
1458 %! y = true;
1459 %! A = arrayfun (@(x) islogical (x && y), false);
1460 %! assert (A, true);
1461 %!test # Three ouptut arguments of different type
1462 %! [A, B, C] = arrayfun (@find, [10, 11; 0, 12], "UniformOutput", false);
1463 %! assert (isequal (A, {true, true; [], true}));
1464 %! assert (isequal (B, {true, true; [], true}));
1465 %! assert (isequal (C, {10, 11; [], 12}));
1466 
1467 ## Input arguments can be of type logical
1468 %!test
1469 %! A = arrayfun (@(x,y) x == y, [false, true], [true, true]);
1470 %! assert (A, [false, true]);
1471 %!test
1472 %! A = arrayfun (@(x,y) x == y, [false; true], [true; true], "UniformOutput", true);
1473 %! assert (A, [false; true]);
1474 %!test
1475 %! A = arrayfun (@(x) x, [false, true, false, true], "UniformOutput", false);
1476 %! assert (A, {false, true, false, true});
1477 %!test # Three ouptut arguments of same type
1478 %! [A, B, C] = arrayfun (@find, [true, false; false, true], "UniformOutput", false);
1479 %! assert (isequal (A, {true, []; [], true}));
1480 %! assert (isequal (B, {true, []; [], true}));
1481 %! assert (isequal (C, {true, []; [], true}));
1482 %!test
1483 %! A = arrayfun (@(x,y) array2str (x,y), true, true, ...
1484 %! "ErrorHandler", @__arrayfunerror);
1485 %! assert (isfield (A, "identifier"), true);
1486 %! assert (isfield (A, "message"), true);
1487 %! assert (isfield (A, "index"), true);
1488 %! assert (isempty (A.message), false);
1489 %! assert (A.index, 1);
1490 %!test # Overwriting setting of "UniformOutput" true
1491 %! A = arrayfun (@(x,y) array2str (x,y), true, true, "UniformOutput", true, ...
1492 %! "ErrorHandler", @__arrayfunerror);
1493 %! assert (isfield (A, "identifier"), true);
1494 %! assert (isfield (A, "message"), true);
1495 %! assert (isfield (A, "index"), true);
1496 %! assert (isempty (A.message), false);
1497 %! assert (A.index, 1);
1498 
1499 ## Input arguments can be of type numeric
1500 %!test
1501 %! A = arrayfun (@(x,y) x>y, [1.1, 4.2], [3.1, 2+3*i]);
1502 %! assert (A, [false, true]);
1503 %!test
1504 %! A = arrayfun (@(x,y) x>y, [1.1, 4.2; 2, 4], [3.1, 2; 2, 4+2*i], "UniformOutput", true);
1505 %! assert (A, [false, true; false, false]);
1506 %!test
1507 %! A = arrayfun (@(x,y) x:y, [1.1, 4], [3.1, 6], "UniformOutput", false);
1508 %! assert (isequal (A{1}, [1.1, 2.1, 3.1]));
1509 %! assert (isequal (A{2}, [4, 5, 6]));
1510 %!test # Three ouptut arguments of different type
1511 %! [A, B, C] = arrayfun (@find, [10, 11; 0, 12], "UniformOutput", false);
1512 %! assert (isequal (A, {true, true; [], true}));
1513 %! assert (isequal (B, {true, true; [], true}));
1514 %! assert (isequal (C, {10, 11; [], 12}));
1515 %!test
1516 %! A = arrayfun (@(x,y) array2str (x,y), {1.1, 4}, {3.1, 6}, ...
1517 %! "ErrorHandler", @__arrayfunerror);
1518 %! B = isfield (A(1), "message") && isfield (A(1), "index");
1519 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
1520 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
1521 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
1522 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
1523 %! assert ([A(1).index, A(2).index], [1, 2]);
1524 %!test # Overwriting setting of "UniformOutput" true
1525 %! A = arrayfun (@(x,y) array2str (x,y), {1.1, 4}, {3.1, 6}, ...
1526 %! "UniformOutput", true, "ErrorHandler", @__arrayfunerror);
1527 %! B = isfield (A(1), "message") && isfield (A(1), "index");
1528 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
1529 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
1530 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
1531 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
1532 %! assert ([A(1).index, A(2).index], [1, 2]);
1533 
1534 ## Input arguments can be of type character or strings
1535 %!test
1536 %! A = arrayfun (@(x,y) x>y, ["ad", "c", "ghi"], ["cc", "d", "fgh"]);
1537 %! assert (A, [false, true, false, true, true, true]);
1538 %!test
1539 %! A = arrayfun (@(x,y) x>y, ["a"; "f"], ["c"; "d"], "UniformOutput", true);
1540 %! assert (A, [false; true]);
1541 %!test
1542 %! A = arrayfun (@(x,y) x:y, ["a", "d"], ["c", "f"], "UniformOutput", false);
1543 %! assert (A, {"abc", "def"});
1544 %!test
1545 %! A = arrayfun (@(x,y) cell2str (x,y), ["a", "d"], ["c", "f"], ...
1546 %! "ErrorHandler", @__arrayfunerror);
1547 %! B = isfield (A(1), "identifier") && isfield (A(1), "message") && isfield (A(1), "index");
1548 %! assert (B, true);
1549 
1550 ## Input arguments can be of type structure
1551 %!test
1552 %! a = struct ("a", 1.1, "b", 4.2); b = struct ("a", 3.1, "b", 2);
1553 %! A = arrayfun (@(x,y) (x.a < y.a) && (x.b > y.b), a, b);
1554 %! assert (A, true);
1555 %!test
1556 %! a = struct ("a", 1.1, "b", 4.2); b = struct ("a", 3.1, "b", 2);
1557 %! A = arrayfun (@(x,y) (x.a < y.a) && (x.b > y.b), a, b, "UniformOutput", true);
1558 %! assert (A, true);
1559 %!test
1560 %! a = struct ("a", 1.1, "b", 4.2); b = struct ("a", 3.1, "b", 2);
1561 %! A = arrayfun (@(x,y) x.a:y.a, a, b, "UniformOutput", false);
1562 %! assert (isequal (A, {[1.1, 2.1, 3.1]}));
1563 %!test
1564 %! A = arrayfun (@(x) mat2str(x), "a", "ErrorHandler", @__arrayfunerror);
1565 %! assert (isfield (A, "identifier"), true);
1566 %! assert (isfield (A, "message"), true);
1567 %! assert (isfield (A, "index"), true);
1568 %! assert (isempty (A.message), false);
1569 %! assert (A.index, 1);
1570 %!test # Overwriting setting of "UniformOutput" true
1571 %! A = arrayfun (@(x) mat2str(x), "a", "UniformOutput", true, ...
1572 %! "ErrorHandler", @__arrayfunerror);
1573 %! assert (isfield (A, "identifier"), true);
1574 %! assert (isfield (A, "message"), true);
1575 %! assert (isfield (A, "index"), true);
1576 %! assert (isempty (A.message), false);
1577 %! assert (A.index, 1);
1578 
1579 ## Input arguments can be of type cell array
1580 %!test
1581 %! A = arrayfun (@(x,y) x{1} < y{1}, {1.1, 4.2}, {3.1, 2});
1582 %! assert (A, [true, false]);
1583 %!test
1584 %! A = arrayfun (@(x,y) x{1} < y{1}, {1.1; 4.2}, {3.1; 2}, "UniformOutput", true);
1585 %! assert (A, [true; false]);
1586 %!test
1587 %! A = arrayfun (@(x,y) x{1} < y{1}, {1.1, 4.2}, {3.1, 2}, "UniformOutput", false);
1588 %! assert (A, {true, false});
1589 %!test
1590 %! A = arrayfun (@(x,y) num2str(x,y), {1.1, 4.2}, {3.1, 2}, "ErrorHandler", @__arrayfunerror);
1591 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
1592 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
1593 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
1594 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
1595 %! assert ([A(1).index, A(2).index], [1, 2]);
1596 %!test
1597 %! A = arrayfun (@(x,y) num2str (x,y), {1.1, 4.2}, {3.1, 2}, ...
1598 %! "UniformOutput", true, "ErrorHandler", @__arrayfunerror);
1599 %! assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
1600 %! assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
1601 %! assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
1602 %! assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
1603 %! assert ([A(1).index, A(2).index], [1, 2]);
1604 */
1605 
1606 static void
1607 do_num2cell_helper (const dim_vector& dv,
1608  const Array<int>& dimv,
1609  dim_vector& celldv, dim_vector& arraydv,
1610  Array<int>& perm)
1611 {
1612  int dvl = dimv.numel ();
1613  int maxd = dv.ndims ();
1614  celldv = dv;
1615  for (int i = 0; i < dvl; i++)
1616  maxd = std::max (maxd, dimv(i));
1617  if (maxd > dv.ndims ())
1618  celldv.resize (maxd, 1);
1619  arraydv = celldv;
1620 
1621  OCTAVE_LOCAL_BUFFER_INIT (bool, sing, maxd, false);
1622 
1623  perm.clear (maxd, 1);
1624  for (int i = 0; i < dvl; i++)
1625  {
1626  int k = dimv(i) - 1;
1627  if (k < 0)
1628  error ("num2cell: dimension indices must be positive");
1629 
1630  if (i > 0 && k < dimv(i-1) - 1)
1631  error ("num2cell: dimension indices must be strictly increasing");
1632 
1633  sing[k] = true;
1634  perm(i) = k;
1635  }
1636 
1637  for (int k = 0, i = dvl; k < maxd; k++)
1638  if (! sing[k])
1639  perm(i++) = k;
1640 
1641  for (int i = 0; i < maxd; i++)
1642  if (sing[i])
1643  celldv(i) = 1;
1644  else
1645  arraydv(i) = 1;
1646 }
1647 
1648 template <typename NDA>
1649 static inline typename NDA::element_type
1650 do_num2cell_elem (const NDA& array, octave_idx_type i)
1651 { return array(i); }
1652 
1653 static inline Cell
1654 do_num2cell_elem (const Cell& array, octave_idx_type i)
1655 { return Cell (array(i)); }
1656 
1657 template <typename NDA>
1658 static Cell
1659 do_num2cell (const NDA& array, const Array<int>& dimv)
1660 {
1661  if (dimv.isempty ())
1662  {
1663  Cell retval (array.dims ());
1664  octave_idx_type nel = array.numel ();
1665  for (octave_idx_type i = 0; i < nel; i++)
1666  retval.xelem (i) = do_num2cell_elem (array, i);
1667 
1668  return retval;
1669  }
1670  else
1671  {
1672  dim_vector celldv, arraydv;
1673  Array<int> perm;
1674  do_num2cell_helper (array.dims (), dimv, celldv, arraydv, perm);
1675 
1676  NDA parray = array.permute (perm);
1677 
1678  octave_idx_type nela = arraydv.numel ();
1679  octave_idx_type nelc = celldv.numel ();
1680  parray = parray.reshape (dim_vector (nela, nelc));
1681 
1682  Cell retval (celldv);
1683  for (octave_idx_type i = 0; i < nelc; i++)
1684  {
1685  retval.xelem (i) = NDA (parray.column (i).reshape (arraydv));
1686  }
1687 
1688  return retval;
1689  }
1690 }
1691 
1692 // FIXME: this is a mess, but if a size method for the object exists,
1693 // we have to call it to get the size of the object instead of using the
1694 // internal dims method.
1695 
1696 static dim_vector
1697 get_object_dims (octave_value& obj)
1698 {
1700 
1701  Matrix m = obj.size ();
1702 
1703  int n = m.numel ();
1704 
1705  retval.resize (n);
1706 
1707  for (int i = 0; i < n; i++)
1708  retval(i) = m(i);
1709 
1710  return retval;
1711 }
1712 
1713 static Cell
1714 do_object2cell (const octave_value& obj, const Array<int>& dimv)
1715 {
1716  Cell retval;
1717 
1718  // FIXME: this copy is only needed because the octave_value::size
1719  // method is not const.
1720  octave_value array = obj;
1721 
1722  if (! dimv.isempty ())
1723  error ("num2cell (A, dim) not implemented for class objects");
1724 
1725  dim_vector dv = get_object_dims (array);
1726 
1727  retval.resize (dv);
1728 
1729  octave_value_list idx (1);
1730 
1731  for (octave_idx_type i = 0; i < dv.numel (); i++)
1732  {
1733  octave_quit ();
1734 
1735  idx(0) = double (i+1);
1736 
1737  retval.xelem (i) = array.single_subsref ("(", idx);
1738  }
1739 
1740  return retval;
1741 }
1742 
1743 DEFUN (num2cell, args, ,
1744  doc: /* -*- texinfo -*-
1745 @deftypefn {} {@var{C} =} num2cell (@var{A})
1746 @deftypefnx {} {@var{C} =} num2cell (@var{A}, @var{dim})
1747 Convert the numeric matrix @var{A} to a cell array.
1748 
1749 If @var{dim} is defined, the value @var{C} is of dimension 1 in this
1750 dimension and the elements of @var{A} are placed into @var{C} in slices.
1751 For example:
1752 
1753 @example
1754 @group
1755 num2cell ([1,2;3,4])
1756  @result{}
1757  @{
1758  [1,1] = 1
1759  [2,1] = 3
1760  [1,2] = 2
1761  [2,2] = 4
1762  @}
1763 num2cell ([1,2;3,4],1)
1764  @result{}
1765  @{
1766  [1,1] =
1767  1
1768  3
1769  [1,2] =
1770  2
1771  4
1772  @}
1773 @end group
1774 @end example
1775 
1776 @seealso{mat2cell}
1777 @end deftypefn */)
1778 {
1779  int nargin = args.length ();
1780 
1781  if (nargin < 1 || nargin > 2)
1782  print_usage ();
1783 
1785 
1786  octave_value array = args(0);
1787 
1788  Array<int> dimv;
1789  if (nargin > 1)
1790  dimv = args(1).int_vector_value (true);
1791 
1792  if (array.islogical ())
1793  retval = do_num2cell (array.bool_array_value (), dimv);
1794  else if (array.is_char_matrix ())
1795  retval = do_num2cell (array.char_array_value (), dimv);
1796  else if (array.isnumeric ())
1797  {
1798  if (array.isinteger ())
1799  {
1800  if (array.is_int8_type ())
1801  retval = do_num2cell (array.int8_array_value (), dimv);
1802  else if (array.is_int16_type ())
1803  retval = do_num2cell (array.int16_array_value (), dimv);
1804  else if (array.is_int32_type ())
1805  retval = do_num2cell (array.int32_array_value (), dimv);
1806  else if (array.is_int64_type ())
1807  retval = do_num2cell (array.int64_array_value (), dimv);
1808  else if (array.is_uint8_type ())
1809  retval = do_num2cell (array.uint8_array_value (), dimv);
1810  else if (array.is_uint16_type ())
1811  retval = do_num2cell (array.uint16_array_value (), dimv);
1812  else if (array.is_uint32_type ())
1813  retval = do_num2cell (array.uint32_array_value (), dimv);
1814  else if (array.is_uint64_type ())
1815  retval = do_num2cell (array.uint64_array_value (), dimv);
1816  }
1817  else if (array.iscomplex ())
1818  {
1819  if (array.is_single_type ())
1820  retval = do_num2cell (array.float_complex_array_value (), dimv);
1821  else
1822  retval = do_num2cell (array.complex_array_value (), dimv);
1823  }
1824  else
1825  {
1826  if (array.is_single_type ())
1827  retval = do_num2cell (array.float_array_value (), dimv);
1828  else
1829  retval = do_num2cell (array.array_value (), dimv);
1830  }
1831  }
1832  else if (array.isobject ())
1833  retval = do_object2cell (array, dimv);
1834  else if (array.isstruct ())
1835  retval = do_num2cell (array.map_value (), dimv);
1836  else if (array.iscell ())
1837  retval = do_num2cell (array.cell_value (), dimv);
1838  else
1839  err_wrong_type_arg ("num2cell", array);
1840 
1841  return retval;
1842 }
1843 
1844 /*
1845 %!assert (num2cell ([1,2;3,4]), {1,2;3,4})
1846 %!assert (num2cell ([1,2;3,4], 1), {[1;3],[2;4]})
1847 %!assert (num2cell ([1,2;3,4], 2), {[1,2];[3,4]})
1848 */
1849 
1850 static bool
1851 mat2cell_mismatch (const dim_vector& dv,
1852  const Array<octave_idx_type> *d, int nd)
1853 {
1854  for (int i = 0; i < nd; i++)
1855  {
1856  octave_idx_type s = 0;
1857  for (octave_idx_type j = 0; j < d[i].numel (); j++)
1858  s += d[i](j);
1859 
1860  octave_idx_type r = (i < dv.ndims () ? dv(i) : 1);
1861 
1862  if (s != r)
1863  error ("mat2cell: mismatch on dimension %d (%d != %d)", i+1, r, s);
1864  }
1865 
1866  return false;
1867 }
1868 
1869 template <typename container>
1870 static void
1871 prepare_idx (container *idx, int idim, int nd,
1872  const Array<octave_idx_type>* d)
1873 {
1874  octave_idx_type nidx = (idim < nd ? d[idim].numel () : 1);
1875  if (nidx == 1)
1876  idx[0] = idx_vector::colon;
1877  else
1878  {
1879  octave_idx_type l = 0;
1880  for (octave_idx_type i = 0; i < nidx; i++)
1881  {
1882  octave_idx_type u = l + d[idim](i);
1883  idx[i] = idx_vector (l, u);
1884  l = u;
1885  }
1886  }
1887 }
1888 
1889 // 2D specialization, works for Array, Sparse and octave_map.
1890 // Uses 1D or 2D indexing.
1891 
1892 template <typename Array2D>
1893 static Cell
1894 do_mat2cell_2d (const Array2D& a, const Array<octave_idx_type> *d, int nd)
1895 {
1897  assert (nd == 1 || nd == 2);
1898  assert (a.ndims () == 2);
1899 
1900  if (mat2cell_mismatch (a.dims (), d, nd))
1901  return retval;
1902 
1903  octave_idx_type nridx = d[0].numel ();
1904  octave_idx_type ncidx = (nd == 1 ? 1 : d[1].numel ());
1905  retval.clear (nridx, ncidx);
1906 
1907  int ivec = -1;
1908  if (a.rows () > 1 && a.cols () == 1 && ncidx == 1)
1909  ivec = 0;
1910  else if (a.rows () == 1 && nridx == 1 && nd == 2)
1911  ivec = 1;
1912 
1913  if (ivec >= 0)
1914  {
1915  // Vector split. Use 1D indexing.
1916  octave_idx_type l = 0;
1917  octave_idx_type nidx = (ivec == 0 ? nridx : ncidx);
1918  for (octave_idx_type i = 0; i < nidx; i++)
1919  {
1920  octave_idx_type u = l + d[ivec](i);
1921  retval(i) = a.index (idx_vector (l, u));
1922  l = u;
1923  }
1924  }
1925  else
1926  {
1927  // General 2D case. Use 2D indexing.
1928  OCTAVE_LOCAL_BUFFER (idx_vector, ridx, nridx);
1929  prepare_idx (ridx, 0, nd, d);
1930 
1931  OCTAVE_LOCAL_BUFFER (idx_vector, cidx, ncidx);
1932  prepare_idx (cidx, 1, nd, d);
1933 
1934  for (octave_idx_type j = 0; j < ncidx; j++)
1935  for (octave_idx_type i = 0; i < nridx; i++)
1936  {
1937  octave_quit ();
1938 
1939  retval(i,j) = a.index (ridx[i], cidx[j]);
1940  }
1941  }
1942 
1943  return retval;
1944 }
1945 
1946 // Nd case. Works for Arrays and octave_map.
1947 // Uses Nd indexing.
1948 
1949 template <typename ArrayND>
1950 Cell
1951 do_mat2cell_nd (const ArrayND& a, const Array<octave_idx_type> *d, int nd)
1952 {
1954  assert (nd >= 1);
1955 
1956  if (mat2cell_mismatch (a.dims (), d, nd))
1957  return retval;
1958 
1959  dim_vector rdv = dim_vector::alloc (nd);
1961  octave_idx_type idxtot = 0;
1962  for (int i = 0; i < nd; i++)
1963  {
1964  rdv(i) = nidx[i] = d[i].numel ();
1965  idxtot += nidx[i];
1966  }
1967 
1968  retval.clear (rdv);
1969 
1970  OCTAVE_LOCAL_BUFFER (idx_vector, xidx, idxtot);
1971  OCTAVE_LOCAL_BUFFER (idx_vector *, idx, nd);
1972 
1973  idxtot = 0;
1974  for (int i = 0; i < nd; i++)
1975  {
1976  idx[i] = xidx + idxtot;
1977  prepare_idx (idx[i], i, nd, d);
1978  idxtot += nidx[i];
1979  }
1980 
1983  (dim_vector (1, std::max (nd, a.ndims ())), idx_vector::colon);
1984 
1985  for (octave_idx_type j = 0; j < retval.numel (); j++)
1986  {
1987  octave_quit ();
1988 
1989  for (int i = 0; i < nd; i++)
1990  ra_idx(i) = idx[i][ridx[i]];
1991 
1992  retval(j) = a.index (ra_idx);
1993 
1994  rdv.increment_index (ridx);
1995  }
1996 
1997  return retval;
1998 }
1999 
2000 // Dispatcher.
2001 template <typename ArrayND>
2002 Cell
2003 do_mat2cell (const ArrayND& a, const Array<octave_idx_type> *d, int nd)
2004 {
2005  if (a.ndims () == 2 && nd <= 2)
2006  return do_mat2cell_2d (a, d, nd);
2007  else
2008  return do_mat2cell_nd (a, d, nd);
2009 }
2010 
2011 // General case. Works for any class supporting do_index_op.
2012 // Uses Nd indexing.
2013 
2014 Cell
2015 do_mat2cell (octave_value& a, const Array<octave_idx_type> *d, int nd)
2016 {
2018  assert (nd >= 1);
2019 
2020  if (mat2cell_mismatch (a.dims (), d, nd))
2021  return retval;
2022 
2023  dim_vector rdv = dim_vector::alloc (nd);
2025  octave_idx_type idxtot = 0;
2026  for (int i = 0; i < nd; i++)
2027  {
2028  rdv(i) = nidx[i] = d[i].numel ();
2029  idxtot += nidx[i];
2030  }
2031 
2032  retval.clear (rdv);
2033 
2034  OCTAVE_LOCAL_BUFFER (octave_value, xidx, idxtot);
2035  OCTAVE_LOCAL_BUFFER (octave_value *, idx, nd);
2036 
2037  idxtot = 0;
2038  for (int i = 0; i < nd; i++)
2039  {
2040  idx[i] = xidx + idxtot;
2041  prepare_idx (idx[i], i, nd, d);
2042  idxtot += nidx[i];
2043  }
2044 
2046  octave_value_list ra_idx (std::max (nd, a.ndims ()),
2048 
2049  for (octave_idx_type j = 0; j < retval.numel (); j++)
2050  {
2051  octave_quit ();
2052 
2053  for (int i = 0; i < nd; i++)
2054  ra_idx(i) = idx[i][ridx[i]];
2055 
2056  retval(j) = a.do_index_op (ra_idx);
2057 
2058  rdv.increment_index (ridx);
2059  }
2060 
2061  return retval;
2062 }
2063 
2064 DEFUN (mat2cell, args, ,
2065  doc: /* -*- texinfo -*-
2066 @deftypefn {} {@var{C} =} mat2cell (@var{A}, @var{m}, @var{n})
2067 @deftypefnx {} {@var{C} =} mat2cell (@var{A}, @var{d1}, @var{d2}, @dots{})
2068 @deftypefnx {} {@var{C} =} mat2cell (@var{A}, @var{r})
2069 Convert the matrix @var{A} to a cell array.
2070 
2071 If @var{A} is 2-D, then it is required that
2072 @code{sum (@var{m}) == size (@var{A}, 1)} and
2073 @code{sum (@var{n}) == size (@var{A}, 2)}. Similarly, if @var{A} is
2074 multi-dimensional and the number of dimensional arguments is equal to the
2075 dimensions of @var{A}, then it is required that
2076 @code{sum (@var{di}) == size (@var{A}, i)}.
2077 
2078 Given a single dimensional argument @var{r}, the other dimensional
2079 arguments are assumed to equal @code{size (@var{A},@var{i})}.
2080 
2081 An example of the use of mat2cell is
2082 
2083 @example
2084 mat2cell (reshape (1:16,4,4), [3,1], [3,1])
2085 @result{}
2086 @{
2087  [1,1] =
2088 
2089  1 5 9
2090  2 6 10
2091  3 7 11
2092 
2093  [2,1] =
2094 
2095  4 8 12
2096 
2097  [1,2] =
2098 
2099  13
2100  14
2101  15
2102 
2103  [2,2] = 16
2104 @}
2105 @end example
2106 @seealso{num2cell, cell2mat}
2107 @end deftypefn */)
2108 {
2109  int nargin = args.length ();
2110 
2111  if (nargin < 2)
2112  print_usage ();
2113 
2115 
2116  // Prepare indices.
2118 
2119  for (int i = 1; i < nargin; i++)
2120  d[i-1] = args(i).octave_idx_type_vector_value (true);
2121 
2122  octave_value a = args(0);
2123  bool sparse = a.issparse ();
2124  if (sparse && nargin > 3)
2125  error ("mat2cell: sparse arguments only support 2-D indexing");
2126 
2127  switch (a.builtin_type ())
2128  {
2129  case btyp_double:
2130  {
2131  if (sparse)
2132  retval = do_mat2cell_2d (a.sparse_matrix_value (), d, nargin-1);
2133  else
2134  retval = do_mat2cell (a.array_value (), d, nargin - 1);
2135  }
2136  break;
2137 
2138  case btyp_complex:
2139  {
2140  if (sparse)
2141  retval = do_mat2cell_2d (a.sparse_complex_matrix_value (), d,
2142  nargin-1);
2143  else
2144  retval = do_mat2cell (a.complex_array_value (), d, nargin - 1);
2145  }
2146  break;
2147 
2148 #define BTYP_BRANCH(X, Y) \
2149  case btyp_ ## X: \
2150  retval = do_mat2cell (a.Y ## _value (), d, nargin - 1); \
2151  break
2152 
2153  BTYP_BRANCH (float, float_array);
2154  BTYP_BRANCH (float_complex, float_complex_array);
2155  BTYP_BRANCH (bool, bool_array);
2156  BTYP_BRANCH (char, char_array);
2157 
2158  BTYP_BRANCH (int8, int8_array);
2159  BTYP_BRANCH (int16, int16_array);
2160  BTYP_BRANCH (int32, int32_array);
2161  BTYP_BRANCH (int64, int64_array);
2162  BTYP_BRANCH (uint8, uint8_array);
2163  BTYP_BRANCH (uint16, uint16_array);
2164  BTYP_BRANCH (uint32, uint32_array);
2165  BTYP_BRANCH (uint64, uint64_array);
2166 
2167  BTYP_BRANCH (cell, cell);
2168  BTYP_BRANCH (struct, map);
2169 
2170 #undef BTYP_BRANCH
2171 
2172  case btyp_func_handle:
2173  err_wrong_type_arg ("mat2cell", a);
2174  break;
2175 
2176  default:
2177  retval = do_mat2cell (a, d, nargin-1);
2178  break;
2179  }
2180 
2181  return retval;
2182 }
2183 
2184 /*
2185 %!test
2186 %! x = reshape (1:20, 5, 4);
2187 %! c = mat2cell (x, [3,2], [3,1]);
2188 %! assert (c, {[1,6,11;2,7,12;3,8,13],[16;17;18];[4,9,14;5,10,15],[19;20]});
2189 
2190 %!test
2191 %! x = "abcdefghij";
2192 %! c = mat2cell (x, 1, [0,4,2,0,4,0]);
2193 %! empty1by0str = resize ("", 1, 0);
2194 %! assert (c, {empty1by0str,"abcd","ef",empty1by0str,"ghij",empty1by0str});
2195 */
2196 
2197 // FIXME: it would be nice to allow ranges being handled without a conversion.
2198 template <typename NDA>
2199 static Cell
2200 do_cellslices_nda (const NDA& array,
2201  const Array<octave_idx_type>& lb,
2202  const Array<octave_idx_type>& ub,
2203  int dim = -1)
2204 {
2205  octave_idx_type n = lb.numel ();
2206  Cell retval (1, n);
2207  if (array.isvector () && (dim == -1
2208  || (dim == 0 && array.columns () == 1)
2209  || (dim == 1 && array.rows () == 1)))
2210  {
2211  for (octave_idx_type i = 0; i < n; i++)
2212  retval(i) = array.index (idx_vector (lb(i) - 1, ub(i)));
2213  }
2214  else
2215  {
2216  const dim_vector dv = array.dims ();
2217  int ndims = dv.ndims ();
2218  if (dim < 0)
2219  dim = dv.first_non_singleton ();
2220  ndims = std::max (ndims, dim + 1);
2221 
2223 
2224  for (octave_idx_type i = 0; i < n; i++)
2225  {
2226  idx(dim) = idx_vector (lb(i) - 1, ub(i));
2227  retval(i) = array.index (idx);
2228  }
2229  }
2230 
2231  return retval;
2232 }
2233 
2234 DEFUN (cellslices, args, ,
2235  doc: /* -*- texinfo -*-
2236 @deftypefn {} {@var{sl} =} cellslices (@var{x}, @var{lb}, @var{ub}, @var{dim})
2237 Given an array @var{x}, this function produces a cell array of slices from
2238 the array determined by the index vectors @var{lb}, @var{ub}, for lower and
2239 upper bounds, respectively.
2240 
2241 In other words, it is equivalent to the following code:
2242 
2243 @example
2244 @group
2245 n = length (lb);
2246 sl = cell (1, n);
2247 for i = 1:length (lb)
2248  sl@{i@} = x(:,@dots{},lb(i):ub(i),@dots{},:);
2249 endfor
2250 @end group
2251 @end example
2252 
2253 The position of the index is determined by @var{dim}. If not specified,
2254 slicing is done along the first non-singleton dimension.
2255 @seealso{cell2mat, cellindexmat, cellfun}
2256 @end deftypefn */)
2257 {
2258  int nargin = args.length ();
2259 
2260  if (nargin < 3 || nargin > 4)
2261  print_usage ();
2262 
2263  octave_value x = args(0);
2264  Array<octave_idx_type> lb = args(1).octave_idx_type_vector_value ();
2265  Array<octave_idx_type> ub = args(2).octave_idx_type_vector_value ();
2266  int dim = -1;
2267  if (nargin == 4)
2268  {
2269  dim = args(3).int_value () - 1;
2270  if (dim < 0)
2271  error ("cellslices: DIM must be a valid dimension");
2272  }
2273 
2274  if (lb.numel () != ub.numel ())
2275  error ("cellslices: the lengths of LB and UB must match");
2276 
2277  Cell retcell;
2278  if (! x.issparse () && x.is_matrix_type ())
2279  {
2280  // specialize for some dense arrays.
2281  if (x.islogical ())
2282  retcell = do_cellslices_nda (x.bool_array_value (),
2283  lb, ub, dim);
2284  else if (x.is_char_matrix ())
2285  retcell = do_cellslices_nda (x.char_array_value (),
2286  lb, ub, dim);
2287  else if (x.isinteger ())
2288  {
2289  if (x.is_int8_type ())
2290  retcell = do_cellslices_nda (x.int8_array_value (),
2291  lb, ub, dim);
2292  else if (x.is_int16_type ())
2293  retcell = do_cellslices_nda (x.int16_array_value (),
2294  lb, ub, dim);
2295  else if (x.is_int32_type ())
2296  retcell = do_cellslices_nda (x.int32_array_value (),
2297  lb, ub, dim);
2298  else if (x.is_int64_type ())
2299  retcell = do_cellslices_nda (x.int64_array_value (),
2300  lb, ub, dim);
2301  else if (x.is_uint8_type ())
2302  retcell = do_cellslices_nda (x.uint8_array_value (),
2303  lb, ub, dim);
2304  else if (x.is_uint16_type ())
2305  retcell = do_cellslices_nda (x.uint16_array_value (),
2306  lb, ub, dim);
2307  else if (x.is_uint32_type ())
2308  retcell = do_cellslices_nda (x.uint32_array_value (),
2309  lb, ub, dim);
2310  else if (x.is_uint64_type ())
2311  retcell = do_cellslices_nda (x.uint64_array_value (),
2312  lb, ub, dim);
2313  }
2314  else if (x.iscomplex ())
2315  {
2316  if (x.is_single_type ())
2317  retcell = do_cellslices_nda (x.float_complex_array_value (),
2318  lb, ub, dim);
2319  else
2320  retcell = do_cellslices_nda (x.complex_array_value (),
2321  lb, ub, dim);
2322  }
2323  else
2324  {
2325  if (x.is_single_type ())
2326  retcell = do_cellslices_nda (x.float_array_value (),
2327  lb, ub, dim);
2328  else
2329  retcell = do_cellslices_nda (x.array_value (),
2330  lb, ub, dim);
2331  }
2332  }
2333  else
2334  {
2335  // generic code.
2336  octave_idx_type n = lb.numel ();
2337  retcell = Cell (1, n);
2338  const dim_vector dv = x.dims ();
2339  int ndims = dv.ndims ();
2340  if (dim < 0)
2341  dim = dv.first_non_singleton ();
2342  ndims = std::max (ndims, dim + 1);
2344  for (octave_idx_type i = 0; i < n; i++)
2345  {
2346  idx(dim) = Range (lb(i), ub(i));
2347  retcell(i) = x.do_index_op (idx);
2348  }
2349  }
2350 
2351  return ovl (retcell);
2352 }
2353 
2354 /*
2355 %!test
2356 %! m = [1, 2, 3, 4; 5, 6, 7, 8; 9, 10, 11, 12];
2357 %! c = cellslices (m, [1, 2], [2, 3], 2);
2358 %! assert (c, {[1, 2; 5, 6; 9, 10], [2, 3; 6, 7; 10, 11]});
2359 */
2360 
2361 DEFUN (cellindexmat, args, ,
2362  doc: /* -*- texinfo -*-
2363 @deftypefn {} {@var{y} =} cellindexmat (@var{x}, @var{varargin})
2364 Perform indexing of matrices in a cell array.
2365 
2366 Given a cell array of matrices @var{x}, this function computes
2367 
2368 @example
2369 @group
2370 Y = cell (size (X));
2371 for i = 1:numel (X)
2372  Y@{i@} = X@{i@}(varargin@{1@}, varargin@{2@}, @dots{}, varargin@{N@});
2373 endfor
2374 @end group
2375 @end example
2376 
2377 The indexing arguments may be scalar (@code{2}), arrays (@code{[1, 3]}),
2378 ranges (@code{1:3}), or the colon operator (@qcode{":"}). However, the
2379 indexing keyword @code{end} is not available.
2380 @seealso{cellslices, cellfun}
2381 @end deftypefn */)
2382 {
2383  if (args.length () == 0)
2384  print_usage ();
2385 
2386  const Cell x = args(0).xcell_value ("cellindexmat: X must be a cell");
2387 
2388  NoAlias<Cell> y (x.dims ());
2389  octave_idx_type nel = x.numel ();
2390  octave_value_list idx = args.slice (1, args.length () - 1);
2391 
2392  for (octave_idx_type i = 0; i < nel; i++)
2393  {
2394  octave_quit ();
2395 
2396  octave_value tmp = x(i);
2397 
2398  y(i) = tmp.do_index_op (idx);
2399  }
2400 
2401  return octave_value (y);
2402 }
OCTINTERP_API octave_value_list feval(const std::string &name, const octave_value_list &args=octave_value_list(), int nargout=0)
octave_value find_function(const std::string &name, const octave_value_list &args=octave_value_list(), bool local_funcs=true)
Definition: symtab.cc:412
Definition: Cell.h:37
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:135
fname
Definition: load-save.cc:767
const octave_base_value const Array< octave_idx_type > & ra_idx
bool isempty(void) const
Definition: ov.h:529
#define OCTAVE_LOCAL_BUFFER_INIT(T, buf, size, value)
Definition: oct-locbuf.h:47
static void recover_from_exception(void)
bool islogical(void) const
Definition: ov.h:696
static const idx_vector colon
Definition: idx-vector.h:498
bool isempty(void) const
Definition: Array.h:565
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
octave_value_list slice(octave_idx_type offset, octave_idx_type len, bool tags=false) const
Definition: ovl.h:114
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
for large enough k
Definition: lu.cc:617
void resize(int n, int fill_value=0)
Definition: dim-vector.h:310
Definition: Range.h:33
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:53
void error(const char *fmt,...)
Definition: error.cc:578
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:442
bool is_defined(void) const
Definition: ov.h:523
T & elem(octave_idx_type n)
Definition: Array.h:488
u
Definition: lu.cc:138
int ndims(void) const
Definition: ov.h:478
s
Definition: file-io.cc:2729
i e
Definition: data.cc:2591
static void get_mapper_fun_options(octave::symbol_table &symtab, const octave_value_list &args, int &nargin, bool &uniform_output, octave_value &error_handler)
Definition: cellfun.cc:222
octave_value arg
Definition: pr-output.cc:3244
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
is the outputs are concatenated into a cell array(or cell arrays). For example endfunction cellfun("factorial", -1, 2, "ErrorHandler", @foo) esult
Definition: cellfun.cc:400
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:511
std::string unique_symbol_name(const std::string &basename)
Definition: variables.cc:498
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
then the function must return scalars which will be concatenated into the return array(s). If code
Definition: cellfun.cc:400
int buffer_error_messages
Definition: error.cc:112
nd deftypefn *std::string name
Definition: sysdep.cc:647
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
bool is_function_handle(void) const
Definition: ov.h:749
int increment_index(octave_idx_type *idx, int start=0) const
Increment a multi-dimensional index tuple, optionally starting from an offset position and return the...
Definition: dim-vector.h:504
bool valid_identifier(const char *s)
Definition: utils.cc:74
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:412
void error_with_id(const char *id, const char *fmt,...)
Definition: error.cc:623
returns the type of the matrix and caches it for future use Called with more than one the function will not attempt to guess the type if it is still unknown This is useful for debugging purposes The possible matrix types depend on whether the matrix is full or sparse
Definition: matrix_type.cc:120
int first_non_singleton(int def=0) const
Definition: dim-vector.h:475
dim_vector dims(void) const
Definition: ov.h:469
OCTINTERP_API std::string last_error_id(void)
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
octave_function * function_value(bool silent=false) const
std::string class_name(void) const
Definition: ov.h:1291
Definition: dMatrix.h:36
bool is_function(void) const
Definition: ov.h:758
the exceeded dimensions are set to if fewer subscripts than dimensions are the exceeding dimensions are merged into the final requested dimension For consider the following dims
Definition: sub2ind.cc:255
static dim_vector alloc(int n)
Definition: dim-vector.h:264
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:162
With real return the complex result
Definition: data.cc:3260
octave::unwind_protect frame
Definition: graphics.cc:12190
OCTINTERP_API std::string last_error_message(void)
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
bool isreal(void) const
Definition: ov.h:703
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:227
void clear(void)
Definition: Array.cc:86
octave_fcn_handle * fcn_handle_value(bool silent=false) const
This is a simple wrapper template that will subclass an Array<T> type or any later type derived from ...
Definition: Array.h:892
static octave_value_list try_cellfun_internal_ops(const octave_value_list &args, int nargin)
Definition: cellfun.cc:123
bool is_undefined(void) const
Definition: ov.h:526
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
#define BTYP_BRANCH(X, Y)
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:362
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:227
octave_map map(dims)
Matrix size(void)
Definition: ov.h:409
Cell cell_value(void) const
Definition: ovl.h:88
octave_function * extract_function(const octave_value &arg, const std::string &warn_for, const std::string &fname, const std::string &header, const std::string &trailer)
Definition: variables.cc:125
the element is set to zero In other the statement xample y
Definition: data.cc:5264
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:41
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:100
args.length() nargin
Definition: file-io.cc:589
for i
Definition: data.cc:5264
bool is_string(void) const
Definition: ov.h:577
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:295
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
octave_idx_type length(void) const
bool strncmpi(const T &str_a, const T &str_b, const typename T::size_type n)
True if the first N characters are the same, ignoring case.
Definition: oct-string.cc:165
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
dim_vector dv
Definition: sub2ind.cc:263
octave_value_list & prepend(const octave_value &val)
Definition: ovl.cc:65
bool isnumeric(void) const
Definition: ov.h:723
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x
bool is_inline_function(void) const
Definition: ov.h:755
static octave_value_list get_output_list(octave_idx_type count, octave_idx_type nargout, const octave_value_list &inputlist, octave_value &func, octave_value &error_handler)
Definition: cellfun.cc:68