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