diff src/ov.cc @ 9607:1be3c73ed7b5

reuse temporary arrays in nested expressions
author Jaroslav Hajek <highegg@gmail.com>
date Thu, 03 Sep 2009 08:48:51 +0200
parents 1beb23d2b892
children 1c76e806c2a7
line wrap: on
line diff
--- a/src/ov.cc	Thu Sep 03 06:59:53 2009 +0200
+++ b/src/ov.cc	Thu Sep 03 08:48:51 2009 +0200
@@ -474,6 +474,44 @@
   return retval;
 }
 
+octave_value::assign_op
+octave_value::binary_op_to_assign_op (binary_op op)
+{
+  assign_op retval;
+
+  switch (op)
+    {
+    case op_add:
+      retval = op_add_eq;
+      break;
+    case op_sub:
+      retval = op_sub_eq;
+      break;
+    case op_mul:
+      retval = op_mul_eq;
+      break;
+    case op_div:
+      retval = op_div_eq;
+      break;
+    case op_el_mul:
+      retval = op_el_mul_eq;
+      break;
+    case op_el_div:
+      retval = op_el_div_eq;
+      break;
+    case op_el_and:
+      retval = op_el_and_eq;
+      break;
+    case op_el_or:
+      retval = op_el_or_eq;
+      break;
+    default:
+      retval = unknown_assign_op;
+    }
+
+  return retval;
+}
+
 octave_value::octave_value (short int i)
   : rep (new octave_scalar (i))
 {
@@ -2246,77 +2284,104 @@
 const octave_value&
 octave_value::do_non_const_unary_op (unary_op op)
 {
-  octave_value retval;
-
-  int t = type_id ();
-
-  octave_value_typeinfo::non_const_unary_op_fcn f
-    = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
-
-  if (f)
+  if (op == op_incr || op == op_decr)
     {
-      make_unique ();
-
-      try
-	{
-	  f (*rep);
-	}
-      catch (octave_execution_exception)
-	{
-	  gripe_library_execution_error ();
-	}
+      // Genuine.
+      int t = type_id ();
+
+      octave_value_typeinfo::non_const_unary_op_fcn f
+        = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
+
+      if (f)
+        {
+          make_unique ();
+
+          try
+            {
+              f (*rep);
+            }
+          catch (octave_execution_exception)
+            {
+              gripe_library_execution_error ();
+            }
+        }
+      else
+        {
+          octave_base_value::type_conv_fcn cf = numeric_conversion_function ();
+
+          if (cf)
+            {
+              octave_base_value *tmp = cf (*rep);
+
+              if (tmp)
+                {
+                  octave_base_value *old_rep = rep;
+                  rep = tmp;
+
+                  t = type_id ();
+
+                  f = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
+
+                  if (f)
+                    {
+                      try
+                        {
+                          f (*rep);
+                        }
+                      catch (octave_execution_exception)
+                        {
+                          gripe_library_execution_error ();
+                        }
+
+                      if (old_rep && --old_rep->count == 0)
+                        delete old_rep;
+                    }
+                  else
+                    {
+                      if (old_rep)
+                        {
+                          if (--rep->count == 0)
+                            delete rep;
+
+                          rep = old_rep;
+                        }
+
+                      gripe_unary_op (octave_value::unary_op_as_string (op),
+                                      type_name ());
+                    }
+                }
+              else
+                gripe_unary_op_conversion_failed
+                  (octave_value::unary_op_as_string (op), type_name ());
+            }
+          else
+            gripe_unary_op (octave_value::unary_op_as_string (op), type_name ());
+        }
     }
   else
     {
-      octave_base_value::type_conv_fcn cf = numeric_conversion_function ();
-
-      if (cf)
-	{
-	  octave_base_value *tmp = cf (*rep);
-
-	  if (tmp)
-	    {
-	      octave_base_value *old_rep = rep;
-	      rep = tmp;
-
-	      t = type_id ();
-
-	      f = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
-
-	      if (f)
-		{
-		  try
-		    {
-		      f (*rep);
-		    }
-		  catch (octave_execution_exception)
-		    {
-		      gripe_library_execution_error ();
-		    }
-
-		  if (old_rep && --old_rep->count == 0)
-		    delete old_rep;
-		}
-	      else
-		{
-		  if (old_rep)
-		    {
-		      if (--rep->count == 0)
-			delete rep;
-
-		      rep = old_rep;
-		    }
-
-		  gripe_unary_op (octave_value::unary_op_as_string (op),
-				  type_name ());
-		}
-	    }
-	  else
-	    gripe_unary_op_conversion_failed
-	      (octave_value::unary_op_as_string (op), type_name ());
-	}
+      // Non-genuine.
+      int t = type_id ();
+
+      octave_value_typeinfo::non_const_unary_op_fcn f = 0;
+
+      // Only attempt to operate in-place if this variable is unshared.
+      if (rep->count == 1)
+        f = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
+
+      if (f)
+        {
+          try
+            {
+              f (*rep);
+            }
+          catch (octave_execution_exception)
+            {
+              gripe_library_execution_error ();
+            }
+        }
       else
-	gripe_unary_op (octave_value::unary_op_as_string (op), type_name ());
+        *this = do_unary_op (op, *this);
     }
 
   return *this;