changeset 8580:188d38a553c7

further indexing optimization touches
author Jaroslav Hajek <highegg@gmail.com>
date Fri, 23 Jan 2009 13:13:39 +0100
parents 7e0f36dfefbe
children 6adcafc70c32
files liboctave/Array.cc liboctave/ChangeLog src/ChangeLog src/oct-obj.cc src/oct-obj.h src/ov-cell.cc src/ov-struct.cc src/ov-usr-fcn.cc src/pt-arg-list.cc src/pt-assign.cc src/pt-idx.cc src/symtab.cc
diffstat 12 files changed, 129 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array.cc	Fri Jan 23 09:57:19 2009 +0100
+++ b/liboctave/Array.cc	Fri Jan 23 13:13:39 2009 +0100
@@ -1216,13 +1216,18 @@
       // Try to resize first if necessary. 
       if (nx != n)
         {
-          // A simple optimization. Things like A(1:N) = x will skip fill on
-          // resizing, if A is 0x0.
+          // Optimize case A = []; A(1:n) = X with A empty. 
           if (rows () == 0 && columns () == 0 && ndims () == 2
-              && rhl == 1 && i.is_colon_equiv (nx))
-            *this = Array<T> (dim_vector (1, nx));
-          else
-            resize_fill (nx, rfv);      
+              && i.is_colon_equiv (nx))
+            {
+              if (rhl == 1)
+                *this = Array<T> (dim_vector (1, nx), rhs(0));
+              else
+                *this = Array<T> (rhs, dim_vector (1, nx));
+              return;
+            }
+
+          resize_fill (nx, rfv);      
           n = numel ();
         }
 
@@ -1284,6 +1289,17 @@
       // Resize if requested.
       if (rdv != dv)
         {
+          // Optimize case A = []; A(1:m, 1:n) = X
+          if (dv.all_zero () && i.is_colon_equiv (rdv(0))
+              && j.is_colon_equiv (rdv(1)))
+            {
+              if (isfill)
+                *this = Array<T> (rdv, rhs(0));
+              else
+                *this = Array<T> (rhs, rdv);
+              return;
+            }
+
           resize (rdv, rfv);
           dv = dimensions;
         }
--- a/liboctave/ChangeLog	Fri Jan 23 09:57:19 2009 +0100
+++ b/liboctave/ChangeLog	Fri Jan 23 13:13:39 2009 +0100
@@ -1,3 +1,10 @@
+2009-01-23  Jaroslav Hajek  <highegg@gmail.com>
+
+	* Array.cc (Array<T>::assign (const idx_vector&, const Array<T>&)):
+	Optimize assignment to an empty array.
+	(Array<T>::assign (const idx_vector&, const idx_vector&, const Array<T>&)):
+	Optimize assignment to an empty array.
+
 2009-01-22  Jaroslav Hajek  <highegg@gmail.com>
 
 	* Array2.h (Array2<T>::index): Declare resize_ok as bool.
--- a/src/ChangeLog	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/ChangeLog	Fri Jan 23 13:13:39 2009 +0100
@@ -4,10 +4,22 @@
 	New functions.
 	* gripes.h: Declare them.
 	* pt-idx.cc: Remove definitions of the above funcs.
-	* ov-cell.cc (octave_cell::subsasgn): Remove dead branch.
-	* ov-struct.cc (octave_struct::subsasgn): Remove dead branch.
+	* ov-cell.cc (octave_cell::subsref): Declare constants as const.
+	(octave_cell::subsasgn): Remove dead branch, declare constants as const.
+	(octave_cell::list_value): Optimize.
+	* ov-struct.cc 
+	(octave_struct::subsref): Declare constants as const.
+	(octave_struct::subsasgn): Remove dead branch, declare constants as const.
 	* ov-cs-list.cc (octave_cs_list::octave_cs_list (const Cell&)):
 	Optimize.
+	* oct-obj.cc (octave_value_list::octave_value_list (const
+	std::list<octave_value_list>&)): New constructor.
+	* oct-obj.h: Declare it.
+	* pt-arg-list.cc (convert_to_const_vector): Optimize.
+	* symtab.cc (symbol_table::fcn_info::fcn_info_rep::find): Use const
+	reference to avoid redundant copy.
+	* ov-usr-fcn.cc (octave_user_function::bind_automatic_vars): Optimize.
+	(octave_user_function::octave_all_va_args): Optimize.
 
 2009-01-22  Jaroslav Hajek  <highegg@gmail.com>
 
--- a/src/oct-obj.cc	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/oct-obj.cc	Fri Jan 23 13:13:39 2009 +0100
@@ -2,6 +2,7 @@
 
 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003,
               2004, 2005, 2006, 2007 John W. Eaton
+Copyright (C) 2009 VZLU Prague
 
 This file is part of Octave.
 
@@ -29,6 +30,36 @@
 #include "oct-obj.h"
 #include "Cell.h"
 
+octave_value_list::octave_value_list (const std::list<octave_value_list>& lst)
+{
+  octave_idx_type n = 0, nel = 0;
+
+  // Determine number.
+  for (std::list<octave_value_list>::const_iterator p = lst.begin ();
+       p != lst.end (); p++)
+    {
+      n++;
+      nel += p->length ();
+    }
+
+  // Optimize single-element case
+  if (n == 1)
+    data = lst.front ().data;
+  else if (nel > 0)
+    {
+      data.resize (nel);
+      octave_idx_type k = 0;
+      for (std::list<octave_value_list>::const_iterator p = lst.begin ();
+           p != lst.end (); p++)
+        {
+          data.assign (idx_vector (k, k + p->length ()), p->data);
+          k += p->length ();
+        }
+      assert (k == nel);
+    }
+
+}
+
 octave_allocator
 octave_value_list::allocator (sizeof (octave_value_list));
 
--- a/src/oct-obj.h	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/oct-obj.h	Fri Jan 23 13:13:39 2009 +0100
@@ -2,6 +2,7 @@
 
 Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2003, 2004,
               2005, 2006, 2007 John W. Eaton
+Copyright (C) 2009 VZLU Prague
 
 This file is part of Octave.
 
@@ -58,6 +59,9 @@
   octave_value_list (const octave_value_list& obj)
     : data (obj.data), names (obj.names) { }
 
+  // Concatenation constructor.
+  octave_value_list (const std::list<octave_value_list>&);
+
   ~octave_value_list (void) { }
 
   void *operator new (size_t size)
--- a/src/ov-cell.cc	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/ov-cell.cc	Fri Jan 23 13:13:39 2009 +0100
@@ -136,7 +136,7 @@
 
 	if (! error_state)
 	  {
-	    Cell tcell = tmp.cell_value ();
+	    const Cell tcell = tmp.cell_value ();
 
 	    if (tcell.length () == 1)
 	      retval = tcell(0,0);
@@ -231,12 +231,16 @@
                 if (tmpc.numel () == 1)
 		  {
 		    octave_value tmp = tmpc(0);
+                    tmpc = Cell ();
 
 		    if (! tmp.is_defined () || tmp.is_zero_by_zero ())
-                      tmp = octave_value::empty_conv (type.substr (1), rhs);
+                      {
+                        tmp = octave_value::empty_conv (type.substr (1), rhs);
+                        tmp.make_unique (); // probably a no-op.
+                      }
                     else
-                      // optimization: ignore the copy still stored inside our array and in tmpc.
-                      tmp.make_unique (2);
+                      // optimization: ignore the copy still stored inside our array. 
+                      tmp.make_unique (1);
 
 		    if (! error_state)
 		      t_rhs = tmp.subsasgn (next_type, next_idx, rhs);
@@ -356,29 +360,7 @@
 octave_value_list
 octave_cell::list_value (void) const
 {
-  octave_value_list retval;
-
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = columns ();
-
-  if (nr == 1 && nc > 0)
-    {
-      retval.resize (nc);
-
-      for (octave_idx_type i = 0; i < nc; i++)
-	retval(i) = matrix(0,i);
-    }
-  else if (nc == 1 && nr > 0)
-    {
-      retval.resize (nr);
-
-      for (octave_idx_type i = 0; i < nr; i++)
-	retval(i) = matrix(i,0);
-    }
-  else
-    error ("invalid conversion from cell array to list");
-
-  return retval;
+  return octave_value_list (matrix);
 }
 
 string_vector
--- a/src/ov-struct.cc	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/ov-struct.cc	Fri Jan 23 13:13:39 2009 +0100
@@ -117,11 +117,11 @@
 	    std::list<octave_value_list>::const_iterator p = idx.begin ();
 	    octave_value_list key_idx = *++p;
 
-	    Cell tmp = dotref (key_idx);
+	    const Cell tmp = dotref (key_idx);
 
 	    if (! error_state)
 	      {
-		Cell t = tmp.index (idx.front ());
+		const Cell t = tmp.index (idx.front ());
 
 		retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true);
 
@@ -140,7 +140,7 @@
       {
 	if (map.numel() > 0)
 	  {
-	    Cell t = dotref (idx.front ());
+	    const Cell t = dotref (idx.front ());
 
 	    retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true);
 	  }
@@ -183,11 +183,11 @@
 	    std::list<octave_value_list>::const_iterator p = idx.begin ();
 	    octave_value_list key_idx = *++p;
 
-	    Cell tmp = dotref (key_idx, auto_add);
+	    const Cell tmp = dotref (key_idx, auto_add);
 
 	    if (! error_state)
 	      {
-		Cell t = tmp.index (idx.front (), auto_add);
+		const Cell t = tmp.index (idx.front (), auto_add);
 
 		retval = (t.length () == 1) ? t(0) : octave_value (t, true);
 
@@ -206,7 +206,7 @@
       {
 	if (map.numel() > 0)
 	  {
-	    Cell t = dotref (idx.front (), auto_add);
+	    const Cell t = dotref (idx.front (), auto_add);
 
 	    retval = (t.length () == 1) ? t(0) : octave_value (t, true);
 	  }
@@ -296,7 +296,6 @@
 
                 // cast map to const reference to avoid forced key insertion.
                 Cell tmpc = cmap.contents (key).index (idx.front (), true);
-                tmpc.make_unique ();
 
                 // FIXME: better code reuse? cf. octave_cell::subsasgn and the case below.
 		if (! error_state)
@@ -304,6 +303,7 @@
                     if (tmpc.numel () == 1)
                       {
                         octave_value tmp = tmpc(0);
+                        tmpc = Cell ();
 
                         if (! tmp.is_defined () || tmp.is_zero_by_zero ())
                           {
@@ -311,8 +311,8 @@
                             tmp.make_unique (); // probably a no-op.
                           }
                         else
-                          // optimization: ignore the copy still stored inside our map and in tmpc.
-                          tmp.make_unique (2);
+                          // optimization: ignore the copy still stored inside our map.
+                          tmp.make_unique (1);
 
                         if (! error_state)
                           t_rhs = tmp.subsasgn (next_type, next_idx, rhs);
@@ -340,10 +340,8 @@
 
             std::string next_type = type.substr (1);
 
-            Cell tmpc1 = octave_value ();
-            Cell& tmpc = (map.contains (key)) ? map.contents (key) : tmpc1;
-
-            tmpc.make_unique ();
+            Cell tmpc (1, 1);
+            if (map.contains (key)) tmpc = cmap.contents (key);
 
             // FIXME: better code reuse?
             if (! error_state)
@@ -351,10 +349,11 @@
                 if (tmpc.numel () == 1)
                   {
                     octave_value tmp = tmpc(0);
+                    tmpc = Cell ();
 
                     if (! tmp.is_defined () || tmp.is_zero_by_zero ())
                       {
-                        tmp = octave_value::empty_conv (type.substr (1), rhs);
+                        tmp = octave_value::empty_conv (next_type, rhs);
                         tmp.make_unique (); // probably a no-op.
                       }
                     else
--- a/src/ov-usr-fcn.cc	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/ov-usr-fcn.cc	Fri Jan 23 13:13:39 2009 +0100
@@ -263,16 +263,10 @@
 {
   octave_value_list retval;
 
-  int n = num_args_passed - num_named_args;
+  octave_idx_type n = num_args_passed - num_named_args;
 
   if (n > 0)
-    {
-      retval.resize (n);
-
-      int k = 0;
-      for (int i = num_named_args; i < num_args_passed; i++)
-	retval(k++) = args_passed(i);
-    }
+    retval = args_passed.slice (num_named_args, n);
 
   return retval;
 }
@@ -539,16 +533,7 @@
   symbol_table::mark_hidden (".nargout.");
 
   if (takes_varargs ())
-    {
-      int n = va_args.length ();
-
-      Cell varargin (1, n);
-
-      for (int i = 0; i < n; i++)
-	varargin(0,i) = va_args(i);
-
-      symbol_table::varref ("varargin") = varargin;
-    }
+    symbol_table::varref ("varargin") = va_args.cell_value ();
 }
 
 DEFUN (nargin, args, ,
--- a/src/pt-arg-list.cc	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/pt-arg-list.cc	Fri Jan 23 13:13:39 2009 +0100
@@ -174,12 +174,9 @@
 
   int len = length ();
 
-  octave_value_list args;
-  int args_len = len;
-  args.resize (args_len);
+  std::list<octave_value_list> args;
 
   iterator p = begin ();
-  int j = 0;
   for (int k = 0; k < len; k++)
     {
       if (stash_object)
@@ -200,33 +197,24 @@
 	  if (error_state)
 	    {
 	      ::error ("evaluating argument list element number %d", k+1);
-	      args = octave_value_list ();
+	      args.clear ();
 	      break;
 	    }
 	  else
 	    {
 	      if (tmp.is_cs_list ())
-		{
-		  octave_value_list tl = tmp.list_value ();
-		  int n = tl.length ();
-		  args_len += n - 1;
-		  args.resize (args_len);
-		  for (int i = 0; i < n; i++)
-		    args(j++) = tl(i);
-		}
+                args.push_back (tmp.list_value ());
 	      else if (tmp.is_defined ())
-		args(j++) = tmp;
+                args.push_back (tmp);
 	    }
 	}
       else
 	{
-	  args(j++) = octave_value ();
+	  args.push_back (octave_value ());
 	  break;
 	}
     }
 
-  args.resize (j);
-
   if (stash_object)
     unwind_protect::run_frame ("convert_to_const_vector");
 
--- a/src/pt-assign.cc	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/pt-assign.cc	Fri Jan 23 13:13:39 2009 +0100
@@ -217,7 +217,7 @@
 	    {
 	      if (rhs_val.is_cs_list ())
 		{
-		  octave_value_list lst = rhs_val.list_value ();
+		  const octave_value_list lst = rhs_val.list_value ();
 
 		  if (! lst.empty ())
 		    rhs_val = lst(0);
@@ -315,7 +315,7 @@
 {
   octave_value retval;
 
-  octave_value_list tmp = rvalue (1);
+  const octave_value_list tmp = rvalue (1);
 
   if (! tmp.empty ())
     retval = tmp(0);
@@ -359,7 +359,10 @@
 	   p++)
 	n_out += p->numel ();
 
-      octave_value_list rhs_val = rhs->rvalue (n_out);
+      // The following trick is used to keep rhs_val constant.
+      const octave_value_list rhs_val1 = rhs->rvalue (n_out);
+      const octave_value_list rhs_val = (rhs_val1.length () == 1 && rhs_val1(0).is_cs_list ()
+                                         ? rhs_val1(0).list_value () : rhs_val1);
 
       if (error_state)
 	return retval;
@@ -378,18 +381,9 @@
 
 	  octave_idx_type n = rhs_val.length ();
 
-	  if (n == 1)
-	    {
-	      octave_value tmp = rhs_val(0);
-
-	      if (tmp.is_cs_list ())
-		{
-		  rhs_val = tmp.list_value ();
-		  n = rhs_val.length ();
-		}
-	    }
-
-	  retval.resize (n, octave_value ());
+          // To avoid copying per elements and possible optimizations, we
+          // postpone joining the final values.
+          std::list<octave_value_list> retval_list;
 
 	  tree_argument_list::iterator q = lhs->begin ();
 
@@ -409,17 +403,14 @@
 		    {
 		      if (etype == octave_value::op_asn_eq)
 			{
-			  octave_value_list ovl (nel, octave_value ());
-
-			  for (octave_idx_type j = 0; j < nel; j++)
-			    ovl(j) = rhs_val(k+j);
+                          // This won't do a copy.
+			  octave_value_list ovl  = rhs_val.slice (k, nel);
 
 			  ult.assign (etype, octave_value (ovl, true));
 
 			  if (! error_state)
 			    {
-			      for (octave_idx_type j = 0; j < nel; j++)
-				retval(k+j) = rhs_val(k+j);
+                              retval_list.push_back (ovl);
 
 			      k += nel;
 			    }
@@ -443,9 +434,9 @@
 		      if (! error_state)
 			{
 			  if (etype == octave_value::op_asn_eq)
-			    retval(k) = rhs_val(k);
+                            retval_list.push_back (rhs_val(k));
 			  else
-			    retval(k) = ult.value ();
+                            retval_list.push_back (ult.value ());
 
 			  k++;
 			}
@@ -476,6 +467,9 @@
 		break;
 
 	    }
+          
+          // Concatenate return values.
+          retval = retval_list;
 	}
     }
 
--- a/src/pt-idx.cc	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/pt-idx.cc	Fri Jan 23 13:13:39 2009 +0100
@@ -331,7 +331,7 @@
 		  // that argument list so we can pass the appropriate
 		  // value to the built-in __end__ function.
 
-		  octave_value_list tmp_list
+		  const octave_value_list tmp_list
 		    = tmp.subsref (type.substr (tmpi, i - tmpi), idx, nargout);
 
 		  tmp = tmp_list(0);
@@ -390,7 +390,7 @@
 {
   octave_value retval;
 
-  octave_value_list tmp = rvalue (1);
+  const octave_value_list tmp = rvalue (1);
 
   if (! tmp.empty ())
     retval = tmp(0);
--- a/src/symtab.cc	Fri Jan 23 09:57:19 2009 +0100
+++ b/src/symtab.cc	Fri Jan 23 13:13:39 2009 +0100
@@ -631,7 +631,8 @@
 
   if (args_evaluated && ! dispatch_map.empty ())
     {
-      std::string dispatch_type = evaluated_args(0).type_name ();
+      std::string dispatch_type = 
+        const_cast<const octave_value_list&>(evaluated_args)(0).type_name ();
 
       std::string fname;