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