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