changeset 17004:19b7c7412a63

cell2mat.m: Re-vamp input validation for 30% speedup * scripts/general/cell2mat.m: Use if tree to only call cellfun if necessary to further validate inputs. Add %!error tests for input validation. Use standard variable name 'sz' for size of object. * libinterp/corefcn/cellfun.cc(try_cellfun_internal_ops): Put test for 'numel' ahead of test for 'prodofsize' since it is the more common usage.
author Rik <rik@octave.org>
date Thu, 18 Jul 2013 12:05:34 -0700
parents c6a39f7f193d
children b3d4edc991c0
files libinterp/corefcn/cellfun.cc scripts/general/cell2mat.m
diffstat 2 files changed, 27 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/cellfun.cc	Thu Jul 18 12:01:32 2013 -0700
+++ b/libinterp/corefcn/cellfun.cc	Thu Jul 18 12:05:34 2013 -0700
@@ -161,7 +161,7 @@
         result(count) = static_cast<double> (f_args.elem (count).ndims ());
       retval(0) = result;
     }
-  else if (name == "prodofsize" || name == "numel")
+  else if (name == "numel" || name == "prodofsize")
     {
       NDArray result (f_args.dims ());
       for (octave_idx_type count = 0; count < k; count++)
--- a/scripts/general/cell2mat.m	Thu Jul 18 12:01:32 2013 -0700
+++ b/scripts/general/cell2mat.m	Thu Jul 18 12:05:34 2013 -0700
@@ -21,8 +21,8 @@
 ## @deftypefn {Function File} {@var{m} =} cell2mat (@var{c})
 ## Convert the cell array @var{c} into a matrix by concatenating all
 ## elements of @var{c} into a hyperrectangle.  Elements of @var{c} must
-## be numeric, logical or char matrices, or cell arrays, and @code{cat}
-## must be able to concatenate them together.
+## be numeric, logical, or char matrices; or cell arrays; or structs; and
+## @code{cat} must be able to concatenate them together.
 ## @seealso{mat2cell, num2cell}
 ## @end deftypefn
 
@@ -42,20 +42,24 @@
     m = [];
   else
 
-    ## We only want numeric, logical, and char matrices.
+    ## Check first for valid matrix types
     valid = cellfun ("isnumeric", c);
-    valid |= cellfun ("islogical", c);
-    valid |= cellfun ("isclass", c, "char");
-    validc = cellfun ("isclass", c, "cell");
-    valids = cellfun ("isclass", c, "struct");
-
-    if (! all (valid(:)) && ! all (validc(:)) && ! all (valids(:)))
-      error ("cell2mat: wrong type elements or mixed cells, structs and matrices");
+    valid = cellfun ("islogical", c(! valid));
+    valid = cellfun ("isclass", c(! valid), "char");
+    if (! all (valid(:)))
+      valid = cellfun ("isclass", c, "cell");
+      if (! all (valid(:)))
+        valid = cellfun ("isclass", c, "struct");
+        if (! all (valid(:)))
+          error ("cell2mat: wrong type elements or mixed cells, structs, and matrices");
+        endif
+      endif
     endif
 
-    sc = size (c);
+    sz = size (c);
     if (all (cellfun ("numel", c)(:) == 1))
-      m = reshape (cat (1, c{:}), sc);
+      ## Special case of all scalars
+      m = reshape (cat (1, c{:}), sz);
     else
 
       ## The goal is to minimize the total number of cat() calls.
@@ -68,9 +72,9 @@
       ## This is minimized if d1 >= d2 >= d3...
 
       nd = ndims (c);
-      [~, isc] = sort (sc, "descend");
-      for idim = isc
-        if (sc(idim) == 1)
+      [~, isz] = sort (sz, "descend");
+      for idim = isz
+        if (sz(idim) == 1)
           continue;
         endif
         xdim = [1:idim-1, idim+1:nd];
@@ -109,3 +113,10 @@
 %! m = {1, 2, 3};
 %! assert (cell2mat (mat2cell (m, 1, [1 1 1])), m);
 
+%!error cell2mat ()
+%!error cell2mat (1,2)
+%!error <C is not a cell array> cell2mat ([1,2])
+%!error <mixed cells, structs, and matrices> cell2mat ({[1], struct()})
+%!error <mixed cells, structs, and matrices> cell2mat ({[1], {1}})
+%!error <mixed cells, structs, and matrices> cell2mat ({struct(), {1}})
+