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