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