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