changeset 13229:983720941822

maint: improve readability of cellfun * cellfun.cc (try_cellfun_internal_ops, get_cellfun_options): New functions. (Fcellfun): Use them to improve readability.
author John W. Eaton <jwe@octave.org>
date Sun, 25 Sep 2011 22:33:47 -0400
parents e8c52b442a99
children c73cc5b67feb
files src/DLD-FUNCTIONS/cellfun.cc
diffstat 1 files changed, 194 insertions(+), 155 deletions(-) [+]
line wrap: on
line diff
--- a/src/DLD-FUNCTIONS/cellfun.cc	Sun Sep 25 22:03:45 2011 -0700
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Sun Sep 25 22:33:47 2011 -0400
@@ -76,11 +76,16 @@
           msg.assign ("identifier", last_error_id ());
           msg.assign ("message", last_error_message ());
           msg.assign ("index", static_cast<double> (count + static_cast<octave_idx_type>(1)));
+
           octave_value_list errlist = inputlist;
           errlist.prepend (msg);
+
           buffer_error_messages--;
+
           error_state = 0;
+
           tmp = error_handler.do_multi_index_op (nargout, errlist);
+
           buffer_error_messages++;
 
           if (error_state)
@@ -93,6 +98,155 @@
   return tmp;
 }
 
+static octave_value_list
+try_cellfun_internal_ops (const octave_value_list& args, int nargin)
+{
+  octave_value_list retval;
+
+  std::string name = args(0).string_value ();
+
+  const Cell f_args = args(1).cell_value ();
+
+  octave_idx_type k = f_args.numel ();
+
+  if (name == "isempty")
+    {
+      boolNDArray result (f_args.dims ());
+      for (octave_idx_type count = 0; count < k ; count++)
+        result(count) = f_args.elem(count).is_empty ();
+      retval(0) = result;
+    }
+  else if (name == "islogical")
+    {
+      boolNDArray result (f_args.dims ());
+      for (octave_idx_type  count= 0; count < k ; count++)
+        result(count) = f_args.elem(count).is_bool_type ();
+      retval(0) = result;
+    }
+  else if (name == "isreal")
+    {
+      boolNDArray result (f_args.dims ());
+      for (octave_idx_type  count= 0; count < k ; count++)
+        result(count) = f_args.elem(count).is_real_type ();
+      retval(0) = result;
+    }
+  else if (name == "length")
+    {
+      NDArray result (f_args.dims ());
+      for (octave_idx_type  count= 0; count < k ; count++)
+        result(count) = static_cast<double> (f_args.elem(count).length ());
+      retval(0) = result;
+    }
+  else if (name == "ndims")
+    {
+      NDArray result (f_args.dims ());
+      for (octave_idx_type count = 0; count < k ; count++)
+        result(count) = static_cast<double> (f_args.elem(count).ndims ());
+      retval(0) = result;
+    }
+  else if (name == "prodofsize" || name == "numel")
+    {
+      NDArray result (f_args.dims ());
+      for (octave_idx_type count = 0; count < k ; count++)
+        result(count) = static_cast<double> (f_args.elem(count).numel ());
+      retval(0) = result;
+    }
+  else if (name == "size")
+    {
+      if (nargin == 3)
+        {
+          int d = args(2).nint_value () - 1;
+
+          if (d < 0)
+            error ("cellfun: K must be a positive integer");
+
+          if (! error_state)
+            {
+              NDArray result (f_args.dims ());
+              for (octave_idx_type count = 0; count < k ; count++)
+                {
+                  dim_vector dv = f_args.elem(count).dims ();
+                  if (d < dv.length ())
+                    result(count) = static_cast<double> (dv(d));
+                  else
+                    result(count) = 1.0;
+                }
+              retval(0) = result;
+            }
+        }
+      else
+        error ("cellfun: not enough arguments for \"size\"");
+    }
+  else if (name == "isclass")
+    {
+      if (nargin == 3)
+        {
+          std::string class_name = args(2).string_value();
+          boolNDArray result (f_args.dims ());
+          for (octave_idx_type count = 0; count < k ; count++)
+            result(count) = (f_args.elem(count).class_name() == class_name);
+
+          retval(0) = result;
+        }
+      else
+        error ("cellfun: not enough arguments for \"isclass\"");
+    }
+
+  return retval;
+}
+
+static void
+get_cellfun_options (const octave_value_list& args, int& nargin,
+                     bool& uniform_output, octave_value& error_handler)
+{
+  while (nargin > 3 && args(nargin-2).is_string ())
+    {
+      std::string arg = args(nargin-2).string_value ();
+
+      std::transform (arg.begin (), arg.end (),
+                      arg.begin (), tolower);
+
+      if (arg == "uniformoutput")
+        uniform_output = args(nargin-1).bool_value();
+      else if (arg == "errorhandler")
+        {
+          if (args(nargin-1).is_function_handle ()
+              || args(nargin-1).is_inline_function ())
+            {
+              error_handler = args(nargin-1);
+            }
+          else if (args(nargin-1).is_string ())
+            {
+              std::string err_name = args(nargin-1).string_value ();
+
+              error_handler = symbol_table::find_function (err_name);
+
+              if (error_handler.is_undefined ())
+                {
+                  error ("cellfun: invalid function NAME: %s",
+                         err_name.c_str ());
+                  break;
+                }
+            }
+          else
+            {
+              error ("cellfun: invalid value for 'ErrorHandler' function");
+              break;
+            }
+        }
+      else
+        {
+          error ("cellfun: unrecognized parameter %s",
+                 arg.c_str());
+          break;
+        }
+
+      nargin -= 2;
+    }
+
+  nargin -= 1;
+}
+
 DEFUN_DLD (cellfun, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Loadable Function} {} cellfun (@var{name}, @var{C})\n\
@@ -235,130 +389,49 @@
 
   if (func.is_string ())
     {
-      const Cell f_args = args(1).cell_value ();
+      retval = try_cellfun_internal_ops (args, nargin);
 
-      octave_idx_type k = f_args.numel ();
-
-      std::string name = func.string_value ();
+      if (error_state || ! retval.empty ())
+        return retval;
 
-      if (name == "isempty")
-        {
-          boolNDArray result (f_args.dims ());
-          for (octave_idx_type count = 0; count < k ; count++)
-            result(count) = f_args.elem(count).is_empty ();
-          retval(0) = result;
-        }
-      else if (name == "islogical")
-        {
-          boolNDArray result (f_args.dims ());
-          for (octave_idx_type  count= 0; count < k ; count++)
-            result(count) = f_args.elem(count).is_bool_type ();
-          retval(0) = result;
-        }
-      else if (name == "isreal")
-        {
-          boolNDArray result (f_args.dims ());
-          for (octave_idx_type  count= 0; count < k ; count++)
-            result(count) = f_args.elem(count).is_real_type ();
-          retval(0) = result;
-        }
-      else if (name == "length")
-        {
-          NDArray result (f_args.dims ());
-          for (octave_idx_type  count= 0; count < k ; count++)
-            result(count) = static_cast<double> (f_args.elem(count).length ());
-          retval(0) = result;
-        }
-      else if (name == "ndims")
-        {
-          NDArray result (f_args.dims ());
-          for (octave_idx_type count = 0; count < k ; count++)
-            result(count) = static_cast<double> (f_args.elem(count).ndims ());
-          retval(0) = result;
-        }
-      else if (name == "prodofsize" || name == "numel")
+      // See if we can convert the string into a function.
+
+      std::string name = args(0).string_value ();
+
+      if (! valid_identifier (name))
         {
-          NDArray result (f_args.dims ());
-          for (octave_idx_type count = 0; count < k ; count++)
-            result(count) = static_cast<double> (f_args.elem(count).numel ());
-          retval(0) = result;
-        }
-      else if (name == "size")
-        {
-          if (nargin == 3)
-            {
-              int d = args(2).nint_value () - 1;
-
-              if (d < 0)
-                error ("cellfun: K must be a positive integer");
+          std::string fcn_name = unique_symbol_name ("__cellfun_fcn_");
+          std::string fname = "function y = " + fcn_name + "(x) y = ";
 
-              if (! error_state)
-                {
-                  NDArray result (f_args.dims ());
-                  for (octave_idx_type count = 0; count < k ; count++)
-                    {
-                      dim_vector dv = f_args.elem(count).dims ();
-                      if (d < dv.length ())
-                        result(count) = static_cast<double> (dv(d));
-                      else
-                        result(count) = 1.0;
-                    }
-                  retval(0) = result;
-                }
-            }
-          else
-            error ("cellfun: not enough arguments for \"size\"");
-        }
-      else if (name == "isclass")
-        {
-          if (nargin == 3)
-            {
-              std::string class_name = args(2).string_value();
-              boolNDArray result (f_args.dims ());
-              for (octave_idx_type count = 0; count < k ; count++)
-                result(count) = (f_args.elem(count).class_name() == class_name);
+          octave_function *ptr_func
+            = extract_function (args(0), "cellfun", fcn_name,
+                                fname, "; endfunction");
 
-              retval(0) = result;
-            }
-          else
-            error ("cellfun: not enough arguments for \"isclass\"");
+          if (ptr_func && ! error_state)
+            func = octave_value (ptr_func, true);
         }
       else
         {
-          if (! valid_identifier (name))
-            {
+          func = symbol_table::find_function (name);
+
+          if (func.is_undefined ())
+            error ("cellfun: invalid function NAME: %s", name.c_str ());
 
-              std::string fcn_name = unique_symbol_name ("__cellfun_fcn_");
-              std::string fname = "function y = ";
-              fname.append (fcn_name);
-              fname.append ("(x) y = ");
-              octave_function *ptr_func = extract_function (args(0), "cellfun",
-                                                            fcn_name, fname, "; endfunction");
-              if (ptr_func && ! error_state)
-                func = octave_value (ptr_func, true);
-            }
-          else
-            {
-              func = symbol_table::find_function (name);
-              if (func.is_undefined ())
-                error ("cellfun: invalid function NAME: %s", name.c_str ());
+          symbol_table_lookup = true;
+        }
 
-              symbol_table_lookup = true;
-            }
-        }
+      if (error_state || ! retval.empty ())
+        return retval;
     }
 
-  if (error_state || ! retval.empty ())
-    return retval;
-
   if (func.is_function_handle () || func.is_inline_function ()
       || func.is_function ())
     {
-
       // The following is an optimisation because the symbol table can
       // give a more specific function class, so this can result in
       // fewer polymorphic function calls as the function gets called
       // for each value of the array.
+
       if (! symbol_table_lookup )
         {
           if (func.is_function_handle ())
@@ -368,6 +441,7 @@
               // Overloaded function handles need to check the type of
               // the arguments for each element of the array, so they
               // cannot be optimised this way.
+
               if (f -> is_overloaded ())
                 goto nevermind;
             }
@@ -376,57 +450,18 @@
           if (f.is_defined ())
             func = f;
         }
-      nevermind:
 
-      unwind_protect frame;
-      frame.protect_var (buffer_error_messages);
+    nevermind:
 
       bool uniform_output = true;
       octave_value error_handler;
-
-      while (nargin > 3 && args(nargin-2).is_string())
-        {
-          std::string arg = args(nargin-2).string_value();
-
-          std::transform (arg.begin (), arg.end (),
-                          arg.begin (), tolower);
+      
+      get_cellfun_options (args, nargin, uniform_output, error_handler);
 
-          if (arg == "uniformoutput")
-            uniform_output = args(nargin-1).bool_value();
-          else if (arg == "errorhandler")
-            {
-              if (args(nargin-1).is_function_handle () ||
-                  args(nargin-1).is_inline_function ())
-                {
-                  error_handler = args(nargin-1);
-                }
-              else if (args(nargin-1).is_string ())
-                {
-                  std::string err_name = args(nargin-1).string_value ();
-                  error_handler = symbol_table::find_function (err_name);
-                  if (error_handler.is_undefined ())
-                    {
-                      error ("cellfun: invalid function NAME: %s", err_name.c_str ());
-                      break;
-                    }
-                }
-              else
-                {
-                  error ("cellfun: invalid value for 'ErrorHandler' function");
-                  break;
-                }
-            }
-          else
-            {
-              error ("cellfun: unrecognized parameter %s",
-                     arg.c_str());
-              break;
-            }
+      if (error_state)
+        return octave_value_list ();
 
-          nargin -= 2;
-        }
-
-      nargin -= 1;
+      // Extract cell arguments.
 
       octave_value_list inputlist (nargin, octave_value ());
 
@@ -440,9 +475,6 @@
 
       dim_vector fdims (1, 1);
 
-      if (error_state)
-        return octave_value_list ();
-
       for (int j = 0; j < nargin; j++)
         {
           if (! args(j+1).is_cell ())
@@ -475,9 +507,14 @@
             }
         }
 
+      unwind_protect frame;
+      frame.protect_var (buffer_error_messages);
+
       if (error_handler.is_defined ())
         buffer_error_messages++;
 
+      // Apply functions.
+
       if (uniform_output)
         {
           std::list<octave_value_list> idx_list (1);
@@ -494,8 +531,9 @@
                     inputlist.xelem (j) = cinputs[j](count);
                 }
 
-              const octave_value_list tmp = get_output_list (count, nargout, inputlist,
-                                                             func, error_handler);
+              const octave_value_list tmp
+                = get_output_list (count, nargout, inputlist, func,
+                                   error_handler);
 
               if (error_state)
                 return retval;
@@ -557,6 +595,7 @@
             }
 
           retval.resize (nargout1);
+
           for (int j = 0; j < nargout1; j++)
             {
               if (nargout > 0 && retv[j].is_undefined ())