cellfun.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2005-2012 Mohamed Kamoun
00004 Copyright (C) 2006-2012 Bill Denney
00005 Copyright (C) 2009 Jaroslav Hajek
00006 Copyright (C) 2010 VZLU Prague
00007 
00008 This file is part of Octave.
00009 
00010 Octave is free software; you can redistribute it and/or modify it
00011 under the terms of the GNU General Public License as published by the
00012 Free Software Foundation; either version 3 of the License, or (at your
00013 option) any later version.
00014 
00015 Octave is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018 for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with Octave; see the file COPYING.  If not, see
00022 <http://www.gnu.org/licenses/>.
00023 
00024 */
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029 
00030 #include <string>
00031 #include <vector>
00032 #include <list>
00033 #include <memory>
00034 
00035 #include "caseless-str.h"
00036 #include "lo-mappers.h"
00037 #include "oct-locbuf.h"
00038 
00039 #include "Cell.h"
00040 #include "oct-map.h"
00041 #include "defun-dld.h"
00042 #include "parse.h"
00043 #include "variables.h"
00044 #include "ov-colon.h"
00045 #include "unwind-prot.h"
00046 #include "gripes.h"
00047 #include "utils.h"
00048 
00049 #include "ov-class.h"
00050 #include "ov-scalar.h"
00051 #include "ov-float.h"
00052 #include "ov-complex.h"
00053 #include "ov-flt-complex.h"
00054 #include "ov-bool.h"
00055 #include "ov-int8.h"
00056 #include "ov-int16.h"
00057 #include "ov-int32.h"
00058 #include "ov-int64.h"
00059 #include "ov-uint8.h"
00060 #include "ov-uint16.h"
00061 #include "ov-uint32.h"
00062 #include "ov-uint64.h"
00063 
00064 #include "ov-fcn-handle.h"
00065 
00066 static octave_value_list
00067 get_output_list (octave_idx_type count, octave_idx_type nargout,
00068                  const octave_value_list& inputlist,
00069                  octave_value& func,
00070                  octave_value& error_handler)
00071 {
00072   octave_value_list tmp;
00073   try {
00074     tmp = func.do_multi_index_op (nargout, inputlist);
00075   }
00076   catch (octave_execution_exception) {
00077     if (error_handler.is_defined ())
00078       error_state = 1;
00079   }
00080 
00081   if (error_state)
00082     {
00083       if (error_handler.is_defined ())
00084         {
00085           octave_scalar_map msg;
00086           msg.assign ("identifier", last_error_id ());
00087           msg.assign ("message", last_error_message ());
00088           msg.assign ("index", static_cast<double> (count + static_cast<octave_idx_type>(1)));
00089 
00090           octave_value_list errlist = inputlist;
00091           errlist.prepend (msg);
00092 
00093           buffer_error_messages--;
00094 
00095           error_state = 0;
00096 
00097           tmp = error_handler.do_multi_index_op (nargout, errlist);
00098 
00099           buffer_error_messages++;
00100 
00101           if (error_state)
00102             tmp.clear ();
00103         }
00104       else
00105         tmp.clear ();
00106     }
00107 
00108   return tmp;
00109 }
00110 
00111 static octave_value_list
00112 try_cellfun_internal_ops (const octave_value_list& args, int nargin)
00113 {
00114   octave_value_list retval;
00115 
00116   std::string name = args(0).string_value ();
00117 
00118   const Cell f_args = args(1).cell_value ();
00119 
00120   octave_idx_type k = f_args.numel ();
00121 
00122   if (name == "isempty")
00123     {
00124       boolNDArray result (f_args.dims ());
00125       for (octave_idx_type count = 0; count < k; count++)
00126         result(count) = f_args.elem(count).is_empty ();
00127       retval(0) = result;
00128     }
00129   else if (name == "islogical")
00130     {
00131       boolNDArray result (f_args.dims ());
00132       for (octave_idx_type  count= 0; count < k; count++)
00133         result(count) = f_args.elem(count).is_bool_type ();
00134       retval(0) = result;
00135     }
00136   else if (name == "isreal")
00137     {
00138       boolNDArray result (f_args.dims ());
00139       for (octave_idx_type  count= 0; count < k; count++)
00140         result(count) = f_args.elem(count).is_real_type ();
00141       retval(0) = result;
00142     }
00143   else if (name == "length")
00144     {
00145       NDArray result (f_args.dims ());
00146       for (octave_idx_type  count= 0; count < k; count++)
00147         result(count) = static_cast<double> (f_args.elem(count).length ());
00148       retval(0) = result;
00149     }
00150   else if (name == "ndims")
00151     {
00152       NDArray result (f_args.dims ());
00153       for (octave_idx_type count = 0; count < k; count++)
00154         result(count) = static_cast<double> (f_args.elem(count).ndims ());
00155       retval(0) = result;
00156     }
00157   else if (name == "prodofsize" || name == "numel")
00158     {
00159       NDArray result (f_args.dims ());
00160       for (octave_idx_type count = 0; count < k; count++)
00161         result(count) = static_cast<double> (f_args.elem(count).numel ());
00162       retval(0) = result;
00163     }
00164   else if (name == "size")
00165     {
00166       if (nargin == 3)
00167         {
00168           int d = args(2).nint_value () - 1;
00169 
00170           if (d < 0)
00171             error ("cellfun: K must be a positive integer");
00172 
00173           if (! error_state)
00174             {
00175               NDArray result (f_args.dims ());
00176               for (octave_idx_type count = 0; count < k; count++)
00177                 {
00178                   dim_vector dv = f_args.elem(count).dims ();
00179                   if (d < dv.length ())
00180                     result(count) = static_cast<double> (dv(d));
00181                   else
00182                     result(count) = 1.0;
00183                 }
00184               retval(0) = result;
00185             }
00186         }
00187       else
00188         error ("cellfun: not enough arguments for \"size\"");
00189     }
00190   else if (name == "isclass")
00191     {
00192       if (nargin == 3)
00193         {
00194           std::string class_name = args(2).string_value();
00195           boolNDArray result (f_args.dims ());
00196           for (octave_idx_type count = 0; count < k; count++)
00197             result(count) = (f_args.elem(count).class_name() == class_name);
00198 
00199           retval(0) = result;
00200         }
00201       else
00202         error ("cellfun: not enough arguments for \"isclass\"");
00203     }
00204 
00205   return retval;
00206 }
00207 
00208 static void
00209 get_mapper_fun_options (const octave_value_list& args, int& nargin,
00210                         bool& uniform_output, octave_value& error_handler)
00211 {
00212   while (nargin > 3 && args(nargin-2).is_string ())
00213     {
00214       caseless_str arg = args(nargin-2).string_value ();
00215 
00216       size_t compare_len = std::max (arg.length (), static_cast<size_t> (2));
00217 
00218       if (arg.compare ("uniformoutput", compare_len))
00219         uniform_output = args(nargin-1).bool_value();
00220       else if (arg.compare ("errorhandler", compare_len))
00221         {
00222           if (args(nargin-1).is_function_handle ()
00223               || args(nargin-1).is_inline_function ())
00224             {
00225               error_handler = args(nargin-1);
00226             }
00227           else if (args(nargin-1).is_string ())
00228             {
00229               std::string err_name = args(nargin-1).string_value ();
00230 
00231               error_handler = symbol_table::find_function (err_name);
00232 
00233               if (error_handler.is_undefined ())
00234                 {
00235                   error ("cellfun: invalid function NAME: %s",
00236                          err_name.c_str ());
00237                   break;
00238                 }
00239             }
00240           else
00241             {
00242               error ("cellfun: invalid value for 'ErrorHandler' function");
00243               break;
00244             }
00245         }
00246       else
00247         {
00248           error ("cellfun: unrecognized parameter %s",
00249                  arg.c_str());
00250           break;
00251         }
00252 
00253       nargin -= 2;
00254     }
00255 
00256   nargin -= 1;
00257 }
00258 
00259 DEFUN_DLD (cellfun, args, nargout,
00260   "-*- texinfo -*-\n\
00261 @deftypefn  {Loadable Function} {} cellfun (@var{name}, @var{C})\n\
00262 @deftypefnx {Loadable Function} {} cellfun (\"size\", @var{C}, @var{k})\n\
00263 @deftypefnx {Loadable Function} {} cellfun (\"isclass\", @var{C}, @var{class})\n\
00264 @deftypefnx {Loadable Function} {} cellfun (@var{func}, @var{C})\n\
00265 @deftypefnx {Loadable Function} {} cellfun (@var{func}, @var{C}, @var{D})\n\
00266 @deftypefnx {Loadable Function} {[@var{a}, @dots{}] =} cellfun (@dots{})\n\
00267 @deftypefnx {Loadable Function} {} cellfun (@dots{}, 'ErrorHandler', @var{errfunc})\n\
00268 @deftypefnx {Loadable Function} {} cellfun (@dots{}, 'UniformOutput', @var{val})\n\
00269 \n\
00270 Evaluate the function named @var{name} on the elements of the cell array\n\
00271 @var{C}.  Elements in @var{C} are passed on to the named function\n\
00272 individually.  The function @var{name} can be one of the functions\n\
00273 \n\
00274 @table @code\n\
00275 @item isempty\n\
00276 Return 1 for empty elements.\n\
00277 \n\
00278 @item islogical\n\
00279 Return 1 for logical elements.\n\
00280 \n\
00281 @item isreal\n\
00282 Return 1 for real elements.\n\
00283 \n\
00284 @item length\n\
00285 Return a vector of the lengths of cell elements.\n\
00286 \n\
00287 @item ndims\n\
00288 Return the number of dimensions of each element.\n\
00289 \n\
00290 @item numel\n\
00291 @itemx prodofsize\n\
00292 Return the number of elements contained within each cell element.  The\n\
00293 number is the product of the dimensions of the object at each cell element.\n\
00294 \n\
00295 @item size\n\
00296 Return the size along the @var{k}-th dimension.\n\
00297 \n\
00298 @item isclass\n\
00299 Return 1 for elements of @var{class}.\n\
00300 @end table\n\
00301 \n\
00302 Additionally, @code{cellfun} accepts an arbitrary function @var{func}\n\
00303 in the form of an inline function, function handle, or the name of a\n\
00304 function (in a character string).  In the case of a character string\n\
00305 argument, the function must accept a single argument named @var{x}, and\n\
00306 it must return a string value.  The function can take one or more arguments,\n\
00307 with the inputs arguments given by @var{C}, @var{D}, etc.  Equally the\n\
00308 function can return one or more output arguments.  For example:\n\
00309 \n\
00310 @example\n\
00311 @group\n\
00312 cellfun (\"atan2\", @{1, 0@}, @{0, 1@})\n\
00313      @result{}ans = [1.57080   0.00000]\n\
00314 @end group\n\
00315 @end example\n\
00316 \n\
00317 The number of output arguments of @code{cellfun} matches the number of output\n\
00318 arguments of the function.  The outputs of the function will be collected\n\
00319 into the output arguments of @code{cellfun} like this:\n\
00320 \n\
00321 @example\n\
00322 @group\n\
00323 function [a, b] = twoouts (x)\n\
00324   a = x;\n\
00325   b = x*x;\n\
00326 endfunction\n\
00327 [aa, bb] = cellfun(@@twoouts, @{1, 2, 3@})\n\
00328      @result{}\n\
00329         aa =\n\
00330            1 2 3\n\
00331         bb =\n\
00332            1 4 9\n\
00333 @end group\n\
00334 @end example\n\
00335 \n\
00336 Note that per default the output argument(s) are arrays of the same size as\n\
00337 the input arguments.  Input arguments that are singleton (1x1) cells will be\n\
00338 automatically expanded to the size of the other arguments.\n\
00339 \n\
00340 If the parameter 'UniformOutput' is set to true (the default), then the\n\
00341 function must return scalars which will be concatenated into the return\n\
00342 array(s).  If 'UniformOutput' is false, the outputs are concatenated into a\n\
00343 cell array (or cell arrays).  For example:\n\
00344 \n\
00345 @example\n\
00346 @group\n\
00347 cellfun (\"tolower\", @{\"Foo\", \"Bar\", \"FooBar\"@},\n\
00348          \"UniformOutput\",false)\n\
00349 @result{} ans = @{\"foo\", \"bar\", \"foobar\"@}\n\
00350 @end group\n\
00351 @end example\n\
00352 \n\
00353 Given the parameter 'ErrorHandler', then @var{errfunc} defines a function to\n\
00354 call in case @var{func} generates an error.  The form of the function is\n\
00355 \n\
00356 @example\n\
00357 function [@dots{}] = errfunc (@var{s}, @dots{})\n\
00358 @end example\n\
00359 \n\
00360 @noindent\n\
00361 where there is an additional input argument to @var{errfunc} relative to\n\
00362 @var{func}, given by @var{s}.  This is a structure with the elements\n\
00363 'identifier', 'message' and 'index', giving respectively the error\n\
00364 identifier, the error message, and the index into the input arguments\n\
00365 of the element that caused the error.  For example:\n\
00366 \n\
00367 @example\n\
00368 @group\n\
00369 function y = foo (s, x), y = NaN; endfunction\n\
00370 cellfun (\"factorial\", @{-1,2@}, 'ErrorHandler', @@foo)\n\
00371 @result{} ans = [NaN 2]\n\
00372 @end group\n\
00373 @end example\n\
00374 \n\
00375 Use @code{cellfun} intelligently.  The @code{cellfun} function is a\n\
00376 useful tool for avoiding loops.  It is often used with anonymous\n\
00377 function handles; however, calling an anonymous function involves an\n\
00378 overhead quite comparable to the overhead of an m-file function.\n\
00379 Passing a handle to a built-in function is faster, because the\n\
00380 interpreter is not involved in the internal loop.  For example:\n\
00381 \n\
00382 @example\n\
00383 @group\n\
00384 a = @{@dots{}@}\n\
00385 v = cellfun (@@(x) det(x), a); # compute determinants\n\
00386 v = cellfun (@@det, a); # faster\n\
00387 @end group\n\
00388 @end example\n\
00389 \n\
00390 @seealso{arrayfun, structfun, spfun}\n\
00391 @end deftypefn")
00392 {
00393   octave_value_list retval;
00394   int nargin = args.length ();
00395   int nargout1 = (nargout < 1 ? 1 : nargout);
00396 
00397   if (nargin < 2)
00398     {
00399       error ("cellfun: function requires at least 2 arguments");
00400       print_usage ();
00401       return retval;
00402     }
00403 
00404   octave_value func = args(0);
00405 
00406   if (! args(1).is_cell ())
00407     {
00408       error ("cellfun: C must be a cell array");
00409 
00410       return retval;
00411     }
00412 
00413   if (func.is_string ())
00414     {
00415       retval = try_cellfun_internal_ops (args, nargin);
00416 
00417       if (error_state || ! retval.empty ())
00418         return retval;
00419 
00420       // See if we can convert the string into a function.
00421 
00422       std::string name = args(0).string_value ();
00423 
00424       if (! valid_identifier (name))
00425         {
00426           std::string fcn_name = unique_symbol_name ("__cellfun_fcn_");
00427           std::string fname = "function y = " + fcn_name + "(x) y = ";
00428 
00429           octave_function *ptr_func
00430             = extract_function (args(0), "cellfun", fcn_name,
00431                                 fname, "; endfunction");
00432 
00433           if (ptr_func && ! error_state)
00434             func = octave_value (ptr_func, true);
00435         }
00436       else
00437         {
00438           func = symbol_table::find_function (name);
00439 
00440           if (func.is_undefined ())
00441             error ("cellfun: invalid function NAME: %s", name.c_str ());
00442         }
00443 
00444       if (error_state || ! retval.empty ())
00445         return retval;
00446     }
00447 
00448   if (func.is_function_handle () || func.is_inline_function ()
00449       || func.is_function ())
00450     {
00451 
00452       // The following is an optimisation because the symbol table can
00453       // give a more specific function class, so this can result in
00454       // fewer polymorphic function calls as the function gets called
00455       // for each value of the array.
00456       {
00457         if (func.is_function_handle ())
00458           {
00459             octave_fcn_handle* f = func.fcn_handle_value ();
00460 
00461             // Overloaded function handles need to check the type of the
00462             // arguments for each element of the array, so they cannot
00463             // be optimised this way.
00464             if (f -> is_overloaded ())
00465               goto nevermind;
00466           }
00467 
00468         std::string name = func.function_value () -> name ();
00469         octave_value f = symbol_table::find_function (name);
00470 
00471         if (f.is_defined ())
00472           {
00473             //Except for these two which are special cases...
00474             if (name != "size" && name != "class")
00475               {
00476                 //Try first the optimised code path for built-in functions
00477                 octave_value_list tmp_args = args;
00478                 tmp_args(0) = name;
00479                 retval = try_cellfun_internal_ops (tmp_args, nargin);
00480                 if (error_state || ! retval.empty ())
00481                   return retval;
00482               }
00483 
00484             //Okay, we tried, doesn't work, let's do the best we can
00485             //instead and avoid polymorphic calls for each element of
00486             //the array.
00487             func = f;
00488           }
00489       }
00490     nevermind:
00491 
00492       bool uniform_output = true;
00493       octave_value error_handler;
00494 
00495       get_mapper_fun_options (args, nargin, uniform_output, error_handler);
00496 
00497       if (error_state)
00498         return octave_value_list ();
00499 
00500       // Extract cell arguments.
00501 
00502       octave_value_list inputlist (nargin, octave_value ());
00503 
00504       OCTAVE_LOCAL_BUFFER (Cell, inputs, nargin);
00505       OCTAVE_LOCAL_BUFFER (bool, mask, nargin);
00506 
00507       // This is to prevent copy-on-write.
00508       const Cell *cinputs = inputs;
00509 
00510       octave_idx_type k = 1;
00511 
00512       dim_vector fdims (1, 1);
00513 
00514       // Collect arguments.  Pre-fill scalar elements of inputlist
00515       // array.
00516 
00517       for (int j = 0; j < nargin; j++)
00518         {
00519           if (! args(j+1).is_cell ())
00520             {
00521               error ("cellfun: arguments must be cells");
00522               return octave_value_list ();
00523             }
00524 
00525           inputs[j] = args(j+1).cell_value ();
00526           mask[j] = inputs[j].numel () != 1;
00527           if (! mask[j])
00528             inputlist(j) = cinputs[j](0);
00529         }
00530 
00531       for (int j = 0; j < nargin; j++)
00532         {
00533           if (mask[j])
00534             {
00535               fdims = inputs[j].dims ();
00536               k = inputs[j].numel ();
00537               for (int i = j+1; i < nargin; i++)
00538                 {
00539                   if (mask[i] && inputs[i].dims () != fdims)
00540                     {
00541                       error ("cellfun: dimensions mismatch");
00542                       return octave_value_list ();
00543                     }
00544                 }
00545               break;
00546             }
00547         }
00548 
00549       unwind_protect frame;
00550       frame.protect_var (buffer_error_messages);
00551 
00552       if (error_handler.is_defined ())
00553         buffer_error_messages++;
00554 
00555       // Apply functions.
00556 
00557       if (uniform_output)
00558         {
00559           std::list<octave_value_list> idx_list (1);
00560           idx_list.front ().resize (1);
00561           std::string idx_type = "(";
00562 
00563           OCTAVE_LOCAL_BUFFER (octave_value, retv, nargout1);
00564 
00565           for (octave_idx_type count = 0; count < k; count++)
00566             {
00567               for (int j = 0; j < nargin; j++)
00568                 {
00569                   if (mask[j])
00570                     inputlist.xelem (j) = cinputs[j](count);
00571                 }
00572 
00573               const octave_value_list tmp
00574                 = get_output_list (count, nargout, inputlist, func,
00575                                    error_handler);
00576 
00577               if (error_state)
00578                 return retval;
00579 
00580               if (nargout > 0 && tmp.length () < nargout)
00581                 {
00582                   error ("cellfun: function returned fewer than nargout values");
00583                   return retval;
00584                 }
00585 
00586               if  (nargout > 0
00587                    || (nargout == 0
00588                        && tmp.length () > 0 && tmp(0).is_defined ()))
00589                 {
00590                   int num_to_copy = tmp.length ();
00591 
00592                   if (num_to_copy > nargout1)
00593                     num_to_copy = nargout1;
00594 
00595                   if (count == 0)
00596                     {
00597                       for (int j = 0; j < num_to_copy; j++)
00598                         {
00599                           if (tmp(j).is_defined ())
00600                             {
00601                               octave_value val = tmp(j);
00602 
00603                               if (val.numel () == 1)
00604                                 retv[j] = val.resize (fdims);
00605                               else
00606                                 {
00607                                   error ("cellfun: all values must be scalars when UniformOutput = true");
00608                                   break;
00609                                 }
00610                             }
00611                         }
00612                     }
00613                   else
00614                     {
00615                       for (int j = 0; j < num_to_copy; j++)
00616                         {
00617                           if (tmp(j).is_defined ())
00618                             {
00619                               octave_value val = tmp(j);
00620 
00621                               if (! retv[j].fast_elem_insert (count, val))
00622                                 {
00623                                   if (val.numel () == 1)
00624                                     {
00625                                       idx_list.front ()(0) = count + 1.0;
00626                                       retv[j].assign (octave_value::op_asn_eq,
00627                                                       idx_type, idx_list, val);
00628 
00629                                       if (error_state)
00630                                         break;
00631                                     }
00632                                   else
00633                                     {
00634                                       error ("cellfun: all values must be scalars when UniformOutput = true");
00635                                       break;
00636                                     }
00637                                 }
00638                             }
00639                         }
00640                     }
00641                 }
00642 
00643               if (error_state)
00644                 break;
00645             }
00646 
00647           retval.resize (nargout1);
00648 
00649           for (int j = 0; j < nargout1; j++)
00650             {
00651               if (nargout > 0 && retv[j].is_undefined ())
00652                 retval(j) = NDArray (fdims);
00653               else
00654                 retval(j) = retv[j];
00655             }
00656         }
00657       else
00658         {
00659           OCTAVE_LOCAL_BUFFER (Cell, results, nargout1);
00660 
00661           for (int j = 0; j < nargout1; j++)
00662             results[j].resize (fdims, Matrix ());
00663 
00664           bool have_some_output = false;
00665 
00666           for (octave_idx_type count = 0; count < k; count++)
00667             {
00668               for (int j = 0; j < nargin; j++)
00669                 {
00670                   if (mask[j])
00671                     inputlist.xelem (j) = cinputs[j](count);
00672                 }
00673 
00674               const octave_value_list tmp
00675                 = get_output_list (count, nargout, inputlist, func,
00676                                    error_handler);
00677 
00678               if (error_state)
00679                 return retval;
00680 
00681               if (nargout > 0 && tmp.length () < nargout)
00682                 {
00683                   error ("cellfun: function returned fewer than nargout values");
00684                   return retval;
00685                 }
00686 
00687               if  (nargout > 0
00688                    || (nargout == 0
00689                        && tmp.length () > 0 && tmp(0).is_defined ()))
00690                 {
00691                   int num_to_copy = tmp.length ();
00692 
00693                   if (num_to_copy > nargout1)
00694                     num_to_copy = nargout1;
00695 
00696                   if (num_to_copy > 0)
00697                     have_some_output = true;
00698 
00699                   for (int j = 0; j < num_to_copy; j++)
00700                     results[j](count) = tmp(j);
00701                 }
00702             }
00703 
00704           if (have_some_output || fdims.any_zero ())
00705             {
00706               retval.resize (nargout1);
00707 
00708               for (int j = 0; j < nargout1; j++)
00709                 retval(j) = results[j];
00710             }
00711         }
00712     }
00713   else
00714     error ("cellfun: argument NAME must be a string or function handle");
00715 
00716   return retval;
00717 }
00718 
00719 /*
00720 
00721 %!function r = __f11 (x)
00722 %!  global __cellfun_test_num_outputs__
00723 %!  __cellfun_test_num_outputs__ = nargout;
00724 %!  r = x;
00725 %!endfunction
00726 
00727 %!function __f01 (x)
00728 %!  global __cellfun_test_num_outputs__
00729 %!  __cellfun_test_num_outputs__ = nargout;
00730 %!endfunction
00731 
00732 %!test
00733 %! global __cellfun_test_num_outputs__
00734 %! cellfun (@__f11, {1});
00735 %! assert (__cellfun_test_num_outputs__, 0)
00736 %! x = cellfun (@__f11, {1});
00737 %! assert (__cellfun_test_num_outputs__, 1)
00738 
00739 %!test
00740 %! global __cellfun_test_num_outputs__
00741 %! cellfun (@__f01, {1});
00742 %! assert (__cellfun_test_num_outputs__, 0)
00743 
00744 %!error x = cellfun (@__f01, {1, 2});
00745 
00746 %!test
00747 %! assert (cellfun (@__f11, {1, 2}), [1, 2])
00748 %! assert (cellfun (@__f11, {1, 2}, 'uniformoutput', false), {1, 2})
00749 
00750 %!test
00751 %!  [a,b] = cellfun (@(x) x, cell (2, 0));
00752 %!  assert (a, zeros (2, 0));
00753 %!  assert (b, zeros (2, 0));
00754 
00755 %!test
00756 %!  [a,b] = cellfun (@(x) x, cell (2, 0), "uniformoutput", false);
00757 %!  assert (a, cell (2, 0));
00758 %!  assert (b, cell (2, 0));
00759 
00760 %% Test function to check the "Errorhandler" option
00761 %!function [z] = __cellfunerror (S, varargin)
00762 %!  z = S;
00763 %!endfunction
00764 
00765 %% First input argument can be a string, an inline function,
00766 %% a function_handle or an anonymous function
00767 %!test
00768 %!  A = cellfun ("islogical", {true, 0.1, false, i*2});
00769 %!  assert (A, [true, false, true, false]);
00770 %!test
00771 %!  A = cellfun (inline ("islogical (x)", "x"), {true, 0.1, false, i*2});
00772 %!  assert (A, [true, false, true, false]);
00773 %!test
00774 %!  A = cellfun (@islogical, {true, 0.1, false, i*2});
00775 %!  assert (A, [true, false, true, false]);
00776 %!test
00777 %!  A = cellfun (@(x) islogical(x), {true, 0.1, false, i*2});
00778 %!  assert (A, [true, false, true, false]);
00779 
00780 %% First input argument can be the special string "isreal",
00781 %% "isempty", "islogical", "length", "ndims" or "prodofsize"
00782 %!test
00783 %!  A = cellfun ("isreal", {true, 0.1, {}, i*2, [], "abc"});
00784 %!  assert (A, [true, true, false, false, true, true]);
00785 %!test
00786 %!  A = cellfun ("isempty", {true, 0.1, false, i*2, [], "abc"});
00787 %!  assert (A, [false, false, false, false, true, false]);
00788 %!test
00789 %!  A = cellfun ("islogical", {true, 0.1, false, i*2, [], "abc"});
00790 %!  assert (A, [true, false, true, false, false, false]);
00791 %!test
00792 %!  A = cellfun ("length", {true, 0.1, false, i*2, [], "abc"});
00793 %!  assert (A, [1, 1, 1, 1, 0, 3]);
00794 %!test
00795 %!  A = cellfun ("ndims", {[1, 2; 3, 4]; (cell (1,2,3,4))});
00796 %!  assert (A, [2; 4]);
00797 %!test
00798 %!  A = cellfun ("prodofsize", {[1, 2; 3, 4], (cell (1,2,3,4))});
00799 %!  assert (A, [4, 24]);
00800 
00801 %% Number of input and output arguments may not be limited to one
00802 %!test
00803 %!  A = cellfun (@(x,y,z) x + y + z, {1, 1, 1}, {2, 2, 2}, {3, 4, 5});
00804 %!  assert (A, [6, 7, 8]);
00805 %!test
00806 %!  A = cellfun (@(x,y,z) x + y + z, {1, 1, 1}, {2, 2, 2}, {3, 4, 5}, \
00807 %!    "UniformOutput", false);
00808 %!  assert (A, {6, 7, 8});
00809 %!test %% Two input arguments of different types
00810 %!  A = cellfun (@(x,y) islogical (x) && ischar (y), {false, true}, {"a", 3});
00811 %!  assert (A, [true, false]);
00812 %!test %% Pass another variable to the anonymous function
00813 %!  y = true; A = cellfun (@(x) islogical (x) && y, {false, 0.3});
00814 %!  assert (A, [true, false]);
00815 %!test %% Three ouptut arguments of different type
00816 %!  [A, B, C] = cellfun (@find, {10, 11; 0, 12}, "UniformOutput", false);
00817 %!  assert (isequal (A, {true, true; [], true}));
00818 %!  assert (isequal (B, {true, true; [], true}));
00819 %!  assert (isequal (C, {10, 11; [], 12}));
00820 
00821 %% Input arguments can be of type cell array of logical
00822 %!test
00823 %!  A = cellfun (@(x,y) x == y, {false, true}, {true, true});
00824 %!  assert (A, [false, true]);
00825 %!test
00826 %!  A = cellfun (@(x,y) x == y, {false; true}, {true; true}, \
00827 %!    "UniformOutput", true);
00828 %!  assert (A, [false; true]);
00829 %!test
00830 %!  A = cellfun (@(x) x, {false, true; false, true}, "UniformOutput", false);
00831 %!  assert (A, {false, true; false, true});
00832 %!test %% Three ouptut arguments of same type
00833 %!  [A, B, C] = cellfun (@find, {true, false; false, true}, \
00834 %!    "UniformOutput", false);
00835 %!  assert (isequal (A, {true, []; [], true}));
00836 %!  assert (isequal (B, {true, []; [], true}));
00837 %!  assert (isequal (C, {true, []; [], true}));
00838 %!test
00839 %!  A = cellfun (@(x,y) cell2str (x,y), {true}, {true}, \
00840 %!    "ErrorHandler", @__cellfunerror);
00841 %!  assert (isfield (A, "identifier"), true);
00842 %!  assert (isfield (A, "message"), true);
00843 %!  assert (isfield (A, "index"), true);
00844 %!  assert (isempty (A.message), false);
00845 %!  assert (A.index, 1);
00846 %!test %% Overwriting setting of "UniformOutput" true
00847 %!  A = cellfun (@(x,y) cell2str (x,y), {true}, {true}, \
00848 %!    "UniformOutput", true, "ErrorHandler", @__cellfunerror);
00849 %!  assert (isfield (A, "identifier"), true);
00850 %!  assert (isfield (A, "message"), true);
00851 %!  assert (isfield (A, "index"), true);
00852 %!  assert (isempty (A.message), false);
00853 %!  assert (A.index, 1);
00854 
00855 %% Input arguments can be of type cell array of numeric
00856 %!test
00857 %!  A = cellfun (@(x,y) x>y, {1.1, 4.2}, {3.1, 2+3*i});
00858 %!  assert (A, [false, true]);
00859 %!test
00860 %!  A = cellfun (@(x,y) x>y, {1.1, 4.2; 2, 4}, {3.1, 2; 2, 4+2*i}, \
00861 %!    "UniformOutput", true);
00862 %!  assert (A, [false, true; false, false]);
00863 %!test
00864 %!  A = cellfun (@(x,y) x:y, {1.1, 4}, {3.1, 6}, "UniformOutput", false);
00865 %!  assert (isequal (A{1}, [1.1, 2.1, 3.1]));
00866 %!  assert (isequal (A{2}, [4, 5, 6]));
00867 %!test %% Three ouptut arguments of different type
00868 %!  [A, B, C] = cellfun (@find, {10, 11; 0, 12}, "UniformOutput", false);
00869 %!  assert (isequal (A, {true, true; [], true}));
00870 %!  assert (isequal (B, {true, true; [], true}));
00871 %!  assert (isequal (C, {10, 11; [], 12}));
00872 %!test
00873 %!  A = cellfun (@(x,y) cell2str(x,y), {1.1, 4}, {3.1, 6}, \
00874 %!    "ErrorHandler", @__cellfunerror);
00875 %!  B = isfield (A(1), "message") && isfield (A(1), "index");
00876 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
00877 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
00878 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
00879 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
00880 %!  assert ([A(1).index, A(2).index], [1, 2]);
00881 %!test %% Overwriting setting of "UniformOutput" true
00882 %!  A = cellfun (@(x,y) cell2str(x,y), {1.1, 4}, {3.1, 6}, \
00883 %!    "UniformOutput", true, "ErrorHandler", @__cellfunerror);
00884 %!  B = isfield (A(1), "message") && isfield (A(1), "index");
00885 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
00886 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
00887 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
00888 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
00889 %!  assert ([A(1).index, A(2).index], [1, 2]);
00890 
00891 %% Input arguments can be of type cell arrays of character or strings
00892 %!error %% "UniformOutput" false should be used
00893 %!  A = cellfun (@(x,y) x>y, {"ad", "c", "ghi"}, {"cc", "d", "fgh"});
00894 %!test
00895 %!  A = cellfun (@(x,y) x>y, {"a"; "f"}, {"c"; "d"}, "UniformOutput", true);
00896 %!  assert (A, [false; true]);
00897 %!test
00898 %!  A = cellfun (@(x,y) x:y, {"a", "d"}, {"c", "f"}, "UniformOutput", false);
00899 %!  assert (A, {"abc", "def"});
00900 %!test
00901 %!  A = cellfun (@(x,y) cell2str(x,y), {"a", "d"}, {"c", "f"}, \
00902 %!    "ErrorHandler", @__cellfunerror);
00903 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
00904 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
00905 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
00906 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
00907 %!  assert ([A(1).index, A(2).index], [1, 2]);
00908 %!test %% Overwriting setting of "UniformOutput" true
00909 %!  A = cellfun (@(x,y) cell2str(x,y), {"a", "d"}, {"c", "f"}, \
00910 %!    "UniformOutput", true, "ErrorHandler", @__cellfunerror);
00911 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
00912 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
00913 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
00914 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
00915 %!  assert ([A(1).index, A(2).index], [1, 2]);
00916 
00917 %% Structures cannot be handled by cellfun
00918 %!error
00919 %!  vst1.a = 1.1; vst1.b = 4.2; vst2.a = 3.1; vst2.b = 2;
00920 %!  A = cellfun (@(x,y) (x.a < y.a) && (x.b > y.b), vst1, vst2);
00921 
00922 %% Input arguments can be of type cell array of cell arrays
00923 %!test
00924 %!  A = cellfun (@(x,y) x{1} < y{1}, {{1.1}, {4.2}}, {{3.1}, {2}});
00925 %!  assert (A, [1, 0], 1e-16);
00926 %!test
00927 %!  A = cellfun (@(x,y) x{1} < y{1}, {{1.1}; {4.2}}, {{3.1}; {2}}, \
00928 %!    "UniformOutput", true);
00929 %!  assert (A, [1; 0], 1e-16);
00930 %!test
00931 %!  A = cellfun (@(x,y) x{1} < y{1}, {{1.1}, {4.2}}, {{3.1}, {2}}, \
00932 %!    "UniformOutput", false);
00933 %!  assert (A, {true, false});
00934 %!test
00935 %!  A = cellfun (@(x,y) mat2str(x,y), {{1.1}, {4.2}}, {{3.1}, {2}}, \
00936 %!    "ErrorHandler", @__cellfunerror);
00937 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
00938 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
00939 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
00940 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
00941 %!  assert ([A(1).index, A(2).index], [1, 2]);
00942 %!test %% Overwriting setting of "UniformOutput" true
00943 %!  A = cellfun (@(x,y) mat2str(x,y), {{1.1}, {4.2}}, {{3.1}, {2}}, \
00944 %!    "UniformOutput", true, "ErrorHandler", @__cellfunerror);
00945 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
00946 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
00947 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
00948 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
00949 %!  assert ([A(1).index, A(2).index], [1, 2]);
00950 
00951 %% Input arguments can be of type cell array of structure arrays
00952 %!test
00953 %!  a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
00954 %!  A = cellfun (@(x,y) (x.a == y.a) && (x.b < y.b), {a}, {b});
00955 %!  assert (A, true);
00956 %!test
00957 %!  a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
00958 %!  A = cellfun (@(x,y) (x.a == y.a) && (x.b < y.b) , {a}, {b}, \
00959 %!    "UniformOutput", true);
00960 %!  assert (A, true);
00961 %!test
00962 %!  a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
00963 %!  A = cellfun (@(x,y) (x.a == y.a) && (x.b < y.b) , {a}, {b}, \
00964 %!    "UniformOutput", false);
00965 %!  assert (A, {true});
00966 %!test
00967 %!  a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
00968 %!  A = cellfun (@(x,y) cell2str (x.a, y.a), {a}, {b}, \
00969 %!    "ErrorHandler", @__cellfunerror);
00970 %!  assert (isfield (A, "identifier"), true);
00971 %!  assert (isfield (A, "message"), true);
00972 %!  assert (isfield (A, "index"), true);
00973 %!  assert (isempty (A.message), false);
00974 %!  assert (A.index, 1);
00975 %!test %% Overwriting setting of "UniformOutput" true
00976 %!  a = struct ("a", 1, "b", 2); b = struct ("a", 1, "b", 3);
00977 %!  A = cellfun (@(x,y) cell2str (x.a, y.a), {a}, {b}, \
00978 %!    "UniformOutput", true, "ErrorHandler", @__cellfunerror);
00979 %!  assert (isfield (A, "identifier"), true);
00980 %!  assert (isfield (A, "message"), true);
00981 %!  assert (isfield (A, "index"), true);
00982 %!  assert (isempty (A.message), false);
00983 %!  assert (A.index, 1);
00984 
00985 %% A lot of other tests
00986 %!error(cellfun(1))
00987 %!error(cellfun('isclass',1))
00988 %!error(cellfun('size',1))
00989 %!error(cellfun(@sin,{[]},'BadParam',false))
00990 %!error(cellfun(@sin,{[]},'UniformOuput'))
00991 %!error(cellfun(@sin,{[]},'ErrorHandler'))
00992 %!assert(cellfun(@sin,{0,1}),sin([0,1]))
00993 %!assert(cellfun(inline('sin(x)'),{0,1}),sin([0,1]))
00994 %!assert(cellfun('sin',{0,1}),sin([0,1]))
00995 %!assert(cellfun('isempty',{1,[]}),[false,true])
00996 %!assert(cellfun('islogical',{false,pi}),[true,false])
00997 %!assert(cellfun('isreal',{1i,1}),[false,true])
00998 %!assert(cellfun('length',{zeros(2,2),1}),[2,1])
00999 %!assert(cellfun('prodofsize',{zeros(2,2),1}),[4,1])
01000 %!assert(cellfun('ndims',{zeros([2,2,2]),1}),[3,2])
01001 %!assert(cellfun('isclass',{zeros([2,2,2]),'test'},'double'),[true,false])
01002 %!assert(cellfun('size',{zeros([1,2,3]),1},1),[1,1])
01003 %!assert(cellfun('size',{zeros([1,2,3]),1},2),[2,1])
01004 %!assert(cellfun('size',{zeros([1,2,3]),1},3),[3,1])
01005 %!assert(cellfun(@atan2,{1,1},{1,2}),[atan2(1,1),atan2(1,2)])
01006 %!assert(cellfun(@atan2,{1,1},{1,2},'UniformOutput',false),{atan2(1,1),atan2(1,2)})
01007 %!assert(cellfun(@sin,{1,2;3,4}),sin([1,2;3,4]))
01008 %!assert(cellfun(@atan2,{1,1;1,1},{1,2;1,2}),atan2([1,1;1,1],[1,2;1,2]))
01009 %!error(cellfun(@factorial,{-1,3}))
01010 %!assert(cellfun(@factorial,{-1,3},'ErrorHandler',@(x,y) NaN),[NaN,6])
01011 %!assert (cellfun (@(x) x(2),{[1],[1,2]},"ErrorHandler",@(x,y) NaN), [NaN,2])
01012 %!test
01013 %! [a,b,c]=cellfun(@fileparts,{fullfile("a","b","c.d"),fullfile("e","f","g.h")},'UniformOutput',false);
01014 %! assert(a,{fullfile("a","b"),fullfile("e","f")})
01015 %! assert(b,{'c','g'})
01016 %! assert(c,{'.d','.h'})
01017 
01018 */
01019 
01020 // Arrayfun was originally a .m file written by Bill Denney and Jaroslav
01021 // Hajek.  It was converted to C++ by jwe so that it could properly
01022 // handle the nargout = 0 case.
01023 
01024 DEFUN_DLD (arrayfun, args, nargout,
01025   "-*- texinfo -*-\n\
01026 @deftypefn  {Function File} {} arrayfun (@var{func}, @var{A})\n\
01027 @deftypefnx {Function File} {@var{x} =} arrayfun (@var{func}, @var{A})\n\
01028 @deftypefnx {Function File} {@var{x} =} arrayfun (@var{func}, @var{A}, @var{b}, @dots{})\n\
01029 @deftypefnx {Function File} {[@var{x}, @var{y}, @dots{}] =} arrayfun (@var{func}, @var{A}, @dots{})\n\
01030 @deftypefnx {Function File} {} arrayfun (@dots{}, \"UniformOutput\", @var{val})\n\
01031 @deftypefnx {Function File} {} arrayfun (@dots{}, \"ErrorHandler\", @var{errfunc})\n\
01032 \n\
01033 Execute a function on each element of an array.  This is useful for\n\
01034 functions that do not accept array arguments.  If the function does\n\
01035 accept array arguments it is better to call the function directly.\n\
01036 \n\
01037 The first input argument @var{func} can be a string, a function\n\
01038 handle, an inline function, or an anonymous function.  The input\n\
01039 argument @var{A} can be a logic array, a numeric array, a string\n\
01040 array, a structure array, or a cell array.  By a call of the function\n\
01041 @command{arrayfun} all elements of @var{A} are passed on to the named\n\
01042 function @var{func} individually.\n\
01043 \n\
01044 The named function can also take more than two input arguments, with\n\
01045 the input arguments given as third input argument @var{b}, fourth\n\
01046 input argument @var{c}, @dots{}  If given more than one array input\n\
01047 argument then all input arguments must have the same sizes, for\n\
01048 example:\n\
01049 \n\
01050 @example\n\
01051 @group\n\
01052 arrayfun (@@atan2, [1, 0], [0, 1])\n\
01053 @result{} ans = [1.5708   0.0000]\n\
01054 @end group\n\
01055 @end example\n\
01056 \n\
01057 If the parameter @var{val} after a further string input argument\n\
01058 \"UniformOutput\" is set @code{true} (the default), then the named\n\
01059 function @var{func} must return a single element which then will be\n\
01060 concatenated into the return value and is of type matrix.  Otherwise,\n\
01061 if that parameter is set to @code{false}, then the outputs are\n\
01062 concatenated in a cell array.  For example:\n\
01063 \n\
01064 @example\n\
01065 @group\n\
01066 arrayfun (@@(x,y) x:y, \"abc\", \"def\", \"UniformOutput\", false)\n\
01067 @result{} ans =\n\
01068     @{\n\
01069       [1,1] = abcd\n\
01070       [1,2] = bcde\n\
01071       [1,3] = cdef\n\
01072     @}\n\
01073 @end group\n\
01074 @end example\n\
01075 \n\
01076 If more than one output arguments are given then the named function\n\
01077 must return the number of return values that also are expected, for\n\
01078 example:\n\
01079 \n\
01080 @example\n\
01081 @group\n\
01082 [A, B, C] = arrayfun (@@find, [10; 0], \"UniformOutput\", false)\n\
01083 @result{}\n\
01084 A =\n\
01085 @{\n\
01086   [1,1] =  1\n\
01087   [2,1] = [](0x0)\n\
01088 @}\n\
01089 B =\n\
01090 @{\n\
01091   [1,1] =  1\n\
01092   [2,1] = [](0x0)\n\
01093 @}\n\
01094 C =\n\
01095 @{\n\
01096   [1,1] =  10\n\
01097   [2,1] = [](0x0)\n\
01098 @}\n\
01099 @end group\n\
01100 @end example\n\
01101 \n\
01102 If the parameter @var{errfunc} after a further string input argument\n\
01103 \"ErrorHandler\" is another string, a function handle, an inline\n\
01104 function, or an anonymous function, then @var{errfunc} defines a\n\
01105 function to call in the case that @var{func} generates an error.\n\
01106 The definition of the function must be of the form\n\
01107 \n\
01108 @example\n\
01109 function [@dots{}] = errfunc (@var{s}, @dots{})\n\
01110 @end example\n\
01111 \n\
01112 @noindent\n\
01113 where there is an additional input argument to @var{errfunc}\n\
01114 relative to @var{func}, given by @var{s}.  This is a structure with\n\
01115 the elements \"identifier\", \"message\", and \"index\" giving,\n\
01116 respectively, the error identifier, the error message, and the index of\n\
01117 the array elements that caused the error.  The size of the output\n\
01118 argument of @var{errfunc} must have the same size as the output\n\
01119 argument of @var{func}, otherwise a real error is thrown.  For\n\
01120 example:\n\
01121 \n\
01122 @example\n\
01123 @group\n\
01124 function y = ferr (s, x), y = \"MyString\"; endfunction\n\
01125 arrayfun (@@str2num, [1234],\n\
01126            \"UniformOutput\", false, \"ErrorHandler\", @@ferr)\n\
01127 @result{} ans =\n\
01128     @{\n\
01129      [1,1] = MyString\n\
01130     @}\n\
01131 @end group\n\
01132 @end example\n\
01133 \n\
01134 @seealso{spfun, cellfun, structfun}\n\
01135 @end deftypefn")
01136 {
01137   octave_value_list retval;
01138   int nargin = args.length ();
01139   int nargout1 = (nargout < 1 ? 1 : nargout);
01140 
01141   if (nargin < 2)
01142     {
01143       error ("arrayfun: function requires at least 2 arguments");
01144       print_usage ();
01145       return retval;
01146     }
01147 
01148   octave_value func = args(0);
01149   bool symbol_table_lookup = false;
01150 
01151   if (func.is_string ())
01152     {
01153       // See if we can convert the string into a function.
01154 
01155       std::string name = args(0).string_value ();
01156 
01157       if (! valid_identifier (name))
01158         {
01159           std::string fcn_name = unique_symbol_name ("__arrayfun_fcn_");
01160           std::string fname = "function y = " + fcn_name + "(x) y = ";
01161 
01162           octave_function *ptr_func
01163             = extract_function (args(0), "arrayfun", fcn_name,
01164                                 fname, "; endfunction");
01165 
01166           if (ptr_func && ! error_state)
01167             func = octave_value (ptr_func, true);
01168         }
01169       else
01170         {
01171           func = symbol_table::find_function (name);
01172 
01173           if (func.is_undefined ())
01174             error ("arrayfun: invalid function NAME: %s", name.c_str ());
01175 
01176           symbol_table_lookup = true;
01177         }
01178 
01179       if (error_state)
01180         return retval;
01181     }
01182 
01183   if (func.is_function_handle () || func.is_inline_function ()
01184       || func.is_function ())
01185     {
01186       // The following is an optimisation because the symbol table can
01187       // give a more specific function class, so this can result in
01188       // fewer polymorphic function calls as the function gets called
01189       // for each value of the array.
01190 
01191       if (! symbol_table_lookup )
01192         {
01193           if (func.is_function_handle ())
01194             {
01195               octave_fcn_handle* f = func.fcn_handle_value ();
01196 
01197               // Overloaded function handles need to check the type of
01198               // the arguments for each element of the array, so they
01199               // cannot be optimised this way.
01200 
01201               if (f -> is_overloaded ())
01202                 goto nevermind;
01203             }
01204           octave_value f = symbol_table::find_function (func.function_value ()
01205                                                          -> name ());
01206           if (f.is_defined ())
01207             func = f;
01208         }
01209 
01210     nevermind:
01211 
01212       bool uniform_output = true;
01213       octave_value error_handler;
01214       
01215       get_mapper_fun_options (args, nargin, uniform_output, error_handler);
01216 
01217       if (error_state)
01218         return octave_value_list ();
01219 
01220       octave_value_list inputlist (nargin, octave_value ());
01221 
01222       OCTAVE_LOCAL_BUFFER (octave_value, inputs, nargin);
01223       OCTAVE_LOCAL_BUFFER (bool, mask, nargin);
01224 
01225       octave_idx_type k = 1;
01226 
01227       dim_vector fdims (1, 1);
01228 
01229       // Collect arguments.  Pre-fill scalar elements of inputlist
01230       // array.
01231 
01232       for (int j = 0; j < nargin; j++)
01233         {
01234           inputs[j] = args(j+1);
01235           mask[j] = inputs[j].numel () != 1;
01236 
01237           if (! mask[j])
01238             inputlist(j) = inputs[j];
01239         }
01240 
01241       for (int j = 0; j < nargin; j++)
01242         {
01243           if (mask[j])
01244             {
01245               fdims = inputs[j].dims ();
01246               k = inputs[j].numel ();
01247 
01248               for (int i = j+1; i < nargin; i++)
01249                 {
01250                   if (mask[i] && inputs[i].dims () != fdims)
01251                     {
01252                       error ("arrayfun: dimensions mismatch");
01253                       return retval;
01254                     }
01255                 }
01256               break;
01257             }
01258         }
01259 
01260 
01261       unwind_protect frame;
01262       frame.protect_var (buffer_error_messages);
01263 
01264       if (error_handler.is_defined ())
01265         buffer_error_messages++;
01266 
01267       // Apply functions.
01268 
01269       if (uniform_output)
01270         {
01271           std::list<octave_value_list> idx_list (1);
01272           idx_list.front ().resize (1);
01273           std::string idx_type = "(";
01274 
01275           OCTAVE_LOCAL_BUFFER (octave_value, retv, nargout1);
01276 
01277           for (octave_idx_type count = 0; count < k; count++)
01278             {
01279               idx_list.front ()(0) = count + 1.0;
01280 
01281               for (int j = 0; j < nargin; j++)
01282                 {
01283                   if (mask[j])
01284                     inputlist.xelem (j) = inputs[j].do_index_op (idx_list);
01285 
01286                   if (error_state)
01287                     return retval;
01288                 }
01289 
01290               const octave_value_list tmp
01291                 = get_output_list (count, nargout, inputlist, func,
01292                                    error_handler);
01293 
01294               if (error_state)
01295                 return retval;
01296 
01297               if (nargout > 0 && tmp.length () < nargout)
01298                 {
01299                   error ("arrayfun: function returned fewer than nargout values");
01300                   return retval;
01301                 }
01302 
01303               if  (nargout > 0
01304                    || (nargout == 0
01305                        && tmp.length () > 0 && tmp(0).is_defined ()))
01306                 {
01307                   int num_to_copy = tmp.length ();
01308 
01309                   if (num_to_copy > nargout1)
01310                     num_to_copy = nargout1;
01311 
01312                   if (count == 0)
01313                     {
01314                       for (int j = 0; j < num_to_copy; j++)
01315                         {
01316                           if (tmp(j).is_defined ())
01317                             {
01318                               octave_value val = tmp(j);
01319 
01320                               if (val.numel () == 1)
01321                                 retv[j] = val.resize (fdims);
01322                               else
01323                                 {
01324                                   error ("arrayfun: all values must be scalars when UniformOutput = true");
01325                                   break;
01326                                 }
01327                             }
01328                         }
01329                     }
01330                   else
01331                     {
01332                       for (int j = 0; j < num_to_copy; j++)
01333                         {
01334                           if (tmp(j).is_defined ())
01335                             {
01336                               octave_value val = tmp(j);
01337 
01338                               if (! retv[j].fast_elem_insert (count, val))
01339                                 {
01340                                   if (val.numel () == 1)
01341                                     {
01342                                       idx_list.front ()(0) = count + 1.0;
01343                                       retv[j].assign (octave_value::op_asn_eq,
01344                                                       idx_type, idx_list, val);
01345 
01346                                       if (error_state)
01347                                         break;
01348                                     }
01349                                   else
01350                                     {
01351                                       error ("arrayfun: all values must be scalars when UniformOutput = true");
01352                                       break;
01353                                     }
01354                                 }
01355                             }
01356                         }
01357                     }
01358                 }
01359 
01360               if (error_state)
01361                 break;
01362             }
01363 
01364           retval.resize (nargout1);
01365 
01366           for (int j = 0; j < nargout1; j++)
01367             {
01368               if (nargout > 0 && retv[j].is_undefined ())
01369                 retval(j) = NDArray (fdims);
01370               else
01371                 retval(j) = retv[j];
01372             }
01373         }
01374       else
01375         {
01376           std::list<octave_value_list> idx_list (1);
01377           idx_list.front ().resize (1);
01378           std::string idx_type = "(";
01379 
01380           OCTAVE_LOCAL_BUFFER (Cell, results, nargout1);
01381 
01382           for (int j = 0; j < nargout1; j++)
01383             results[j].resize (fdims, Matrix ());
01384 
01385           bool have_some_output = false;
01386 
01387           for (octave_idx_type count = 0; count < k; count++)
01388             {
01389               idx_list.front ()(0) = count + 1.0;
01390 
01391               for (int j = 0; j < nargin; j++)
01392                 {
01393                   if (mask[j])
01394                     inputlist.xelem (j) = inputs[j].do_index_op (idx_list);
01395 
01396                   if (error_state)
01397                     return retval;
01398                 }
01399 
01400               const octave_value_list tmp
01401                 = get_output_list (count, nargout, inputlist, func,
01402                                    error_handler);
01403 
01404               if (error_state)
01405                 return retval;
01406 
01407               if (nargout > 0 && tmp.length () < nargout)
01408                 {
01409                   error ("arrayfun: function returned fewer than nargout values");
01410                   return retval;
01411                 }
01412 
01413               if  (nargout > 0
01414                    || (nargout == 0
01415                        && tmp.length () > 0 && tmp(0).is_defined ()))
01416                 {
01417                   int num_to_copy = tmp.length ();
01418 
01419                   if (num_to_copy > nargout1)
01420                     num_to_copy = nargout1;
01421 
01422                   if (num_to_copy > 0)
01423                     have_some_output = true;
01424 
01425                   for (int j = 0; j < num_to_copy; j++)
01426                     results[j](count) = tmp(j);
01427                 }
01428             }
01429 
01430           if (have_some_output || fdims.any_zero ())
01431             {
01432               retval.resize (nargout1);
01433 
01434               for (int j = 0; j < nargout1; j++)
01435                 retval(j) = results[j];
01436             }
01437         }
01438     }
01439   else
01440     error ("arrayfun: argument NAME must be a string or function handle");
01441 
01442   return retval;
01443 }
01444 
01445 /*
01446 %!function r = __f11 (x)
01447 %!  global __arrayfun_test_num_outputs__
01448 %!  __arrayfun_test_num_outputs__ = nargout;
01449 %!  r = x;
01450 %!endfunction
01451 
01452 %!function __f01 (x)
01453 %!  global __arrayfun_test_num_outputs__
01454 %!  __arrayfun_test_num_outputs__ = nargout;
01455 %!endfunction
01456 
01457 %!test
01458 %! global __arrayfun_test_num_outputs__
01459 %! arrayfun (@__f11, {1});
01460 %! assert (__arrayfun_test_num_outputs__, 0)
01461 %! x = arrayfun (@__f11, {1});
01462 %! assert (__arrayfun_test_num_outputs__, 1)
01463 
01464 %!test
01465 %! global __arrayfun_test_num_outputs__
01466 %! arrayfun (@__f01, {1});
01467 %! assert (__arrayfun_test_num_outputs__, 0)
01468 
01469 %!error x = arrayfun (@__f01, [1, 2]);
01470 
01471 %!test
01472 %! assert (arrayfun (@__f11, [1, 2]), [1, 2])
01473 %! assert (arrayfun (@__f11, [1, 2], 'uniformoutput', false), {1, 2});
01474 %! assert (arrayfun (@__f11, {1, 2}), {1, 2})
01475 %! assert (arrayfun (@__f11, {1, 2}, 'uniformoutput', false), {{1}, {2}});
01476 
01477 %!assert (arrayfun (@ones, 1, [2,3], 'uniformoutput', false), {[1,1], [1,1,1]});
01478 
01479 %% Test function to check the "Errorhandler" option
01480 %!function [z] = __arrayfunerror (S, varargin)
01481 %!      z = S;
01482 %!endfunction
01483 %% First input argument can be a string, an inline function, a
01484 %% function_handle or an anonymous function
01485 %!test
01486 %!  arrayfun (@isequal, [false, true], [true, true]); %% No output argument
01487 %!error
01488 %!  arrayfun (@isequal); %% One or less input arguments
01489 %!test
01490 %!  A = arrayfun ("isequal", [false, true], [true, true]);
01491 %!  assert (A, [false, true]);
01492 %!test
01493 %!  A = arrayfun (inline ("(x == y)", "x", "y"), [false, true], [true, true]);
01494 %!  assert (A, [false, true]);
01495 %!test
01496 %!  A = arrayfun (@isequal, [false, true], [true, true]);
01497 %!  assert (A, [false, true]);
01498 %!test
01499 %!  A = arrayfun (@(x,y) isequal(x,y), [false, true], [true, true]);
01500 %!  assert (A, [false, true]);
01501 
01502 %% Number of input and output arguments may be greater than one
01503 %#!test
01504 %!  A = arrayfun (@(x) islogical (x), false);
01505 %!  assert (A, true);
01506 %!test
01507 %!  A = arrayfun (@(x,y,z) x + y + z, [1, 1, 1], [2, 2, 2], [3, 4, 5]);
01508 %!  assert (A, [6, 7, 8], 1e-16);
01509 %!test %% Two input arguments of different types
01510 %!  A = arrayfun (@(x,y) islogical (x) && ischar (y), false, "a");
01511 %!  assert (A, true);
01512 %!test %% Pass another variable to the anonymous function
01513 %!  y = true; A = arrayfun (@(x) islogical (x && y), false);
01514 %!  assert (A, true);
01515 %!test %% Three ouptut arguments of different type
01516 %!  [A, B, C] = arrayfun (@find, [10, 11; 0, 12], "UniformOutput", false);
01517 %!  assert (isequal (A, {true, true; [], true}));
01518 %!  assert (isequal (B, {true, true; [], true}));
01519 %!  assert (isequal (C, {10, 11; [], 12}));
01520 
01521 %% Input arguments can be of type logical
01522 %!test
01523 %!  A = arrayfun (@(x,y) x == y, [false, true], [true, true]);
01524 %!  assert (A, [false, true]);
01525 %!test
01526 %!  A = arrayfun (@(x,y) x == y, [false; true], [true; true], "UniformOutput", true);
01527 %!  assert (A, [false; true]);
01528 %!test
01529 %!  A = arrayfun (@(x) x, [false, true, false, true], "UniformOutput", false);
01530 %!  assert (A, {false, true, false, true});
01531 %!test %% Three ouptut arguments of same type
01532 %!  [A, B, C] = arrayfun (@find, [true, false; false, true], "UniformOutput", false);
01533 %!  assert (isequal (A, {true, []; [], true}));
01534 %!  assert (isequal (B, {true, []; [], true}));
01535 %!  assert (isequal (C, {true, []; [], true}));
01536 %!test
01537 %!  A = arrayfun (@(x,y) array2str (x,y), true, true, "ErrorHandler", @__arrayfunerror);
01538 %!  assert (isfield (A, "identifier"), true);
01539 %!  assert (isfield (A, "message"), true);
01540 %!  assert (isfield (A, "index"), true);
01541 %!  assert (isempty (A.message), false);
01542 %!  assert (A.index, 1);
01543 %!test %% Overwriting setting of "UniformOutput" true
01544 %!  A = arrayfun (@(x,y) array2str (x,y), true, true, \
01545 %!                "UniformOutput", true, "ErrorHandler", @__arrayfunerror);
01546 %!  assert (isfield (A, "identifier"), true);
01547 %!  assert (isfield (A, "message"), true);
01548 %!  assert (isfield (A, "index"), true);
01549 %!  assert (isempty (A.message), false);
01550 %!  assert (A.index, 1);
01551 
01552 %% Input arguments can be of type numeric
01553 %!test
01554 %!  A = arrayfun (@(x,y) x>y, [1.1, 4.2], [3.1, 2+3*i]);
01555 %!  assert (A, [false, true]);
01556 %!test
01557 %!  A = arrayfun (@(x,y) x>y, [1.1, 4.2; 2, 4], [3.1, 2; 2, 4+2*i], "UniformOutput", true);
01558 %!  assert (A, [false, true; false, false]);
01559 %!test
01560 %!  A = arrayfun (@(x,y) x:y, [1.1, 4], [3.1, 6], "UniformOutput", false);
01561 %!  assert (isequal (A{1}, [1.1, 2.1, 3.1]));
01562 %!  assert (isequal (A{2}, [4, 5, 6]));
01563 %!test %% Three ouptut arguments of different type
01564 %!  [A, B, C] = arrayfun (@find, [10, 11; 0, 12], "UniformOutput", false);
01565 %!  assert (isequal (A, {true, true; [], true}));
01566 %!  assert (isequal (B, {true, true; [], true}));
01567 %!  assert (isequal (C, {10, 11; [], 12}));
01568 %!test
01569 %!  A = arrayfun (@(x,y) array2str(x,y), {1.1, 4}, {3.1, 6}, "ErrorHandler", @__arrayfunerror);
01570 %!  B = isfield (A(1), "message") && isfield (A(1), "index");
01571 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
01572 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
01573 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
01574 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
01575 %!  assert ([A(1).index, A(2).index], [1, 2]);
01576 %!test %% Overwriting setting of "UniformOutput" true
01577 %!  A = arrayfun (@(x,y) array2str(x,y), {1.1, 4}, {3.1, 6}, \
01578 %!                "UniformOutput", true, "ErrorHandler", @__arrayfunerror);
01579 %!  B = isfield (A(1), "message") && isfield (A(1), "index");
01580 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
01581 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
01582 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
01583 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
01584 %!  assert ([A(1).index, A(2).index], [1, 2]);
01585 
01586 %% Input arguments can be of type character or strings
01587 %!test
01588 %!  A = arrayfun (@(x,y) x>y, ["ad", "c", "ghi"], ["cc", "d", "fgh"]);
01589 %!  assert (A, [false, true, false, true, true, true]);
01590 %!test
01591 %!  A = arrayfun (@(x,y) x>y, ["a"; "f"], ["c"; "d"], "UniformOutput", true);
01592 %!  assert (A, [false; true]);
01593 %!test
01594 %!  A = arrayfun (@(x,y) x:y, ["a", "d"], ["c", "f"], "UniformOutput", false);
01595 %!  assert (A, {"abc", "def"});
01596 %! %#!test
01597 %!   A = arrayfun (@(x,y) cell2str(x,y), ["a", "d"], ["c", "f"], "ErrorHandler", @__arrayfunerror);
01598 %!   B = isfield (A(1), "identifier") && isfield (A(1), "message") && isfield (A(1), "index");
01599 %!   assert (B, true);
01600 
01601 %% Input arguments can be of type structure
01602 %!test
01603 %!  a = struct ("a", 1.1, "b", 4.2); b = struct ("a", 3.1, "b", 2);
01604 %!  A = arrayfun (@(x,y) (x.a < y.a) && (x.b > y.b), a, b);
01605 %!  assert (A, true);
01606 %!test
01607 %!  a = struct ("a", 1.1, "b", 4.2); b = struct ("a", 3.1, "b", 2);
01608 %!  A = arrayfun (@(x,y) (x.a < y.a) && (x.b > y.b), a, b, "UniformOutput", true);
01609 %!  assert (A, true);
01610 %!test
01611 %!  a = struct ("a", 1.1, "b", 4.2); b = struct ("a", 3.1, "b", 2);
01612 %!  A = arrayfun (@(x,y) x.a:y.a, a, b, "UniformOutput", false);
01613 %!  assert (isequal (A, {[1.1, 2.1, 3.1]}));
01614 %!test
01615 %!  A = arrayfun (@(x) mat2str(x), "a", "ErrorHandler", @__arrayfunerror);
01616 %!  assert (isfield (A, "identifier"), true);
01617 %!  assert (isfield (A, "message"), true);
01618 %!  assert (isfield (A, "index"), true);
01619 %!  assert (isempty (A.message), false);
01620 %!  assert (A.index, 1);
01621 %!test %% Overwriting setting of "UniformOutput" true
01622 %!  A = arrayfun (@(x) mat2str(x), "a", "UniformOutput", true, \
01623 %!                "ErrorHandler", @__arrayfunerror);
01624 %!  assert (isfield (A, "identifier"), true);
01625 %!  assert (isfield (A, "message"), true);
01626 %!  assert (isfield (A, "index"), true);
01627 %!  assert (isempty (A.message), false);
01628 %!  assert (A.index, 1);
01629 
01630 %% Input arguments can be of type cell array
01631 %!test
01632 %!  A = arrayfun (@(x,y) x{1} < y{1}, {1.1, 4.2}, {3.1, 2});
01633 %!  assert (A, [true, false]);
01634 %!test
01635 %!  A = arrayfun (@(x,y) x{1} < y{1}, {1.1; 4.2}, {3.1; 2}, "UniformOutput", true);
01636 %!  assert (A, [true; false]);
01637 %!test
01638 %!  A = arrayfun (@(x,y) x{1} < y{1}, {1.1, 4.2}, {3.1, 2}, "UniformOutput", false);
01639 %!  assert (A, {true, false});
01640 %!test
01641 %!  A = arrayfun (@(x,y) num2str(x,y), {1.1, 4.2}, {3.1, 2}, "ErrorHandler", @__arrayfunerror);
01642 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
01643 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
01644 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
01645 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
01646 %!  assert ([A(1).index, A(2).index], [1, 2]);
01647 %!test
01648 %!  A = arrayfun (@(x,y) num2str(x,y), {1.1, 4.2}, {3.1, 2}, \
01649 %!                "UniformOutput", true, "ErrorHandler", @__arrayfunerror);
01650 %!  assert ([(isfield (A(1), "identifier")), (isfield (A(2), "identifier"))], [true, true]);
01651 %!  assert ([(isfield (A(1), "message")), (isfield (A(2), "message"))], [true, true]);
01652 %!  assert ([(isfield (A(1), "index")), (isfield (A(2), "index"))], [true, true]);
01653 %!  assert ([(isempty (A(1).message)), (isempty (A(2).message))], [false, false]);
01654 %!  assert ([A(1).index, A(2).index], [1, 2]);
01655 */
01656 
01657 static void
01658 do_num2cell_helper (const dim_vector& dv,
01659                     const Array<int>& dimv,
01660                     dim_vector& celldv, dim_vector& arraydv,
01661                     Array<int>& perm)
01662 {
01663   int dvl = dimv.length ();
01664   int maxd = dv.length ();
01665   celldv = dv;
01666   for (int i = 0; i < dvl; i++)
01667     maxd = std::max (maxd, dimv(i));
01668   if (maxd > dv.length ())
01669     celldv.resize (maxd, 1);
01670   arraydv = celldv;
01671 
01672   OCTAVE_LOCAL_BUFFER_INIT (bool, sing, maxd, false);
01673 
01674   perm.clear (maxd, 1);
01675   for (int i = 0; i < dvl; i++)
01676     {
01677       int k = dimv(i) - 1;
01678       if (k < 0)
01679         {
01680           error ("num2cell: dimension indices must be positive");
01681           return;
01682         }
01683       else if (i > 0 && k < dimv(i-1) - 1)
01684         {
01685           error ("num2cell: dimension indices must be strictly increasing");
01686           return;
01687         }
01688 
01689       sing[k] = true;
01690       perm(i) = k;
01691     }
01692 
01693   for (int k = 0, i = dvl; k < maxd; k++)
01694     if (! sing[k])
01695       perm(i++) = k;
01696 
01697   for (int i = 0; i < maxd; i++)
01698     if (sing[i])
01699       celldv(i) = 1;
01700     else
01701       arraydv(i) = 1;
01702 }
01703 
01704 template<class NDA>
01705 static inline typename NDA::element_type
01706 do_num2cell_elem (const NDA& array, octave_idx_type i)
01707 { return array(i); }
01708 
01709 static inline Cell
01710 do_num2cell_elem (const Cell& array, octave_idx_type i)
01711 { return Cell (array(i)); }
01712 
01713 
01714 template<class NDA>
01715 static Cell
01716 do_num2cell (const NDA& array, const Array<int>& dimv)
01717 {
01718   if (dimv.is_empty ())
01719     {
01720       Cell retval (array.dims ());
01721       octave_idx_type nel = array.numel ();
01722       for (octave_idx_type i = 0; i < nel; i++)
01723         retval.xelem (i) = do_num2cell_elem (array, i);
01724 
01725       return retval;
01726     }
01727   else
01728     {
01729       dim_vector celldv, arraydv;
01730       Array<int> perm;
01731       do_num2cell_helper (array.dims (), dimv, celldv, arraydv, perm);
01732       if (error_state)
01733         return Cell ();
01734 
01735       NDA parray = array.permute (perm);
01736 
01737       octave_idx_type nela = arraydv.numel (), nelc = celldv.numel ();
01738       parray = parray.reshape (dim_vector (nela, nelc));
01739 
01740       Cell retval (celldv);
01741       for (octave_idx_type i = 0; i < nelc; i++)
01742         {
01743           retval.xelem (i) = NDA (parray.column (i).reshape (arraydv));
01744         }
01745 
01746       return retval;
01747     }
01748 }
01749 
01750 // FIXME -- this is a mess, but if a size method for the object exists,
01751 // we have to call it to get the size of the object instead of using the
01752 // internal dims method.
01753 
01754 static dim_vector
01755 get_object_dims (octave_value& obj)
01756 {
01757   dim_vector retval;
01758 
01759   Matrix m = obj.size ();
01760 
01761   int n = m.numel ();
01762 
01763   retval.resize (n);
01764 
01765   for (int i = 0; i < n; i++)
01766     retval(i) = m(i);
01767 
01768   return retval;
01769 }
01770 
01771 static Cell
01772 do_object2cell (const octave_value& obj, const Array<int>& dimv)
01773 {
01774   Cell retval;
01775 
01776   // FIXME -- this copy is only needed because the octave_value::size
01777   // method is not const.
01778   octave_value array = obj;
01779 
01780   if (dimv.is_empty ())
01781     {
01782       dim_vector dv = get_object_dims (array);
01783 
01784       if (! error_state)
01785         {
01786           retval.resize (dv);
01787 
01788           octave_value_list idx (1);
01789 
01790           for (octave_idx_type i = 0; i < dv.numel (); i++)
01791             {
01792               octave_quit ();
01793 
01794               idx(0) = double (i+1);
01795 
01796               retval.xelem(i) = array.single_subsref ("(", idx);
01797 
01798               if (error_state)
01799                 break;
01800             }
01801         }
01802     }
01803   else
01804     {
01805       error ("num2cell (A, dim) not implemented for class objects");
01806     }
01807 
01808   return retval;
01809 }
01810 
01811 DEFUN_DLD (num2cell, args, ,
01812   "-*- texinfo -*-\n\
01813 @deftypefn  {Loadable Function} {@var{C} =} num2cell (@var{A})\n\
01814 @deftypefnx {Loadable Function} {@var{C} =} num2cell (@var{A}, @var{dim})\n\
01815 Convert the numeric matrix @var{A} to a cell array.  If @var{dim} is\n\
01816 defined, the value @var{C} is of dimension 1 in this dimension and the\n\
01817 elements of @var{A} are placed into @var{C} in slices.  For example:\n\
01818 \n\
01819 @example\n\
01820 @group\n\
01821 num2cell([1,2;3,4])\n\
01822      @result{} ans =\n\
01823         @{\n\
01824           [1,1] =  1\n\
01825           [2,1] =  3\n\
01826           [1,2] =  2\n\
01827           [2,2] =  4\n\
01828         @}\n\
01829 num2cell([1,2;3,4],1)\n\
01830      @result{} ans =\n\
01831         @{\n\
01832           [1,1] =\n\
01833              1\n\
01834              3\n\
01835           [1,2] =\n\
01836              2\n\
01837              4\n\
01838         @}\n\
01839 @end group\n\
01840 @end example\n\
01841 \n\
01842 @seealso{mat2cell}\n\
01843 @end deftypefn")
01844 {
01845   int nargin =  args.length();
01846   octave_value retval;
01847 
01848   if (nargin < 1 || nargin > 2)
01849     print_usage ();
01850   else
01851     {
01852       octave_value array = args(0);
01853       Array<int> dimv;
01854       if (nargin > 1)
01855         dimv = args (1).int_vector_value (true);
01856 
01857       if (error_state)
01858         ;
01859       else if (array.is_bool_type ())
01860         retval = do_num2cell (array.bool_array_value (), dimv);
01861       else if (array.is_char_matrix ())
01862         retval = do_num2cell (array.char_array_value (), dimv);
01863       else if (array.is_numeric_type ())
01864         {
01865           if (array.is_integer_type ())
01866             {
01867               if (array.is_int8_type ())
01868                 retval = do_num2cell (array.int8_array_value (), dimv);
01869               else if (array.is_int16_type ())
01870                 retval = do_num2cell (array.int16_array_value (), dimv);
01871               else if (array.is_int32_type ())
01872                 retval = do_num2cell (array.int32_array_value (), dimv);
01873               else if (array.is_int64_type ())
01874                 retval = do_num2cell (array.int64_array_value (), dimv);
01875               else if (array.is_uint8_type ())
01876                 retval = do_num2cell (array.uint8_array_value (), dimv);
01877               else if (array.is_uint16_type ())
01878                 retval = do_num2cell (array.uint16_array_value (), dimv);
01879               else if (array.is_uint32_type ())
01880                 retval = do_num2cell (array.uint32_array_value (), dimv);
01881               else if (array.is_uint64_type ())
01882                 retval = do_num2cell (array.uint64_array_value (), dimv);
01883             }
01884           else if (array.is_complex_type ())
01885             {
01886               if (array.is_single_type ())
01887                 retval = do_num2cell (array.float_complex_array_value (), dimv);
01888               else
01889                 retval = do_num2cell (array.complex_array_value (), dimv);
01890             }
01891           else
01892             {
01893               if (array.is_single_type ())
01894                 retval = do_num2cell (array.float_array_value (), dimv);
01895               else
01896                 retval = do_num2cell (array.array_value (), dimv);
01897             }
01898         }
01899       else if (array.is_object ())
01900         retval = do_object2cell (array, dimv);
01901       else if (array.is_map ())
01902         retval = do_num2cell (array.map_value (), dimv);
01903       else if (array.is_cell ())
01904         retval = do_num2cell (array.cell_value (), dimv);
01905       else if (array.is_object ())
01906         retval = do_num2cell (array.cell_value (), dimv);
01907       else
01908         gripe_wrong_type_arg ("num2cell", array);
01909     }
01910 
01911   return retval;
01912 }
01913 
01914 /*
01915 
01916 %!assert(num2cell([1,2;3,4]),{1,2;3,4})
01917 %!assert(num2cell([1,2;3,4],1),{[1;3],[2;4]})
01918 %!assert(num2cell([1,2;3,4],2),{[1,2];[3,4]})
01919 
01920 */
01921 
01922 static bool
01923 mat2cell_mismatch (const dim_vector& dv,
01924                    const Array<octave_idx_type> *d, int nd)
01925 {
01926   for (int i = 0; i < nd; i++)
01927     {
01928       octave_idx_type s = 0;
01929       for (octave_idx_type j = 0; j < d[i].length (); j++)
01930         s += d[i](j);
01931 
01932       octave_idx_type r = i < dv.length () ? dv(i) : 1;
01933 
01934       if (s != r)
01935         {
01936           error ("mat2cell: mismatch on %d-th dimension (%d != %d)",
01937                  i+1, r, s);
01938           return true;
01939         }
01940     }
01941 
01942   return false;
01943 }
01944 
01945 template<class container>
01946 static void
01947 prepare_idx (container *idx, int idim, int nd,
01948              const Array<octave_idx_type>* d)
01949 {
01950   octave_idx_type nidx = idim < nd ? d[idim].numel () : 1;
01951   if (nidx == 1)
01952     idx[0] = idx_vector::colon;
01953   else
01954     {
01955       octave_idx_type l = 0;
01956       for (octave_idx_type i = 0; i < nidx; i++)
01957         {
01958           octave_idx_type u = l + d[idim](i);
01959           idx[i] = idx_vector (l, u);
01960           l = u;
01961         }
01962     }
01963 }
01964 
01965 // 2D specialization, works for Array, Sparse and octave_map.
01966 // Uses 1D or 2D indexing.
01967 
01968 template <class Array2D>
01969 static Cell
01970 do_mat2cell_2d (const Array2D& a, const Array<octave_idx_type> *d, int nd)
01971 {
01972   NoAlias<Cell> retval;
01973   assert (nd == 1 || nd == 2);
01974   assert (a.ndims () == 2);
01975 
01976   if (mat2cell_mismatch (a.dims (), d, nd))
01977     return retval;
01978 
01979   octave_idx_type nridx = d[0].length ();
01980   octave_idx_type ncidx = nd == 1 ? 1 : d[1].length ();
01981   retval.clear (nridx, ncidx);
01982 
01983   int ivec = -1;
01984   if (a.rows () > 1 && a.cols () == 1 && ncidx == 1)
01985     ivec = 0;
01986   else if (a.rows () == 1 && nridx == 1 && nd == 2)
01987     ivec = 1;
01988 
01989   if (ivec >= 0)
01990     {
01991       // Vector split. Use 1D indexing.
01992       octave_idx_type l = 0, nidx = (ivec == 0 ? nridx : ncidx);
01993       for (octave_idx_type i = 0; i < nidx; i++)
01994         {
01995           octave_idx_type u = l + d[ivec](i);
01996           retval(i) = a.index (idx_vector (l, u));
01997           l = u;
01998         }
01999     }
02000   else
02001     {
02002       // General 2D case. Use 2D indexing.
02003       OCTAVE_LOCAL_BUFFER (idx_vector, ridx, nridx);
02004       prepare_idx (ridx, 0, nd, d);
02005 
02006       OCTAVE_LOCAL_BUFFER (idx_vector, cidx, ncidx);
02007       prepare_idx (cidx, 1, nd, d);
02008 
02009       for (octave_idx_type j = 0; j < ncidx; j++)
02010         for (octave_idx_type i = 0; i < nridx; i++)
02011           {
02012             octave_quit ();
02013 
02014             retval(i,j) = a.index (ridx[i], cidx[j]);
02015           }
02016     }
02017 
02018   return retval;
02019 }
02020 
02021 // Nd case. Works for Arrays and octave_map.
02022 // Uses Nd indexing.
02023 
02024 template <class ArrayND>
02025 Cell
02026 do_mat2cell_nd (const ArrayND& a, const Array<octave_idx_type> *d, int nd)
02027 {
02028   NoAlias<Cell> retval;
02029   assert (nd >= 1);
02030 
02031   if (mat2cell_mismatch (a.dims (), d, nd))
02032     return retval;
02033 
02034   dim_vector rdv = dim_vector::alloc (nd);
02035   OCTAVE_LOCAL_BUFFER (octave_idx_type, nidx, nd);
02036   octave_idx_type idxtot = 0;
02037   for (int i = 0; i < nd; i++)
02038     {
02039       rdv(i) = nidx[i] = d[i].length ();
02040       idxtot += nidx[i];
02041     }
02042 
02043   retval.clear (rdv);
02044 
02045   OCTAVE_LOCAL_BUFFER (idx_vector, xidx, idxtot);
02046   OCTAVE_LOCAL_BUFFER (idx_vector *, idx, nd);
02047 
02048   idxtot = 0;
02049   for (int i = 0; i < nd; i++)
02050     {
02051       idx[i] = xidx + idxtot;
02052       prepare_idx (idx[i], i, nd, d);
02053       idxtot += nidx[i];
02054     }
02055 
02056   OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ridx, nd, 0);
02057   NoAlias< Array<idx_vector> > ra_idx
02058     (dim_vector (1, std::max (nd, a.ndims ())), idx_vector::colon);
02059 
02060   for (octave_idx_type j = 0; j < retval.numel (); j++)
02061     {
02062       octave_quit ();
02063 
02064       for (int i = 0; i < nd; i++)
02065         ra_idx(i) = idx[i][ridx[i]];
02066 
02067       retval(j) = a.index (ra_idx);
02068 
02069       rdv.increment_index (ridx);
02070     }
02071 
02072   return retval;
02073 }
02074 
02075 // Dispatcher.
02076 template <class ArrayND>
02077 Cell
02078 do_mat2cell (const ArrayND& a, const Array<octave_idx_type> *d, int nd)
02079 {
02080   if (a.ndims () == 2 && nd <= 2)
02081     return do_mat2cell_2d (a, d, nd);
02082   else
02083     return do_mat2cell_nd (a, d, nd);
02084 }
02085 
02086 // General case. Works for any class supporting do_index_op.
02087 // Uses Nd indexing.
02088 
02089 Cell
02090 do_mat2cell (octave_value& a, const Array<octave_idx_type> *d, int nd)
02091 {
02092   NoAlias<Cell> retval;
02093   assert (nd >= 1);
02094 
02095   if (mat2cell_mismatch (a.dims (), d, nd))
02096     return retval;
02097 
02098   dim_vector rdv = dim_vector::alloc (nd);
02099   OCTAVE_LOCAL_BUFFER (octave_idx_type, nidx, nd);
02100   octave_idx_type idxtot = 0;
02101   for (int i = 0; i < nd; i++)
02102     {
02103       rdv(i) = nidx[i] = d[i].length ();
02104       idxtot += nidx[i];
02105     }
02106 
02107   retval.clear (rdv);
02108 
02109   OCTAVE_LOCAL_BUFFER (octave_value, xidx, idxtot);
02110   OCTAVE_LOCAL_BUFFER (octave_value *, idx, nd);
02111 
02112   idxtot = 0;
02113   for (int i = 0; i < nd; i++)
02114     {
02115       idx[i] = xidx + idxtot;
02116       prepare_idx (idx[i], i, nd, d);
02117       idxtot += nidx[i];
02118     }
02119 
02120   OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ridx, nd, 0);
02121   octave_value_list ra_idx (std::max (nd, a.ndims ()),
02122                             octave_value::magic_colon_t);
02123 
02124   for (octave_idx_type j = 0; j < retval.numel (); j++)
02125     {
02126       octave_quit ();
02127 
02128       for (int i = 0; i < nd; i++)
02129         ra_idx(i) = idx[i][ridx[i]];
02130 
02131       retval(j) = a.do_index_op (ra_idx);
02132 
02133       if (error_state)
02134         break;
02135 
02136       rdv.increment_index (ridx);
02137     }
02138 
02139   return retval;
02140 }
02141 
02142 DEFUN_DLD (mat2cell, args, ,
02143   "-*- texinfo -*-\n\
02144 @deftypefn  {Loadable Function} {@var{C} =} mat2cell (@var{A}, @var{m}, @var{n})\n\
02145 @deftypefnx {Loadable Function} {@var{C} =} mat2cell (@var{A}, @var{d1}, @var{d2}, @dots{})\n\
02146 @deftypefnx {Loadable Function} {@var{C} =} mat2cell (@var{A}, @var{r})\n\
02147 Convert the matrix @var{A} to a cell array.  If @var{A} is 2-D, then\n\
02148 it is required that @code{sum (@var{m}) == size (@var{A}, 1)} and\n\
02149 @code{sum (@var{n}) == size (@var{A}, 2)}.  Similarly, if @var{A} is\n\
02150 multi-dimensional and the number of dimensional arguments is equal\n\
02151 to the dimensions of @var{A}, then it is required that @code{sum (@var{di})\n\
02152 == size (@var{A}, i)}.\n\
02153 \n\
02154 Given a single dimensional argument @var{r}, the other dimensional\n\
02155 arguments are assumed to equal @code{size (@var{A},@var{i})}.\n\
02156 \n\
02157 An example of the use of mat2cell is\n\
02158 \n\
02159 @example\n\
02160 mat2cell (reshape(1:16,4,4),[3,1],[3,1])\n\
02161 @result{} @{\n\
02162   [1,1] =\n\
02163 \n\
02164      1   5   9\n\
02165      2   6  10\n\
02166      3   7  11\n\
02167 \n\
02168   [2,1] =\n\
02169 \n\
02170      4   8  12\n\
02171 \n\
02172   [1,2] =\n\
02173 \n\
02174     13\n\
02175     14\n\
02176     15\n\
02177 \n\
02178   [2,2] = 16\n\
02179 @}\n\
02180 @end example\n\
02181 @seealso{num2cell, cell2mat}\n\
02182 @end deftypefn")
02183 {
02184   int nargin = args.length();
02185   octave_value retval;
02186 
02187   if (nargin < 2)
02188     print_usage ();
02189   else
02190     {
02191       // Prepare indices.
02192       OCTAVE_LOCAL_BUFFER (Array<octave_idx_type>, d, nargin-1);
02193 
02194       for (int i = 1; i < nargin; i++)
02195         {
02196           d[i-1] = args(i).octave_idx_type_vector_value (true);
02197           if (error_state)
02198             return retval;
02199         }
02200 
02201       octave_value a = args(0);
02202       bool sparse = a.is_sparse_type ();
02203       if (sparse && nargin > 3)
02204         {
02205           error ("mat2cell: sparse arguments only support 2D indexing");
02206           return retval;
02207         }
02208 
02209       switch (a.builtin_type ())
02210         {
02211         case btyp_double:
02212           {
02213             if (sparse)
02214               retval = do_mat2cell_2d (a.sparse_matrix_value (), d, nargin-1);
02215             else
02216               retval = do_mat2cell (a.array_value (), d, nargin - 1);
02217             break;
02218           }
02219         case btyp_complex:
02220           {
02221             if (sparse)
02222               retval = do_mat2cell_2d (a.sparse_complex_matrix_value (), d, nargin-1);
02223             else
02224               retval = do_mat2cell (a.complex_array_value (), d, nargin - 1);
02225             break;
02226           }
02227 #define BTYP_BRANCH(X,Y) \
02228         case btyp_ ## X: \
02229             retval = do_mat2cell (a.Y ## _value (), d, nargin - 1); \
02230           break
02231 
02232         BTYP_BRANCH (float, float_array);
02233         BTYP_BRANCH (float_complex, float_complex_array);
02234         BTYP_BRANCH (bool, bool_array);
02235         BTYP_BRANCH (char, char_array);
02236 
02237         BTYP_BRANCH (int8,  int8_array);
02238         BTYP_BRANCH (int16, int16_array);
02239         BTYP_BRANCH (int32, int32_array);
02240         BTYP_BRANCH (int64, int64_array);
02241         BTYP_BRANCH (uint8,  uint8_array);
02242         BTYP_BRANCH (uint16, uint16_array);
02243         BTYP_BRANCH (uint32, uint32_array);
02244         BTYP_BRANCH (uint64, uint64_array);
02245 
02246         BTYP_BRANCH (cell, cell);
02247         BTYP_BRANCH (struct, map);
02248 #undef BTYP_BRANCH
02249 
02250         case btyp_func_handle:
02251           gripe_wrong_type_arg ("mat2cell", a);
02252           break;
02253         default:
02254           retval = do_mat2cell (a, d, nargin-1);
02255         }
02256     }
02257 
02258   return retval;
02259 }
02260 
02261 /*
02262 
02263 %!test
02264 %! x = reshape(1:20,5,4);
02265 %! c = mat2cell(x,[3,2],[3,1]);
02266 %! assert(c,{[1,6,11;2,7,12;3,8,13],[16;17;18];[4,9,14;5,10,15],[19;20]})
02267 
02268 %!test
02269 %! x = 'abcdefghij';
02270 %! c = mat2cell(x,1,[0,4,2,0,4,0]);
02271 %! empty1by0str = resize('',1,0);
02272 %! assert(c,{empty1by0str,'abcd','ef',empty1by0str,'ghij',empty1by0str})
02273 
02274 */
02275 
02276 // FIXME: it would be nice to allow ranges being handled without a conversion.
02277 template <class NDA>
02278 static Cell
02279 do_cellslices_nda (const NDA& array,
02280                    const Array<octave_idx_type>& lb,
02281                    const Array<octave_idx_type>& ub,
02282                    int dim = -1)
02283 {
02284   octave_idx_type n = lb.length ();
02285   Cell retval (1, n);
02286   if (array.is_vector () && (dim == -1
02287                              || (dim == 0 && array.columns () == 1)
02288                              || (dim == 1 && array.rows () == 1)))
02289     {
02290       for (octave_idx_type i = 0; i < n && ! error_state; i++)
02291         retval(i) = array.index (idx_vector (lb(i) - 1, ub(i)));
02292     }
02293   else
02294     {
02295       const dim_vector dv = array.dims ();
02296       int ndims = dv.length ();
02297       if (dim < 0)
02298         dim = dv.first_non_singleton ();
02299       ndims = std::max (ndims, dim + 1);
02300 
02301       Array<idx_vector> idx (dim_vector (ndims, 1), idx_vector::colon);
02302 
02303       for (octave_idx_type i = 0; i < n && ! error_state; i++)
02304         {
02305           idx(dim) = idx_vector (lb(i) - 1, ub(i));
02306           retval(i) = array.index (idx);
02307         }
02308     }
02309 
02310   return retval;
02311 }
02312 
02313 DEFUN_DLD (cellslices, args, ,
02314   "-*- texinfo -*-\n\
02315 @deftypefn {Loadable Function} {@var{sl} =} cellslices (@var{x}, @var{lb}, @var{ub}, @var{dim})\n\
02316 Given an array @var{x}, this function produces a cell array of slices from\n\
02317 the array determined by the index vectors @var{lb}, @var{ub}, for lower and\n\
02318 upper bounds, respectively.  In other words, it is equivalent to the\n\
02319 following code:\n\
02320 \n\
02321 @example\n\
02322 @group\n\
02323 n = length (lb);\n\
02324 sl = cell (1, n);\n\
02325 for i = 1:length (lb)\n\
02326   sl@{i@} = x(:,@dots{},lb(i):ub(i),@dots{},:);\n\
02327 endfor\n\
02328 @end group\n\
02329 @end example\n\
02330 \n\
02331 The position of the index is determined by @var{dim}.  If not specified,\n\
02332 slicing is done along the first non-singleton dimension.\n\
02333 @seealso{cell2mat, cellindexmat, cellfun}\n\
02334 @end deftypefn")
02335 {
02336   octave_value retval;
02337   int nargin = args.length ();
02338   if (nargin == 3 || nargin == 4)
02339     {
02340       octave_value x = args(0);
02341       Array<octave_idx_type> lb = args(1).octave_idx_type_vector_value ();
02342       Array<octave_idx_type> ub = args(2).octave_idx_type_vector_value ();
02343       int dim = -1;
02344       if (nargin == 4)
02345         {
02346           dim = args(3).int_value () - 1;
02347           if (dim < 0)
02348             error ("cellslices: DIM must be a valid dimension");
02349         }
02350 
02351       if (! error_state)
02352         {
02353           if (lb.length () != ub.length ())
02354             error ("cellslices: the lengths of LB and UB must match");
02355           else
02356             {
02357               Cell retcell;
02358               if (! x.is_sparse_type () && x.is_matrix_type ())
02359                 {
02360                   // specialize for some dense arrays.
02361                   if (x.is_bool_type ())
02362                     retcell = do_cellslices_nda (x.bool_array_value (), lb, ub, dim);
02363                   else if (x.is_char_matrix ())
02364                     retcell = do_cellslices_nda (x.char_array_value (), lb, ub, dim);
02365                   else if (x.is_integer_type ())
02366                     {
02367                       if (x.is_int8_type ())
02368                         retcell = do_cellslices_nda (x.int8_array_value (), lb, ub, dim);
02369                       else if (x.is_int16_type ())
02370                         retcell = do_cellslices_nda (x.int16_array_value (), lb, ub, dim);
02371                       else if (x.is_int32_type ())
02372                         retcell = do_cellslices_nda (x.int32_array_value (), lb, ub, dim);
02373                       else if (x.is_int64_type ())
02374                         retcell = do_cellslices_nda (x.int64_array_value (), lb, ub, dim);
02375                       else if (x.is_uint8_type ())
02376                         retcell = do_cellslices_nda (x.uint8_array_value (), lb, ub, dim);
02377                       else if (x.is_uint16_type ())
02378                         retcell = do_cellslices_nda (x.uint16_array_value (), lb, ub, dim);
02379                       else if (x.is_uint32_type ())
02380                         retcell = do_cellslices_nda (x.uint32_array_value (), lb, ub, dim);
02381                       else if (x.is_uint64_type ())
02382                         retcell = do_cellslices_nda (x.uint64_array_value (), lb, ub, dim);
02383                     }
02384                   else if (x.is_complex_type ())
02385                     {
02386                       if (x.is_single_type ())
02387                         retcell = do_cellslices_nda (x.float_complex_array_value (), lb, ub, dim);
02388                       else
02389                         retcell = do_cellslices_nda (x.complex_array_value (), lb, ub, dim);
02390                     }
02391                   else
02392                     {
02393                       if (x.is_single_type ())
02394                         retcell = do_cellslices_nda (x.float_array_value (), lb, ub, dim);
02395                       else
02396                         retcell = do_cellslices_nda (x.array_value (), lb, ub, dim);
02397                     }
02398                 }
02399               else
02400                 {
02401                   // generic code.
02402                   octave_idx_type n = lb.length ();
02403                   retcell = Cell (1, n);
02404                   const dim_vector dv = x.dims ();
02405                   int ndims = dv.length ();
02406                   if (dim < 0)
02407                     dim = dv.first_non_singleton ();
02408                   ndims = std::max (ndims, dim + 1);
02409                   octave_value_list idx (ndims, octave_value::magic_colon_t);
02410                   for (octave_idx_type i = 0; i < n && ! error_state; i++)
02411                     {
02412                       idx(dim) = Range (lb(i), ub(i));
02413                       retcell(i) = x.do_index_op (idx);
02414                     }
02415                 }
02416               if (! error_state)
02417                 retval = retcell;
02418             }
02419         }
02420     }
02421   else
02422     print_usage ();
02423 
02424   return retval;
02425 }
02426 
02427 /*
02428 %!test
02429 %! m = [1, 2, 3, 4; 5, 6, 7, 8; 9, 10, 11, 12];
02430 %! c = cellslices (m, [1, 2], [2, 3], 2);
02431 %! assert (c, {[1, 2; 5, 6; 9, 10], [2, 3; 6, 7; 10, 11]});
02432 */
02433 
02434 DEFUN_DLD (cellindexmat, args, ,
02435   "-*- texinfo -*-\n\
02436 @deftypefn {Loadable Function} {@var{y} =} cellindexmat (@var{x}, @var{varargin})\n\
02437 Given a cell array of matrices @var{x}, this function computes\n\
02438 \n\
02439 @example\n\
02440 @group\n\
02441   Y = cell (size (X));\n\
02442   for i = 1:numel (X)\n\
02443     Y@{i@} = X@{i@}(varargin@{:@});\n\
02444   endfor\n\
02445 @end group\n\
02446 @end example\n\
02447 @seealso{cellslices, cellfun}\n\
02448 @end deftypefn")
02449 {
02450   octave_value retval;
02451   if (args.length () >= 1)
02452     {
02453       if (args(0).is_cell ())
02454         {
02455           const Cell x = args(0).cell_value ();
02456           NoAlias<Cell> y(x.dims ());
02457           octave_idx_type nel = x.numel ();
02458           octave_value_list idx = args.slice (1, args.length () - 1);
02459 
02460           for (octave_idx_type i = 0; i < nel; i++)
02461             {
02462               octave_quit ();
02463               octave_value tmp = x(i);
02464               y(i) = tmp.do_index_op (idx);
02465               if (error_state)
02466                 break;
02467             }
02468 
02469           retval = y;
02470         }
02471       else
02472         error ("cellindexmat: X must be a cell");
02473     }
02474   else
02475     print_usage ();
02476 
02477   return retval;
02478 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines