changeset 9546:1beb23d2b892

optimize op= in common cases
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 19 Aug 2009 13:47:59 +0200
parents 8670e55078fd
children 588c6bb6fdcb
files liboctave/Array.cc liboctave/Array.h liboctave/CNDArray.cc liboctave/CNDArray.h liboctave/ChangeLog liboctave/MArray-decl.h liboctave/MArray-defs.h liboctave/MArray.cc liboctave/MArray2.cc liboctave/MArrayN.cc liboctave/fCNDArray.cc liboctave/fCNDArray.h src/ChangeLog src/OPERATORS/op-cm-cm.cc src/OPERATORS/op-cm-cs.cc src/OPERATORS/op-cm-s.cc src/OPERATORS/op-fcm-fcm.cc src/OPERATORS/op-fcm-fcs.cc src/OPERATORS/op-fcm-fs.cc src/OPERATORS/op-fm-fm.cc src/OPERATORS/op-fm-fs.cc src/OPERATORS/op-int.h src/OPERATORS/op-m-m.cc src/OPERATORS/op-m-s.cc src/ops.h src/ov-base-mat.h src/ov.cc
diffstat 27 files changed, 375 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/Array.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -111,6 +111,21 @@
 }
 
 template <class T>
+void
+Array<T>::clear (void)
+{
+  if (--rep->count <= 0)
+    delete rep;
+
+  rep = nil_rep ();
+  rep->count++; 
+  slice_data = rep->data;
+  slice_len = rep->len;
+
+  dimensions = dim_vector ();
+}
+
+template <class T>
 Array<T>
 Array<T>::squeeze (void) const
 {
--- a/liboctave/Array.h	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/Array.h	Wed Aug 19 13:47:59 2009 +0200
@@ -238,6 +238,7 @@
   Array<T>& operator = (const Array<T>& a);
 
   void fill (const T& val); 
+  void clear (void);
 
   octave_idx_type capacity (void) const { return slice_len; }
   octave_idx_type length (void) const { return capacity (); }
@@ -440,6 +441,8 @@
 
   T *fortran_vec (void);
 
+  bool is_shared (void) { return rep->count > 1; }
+
   int ndims (void) const { return dimensions.length (); }
 
   void maybe_delete_dims (void);
--- a/liboctave/CNDArray.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/CNDArray.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -36,6 +36,7 @@
 #include "functor.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
+#include "MArray-defs.h"
 #include "mx-base.h"
 #include "mx-op-defs.h"
 #include "oct-fftw.h"
@@ -1083,6 +1084,22 @@
 NDND_CMP_OPS(ComplexNDArray, std::real, ComplexNDArray, std::real)
 NDND_BOOL_OPS(ComplexNDArray, ComplexNDArray, 0.0)
 
+ComplexNDArray& operator *= (ComplexNDArray& a, double s)
+{
+  if (a.is_shared ())
+    return a = a * s;
+  DO_VS_OP2 (Complex, a, *=, s)
+  return a;
+}
+
+ComplexNDArray& operator /= (ComplexNDArray& a, double s)
+{
+  if (a.is_shared ())
+    return a = a / s;
+  DO_VS_OP2 (Complex, a, /=, s)
+  return a;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/CNDArray.h	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/CNDArray.h	Wed Aug 19 13:47:59 2009 +0200
@@ -173,6 +173,9 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, ComplexNDArray, Complex)
 
+extern OCTAVE_API ComplexNDArray& operator *= (ComplexNDArray& a, double s);
+extern OCTAVE_API ComplexNDArray& operator /= (ComplexNDArray& a, double s);
+
 #endif
 
 /*
--- a/liboctave/ChangeLog	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/ChangeLog	Wed Aug 19 13:47:59 2009 +0200
@@ -1,3 +1,26 @@
+2009-08-19  Jaroslav Hajek  <highegg@gmail.com>
+
+	* Array.cc (Array<T>::clear): New method.
+	* Array.h: Declare it.
+	* MArray-decl.h (MARRAY_OP_ASSIGN_DECLS1, MARRAY_OP_ASSIGN_FWD_DECLS1,
+	MARRAY_OP_ASSIGN_FRIENDS1, MARRAY_OP_ASSIGN_FWD_DEFS1): New macros.
+	(MARRAY_OPS_FORWARD_DECLS, MARRAY_OPS_FRIEND_DECLS): Use them.
+	* MArray-defs.h (MARRAY_OP_ASSIGN_DEFS1): New macro.
+	(INSTANTIATE_MARRAY_FRIENDS): Use it.
+	(INSTANTIATE_MARRAY2_FRIENDS): Use it.
+	(INSTANTIATE_MARRAYN_FRIENDS): Use it.
+	* MArray.cc (operator+=, operator-=):
+	Operate out-of-place when this is shared copy.
+	(operator*=, operator/=): New operator overloads.
+	* MArray2.cc: Ditto.
+	* MArrayN.cc: Ditto.
+	* CNDArray.cc (operator *= (ComplexNDArray&, double),
+	operator /= (ComplexNDArray&, double)): New operators.
+	* CNDArray.h: Declare them.
+	* fCNDArray.cc (operator *= (FloatComplexNDArray&, double),
+	operator /= (FloatComplexNDArray&, double)): New operators.
+	* fCNDArray.h: Declare them.
+
 2009-08-17  John W. Eaton  <jwe@octave.org>
 
 	* Makefile.in (LINK_DEPS): List LIBS last.
--- a/liboctave/MArray-decl.h	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/MArray-decl.h	Wed Aug 19 13:47:59 2009 +0200
@@ -33,14 +33,26 @@
   MARRAY_OP_ASSIGN_DECL (A_T, E_T, +=, PFX, API, LTGT, RHS_T); \
   MARRAY_OP_ASSIGN_DECL (A_T, E_T, -=, PFX, API, LTGT, RHS_T);
 
+#define MARRAY_OP_ASSIGN_DECLS1(A_T, E_T, PFX, API, LTGT, RHS_T) \
+  MARRAY_OP_ASSIGN_DECL (A_T, E_T, +=, PFX, API, LTGT, RHS_T); \
+  MARRAY_OP_ASSIGN_DECL (A_T, E_T, -=, PFX, API, LTGT, RHS_T); \
+  MARRAY_OP_ASSIGN_DECL (A_T, E_T, *=, PFX, API, LTGT, RHS_T); \
+  MARRAY_OP_ASSIGN_DECL (A_T, E_T, /=, PFX, API, LTGT, RHS_T);
+
 // Generate forward declarations for OP= operators.
 #define MARRAY_OP_ASSIGN_FWD_DECLS(A_T, RHS_T, API) \
   MARRAY_OP_ASSIGN_DECLS (A_T, T, template <typename T>, API, , RHS_T)
 
+#define MARRAY_OP_ASSIGN_FWD_DECLS1(A_T, RHS_T, API) \
+  MARRAY_OP_ASSIGN_DECLS1 (A_T, T, template <typename T>, API, , RHS_T)
+
 // Generate friend declarations for the OP= operators.
 #define MARRAY_OP_ASSIGN_FRIENDS(A_T, RHS_T, API) \
   MARRAY_OP_ASSIGN_DECLS (A_T, T, friend, API, <>, RHS_T)
 
+#define MARRAY_OP_ASSIGN_FRIENDS1(A_T, RHS_T, API) \
+  MARRAY_OP_ASSIGN_DECLS1 (A_T, T, friend, API, <>, RHS_T)
+
 // A function that can be used to forward OP= operations from derived
 // classes back to us.
 #define MARRAY_OP_ASSIGN_FWD_FCN(R, F, T, C_X, X_T, C_Y, Y_T) \
@@ -55,6 +67,12 @@
   MARRAY_OP_ASSIGN_FWD_FCN (R, operator +=, T, C_X, X_T, C_Y, Y_T) \
   MARRAY_OP_ASSIGN_FWD_FCN (R, operator -=, T, C_X, X_T, C_Y, Y_T)
 
+#define MARRAY_OP_ASSIGN_FWD_DEFS1(R, T, C_X, X_T, C_Y, Y_T) \
+  MARRAY_OP_ASSIGN_FWD_FCN (R, operator +=, T, C_X, X_T, C_Y, Y_T) \
+  MARRAY_OP_ASSIGN_FWD_FCN (R, operator -=, T, C_X, X_T, C_Y, Y_T) \
+  MARRAY_OP_ASSIGN_FWD_FCN (R, operator *=, T, C_X, X_T, C_Y, Y_T) \
+  MARRAY_OP_ASSIGN_FWD_FCN (R, operator /=, T, C_X, X_T, C_Y, Y_T)
+
 // A macro that can be used to declare and instantiate unary operators.
 #define MARRAY_UNOP(A_T, E_T, F, PFX, API, LTGT) \
   PFX API A_T<E_T> \
@@ -182,7 +200,7 @@
   template <class T> \
   class A_T; \
  \
-  MARRAY_OP_ASSIGN_FWD_DECLS (A_T, T, API) \
+  MARRAY_OP_ASSIGN_FWD_DECLS1 (A_T, T, API) \
   MARRAY_OP_ASSIGN_FWD_DECLS (A_T, A_T<T>, API) \
   MARRAY_UNOP_FWD_DECLS (A_T, API) \
   MARRAY_BINOP_FWD_DECLS (A_T, API)
@@ -197,7 +215,7 @@
 
 // Friend declarations for the MArray operators.
 #define MARRAY_OPS_FRIEND_DECLS(A_T, API) \
-  MARRAY_OP_ASSIGN_FRIENDS (A_T, T, API) \
+  MARRAY_OP_ASSIGN_FRIENDS1 (A_T, T, API) \
   MARRAY_OP_ASSIGN_FRIENDS (A_T, A_T<T>, API) \
   MARRAY_UNOP_FRIENDS (A_T, API) \
   MARRAY_BINOP_FRIENDS (A_T, API)
--- a/liboctave/MArray-defs.h	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/MArray-defs.h	Wed Aug 19 13:47:59 2009 +0200
@@ -77,6 +77,9 @@
 #define MARRAY_OP_ASSIGN_DEFS(A_T, E_T, RHS_T, API) \
   MARRAY_OP_ASSIGN_DECLS (A_T, E_T, template, API, , RHS_T)
 
+#define MARRAY_OP_ASSIGN_DEFS1(A_T, E_T, RHS_T, API) \
+  MARRAY_OP_ASSIGN_DECLS1 (A_T, E_T, template, API, , RHS_T)
+
 // Instantiate the unary operators.
 #define MARRAY_UNOP_DEFS(A_T, E_T, API) \
   MARRAY_UNOP_DECLS (A_T, E_T, template, API, )
@@ -96,21 +99,21 @@
 
 // Instantiate all the MArray friends for MArray element type T.
 #define INSTANTIATE_MARRAY_FRIENDS(T, API) \
-  MARRAY_OP_ASSIGN_DEFS (MArray, T, T, API) \
+  MARRAY_OP_ASSIGN_DEFS1 (MArray, T, T, API) \
   MARRAY_OP_ASSIGN_DEFS (MArray, T, MArray<T>, API) \
   MARRAY_UNOP_DEFS (MArray, T, API) \
   MARRAY_BINOP_DEFS (MArray, T, API)
 
 // Instantiate all the MArray2 friends for MArray2 element type T.
 #define INSTANTIATE_MARRAY2_FRIENDS(T, API) \
-  MARRAY_OP_ASSIGN_DEFS (MArray2, T, T, API) \
+  MARRAY_OP_ASSIGN_DEFS1 (MArray2, T, T, API) \
   MARRAY_OP_ASSIGN_DEFS (MArray2, T, MArray2<T>, API) \
   MARRAY_UNOP_DEFS (MArray2, T, API) \
   MARRAY_BINOP_DEFS (MArray2, T, API)
 
 // Instantiate all the MArrayN friends for MArrayN element type T.
 #define INSTANTIATE_MARRAYN_FRIENDS(T, API) \
-  MARRAY_OP_ASSIGN_DEFS (MArrayN, T, T, API) \
+  MARRAY_OP_ASSIGN_DEFS1 (MArrayN, T, T, API) \
   MARRAY_OP_ASSIGN_DEFS (MArrayN, T, MArrayN<T>, API) \
   MARRAY_UNOP_DEFS (MArrayN, T, API) \
   MARRAY_BINOP_DEFS (MArrayN, T, API)
--- a/liboctave/MArray.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/MArray.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -116,6 +116,8 @@
 MArray<T>&
 operator += (MArray<T>& a, const T& s)
 {
+  if (a.is_shared ())
+    return a = a + s;
   DO_VS_OP2 (T, a, +=, s)
   return a;
 }
@@ -124,16 +126,40 @@
 MArray<T>&
 operator -= (MArray<T>& a, const T& s)
 {
+  if (a.is_shared ())
+    return a = a - s;
   DO_VS_OP2 (T, a, -=, s)
   return a;
 }
 
+template <class T>
+MArray<T>&
+operator *= (MArray<T>& a, const T& s)
+{
+  if (a.is_shared ())
+    return a = a * s;
+  DO_VS_OP2 (T, a, *=, s)
+  return a;
+}
+
+template <class T>
+MArray<T>&
+operator /= (MArray<T>& a, const T& s)
+{
+  if (a.is_shared ())
+    return a = a / s;
+  DO_VS_OP2 (T, a, /=, s)
+  return a;
+}
+
 // Element by element MArray by MArray ops.
 
 template <class T>
 MArray<T>&
 operator += (MArray<T>& a, const MArray<T>& b)
 {
+  if (a.is_shared ())
+    return a = a + b;
   octave_idx_type l = a.length ();
   if (l > 0)
     {
@@ -150,6 +176,8 @@
 MArray<T>&
 operator -= (MArray<T>& a, const MArray<T>& b)
 {
+  if (a.is_shared ())
+    return a = a - b;
   octave_idx_type l = a.length ();
   if (l > 0)
     {
--- a/liboctave/MArray2.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/MArray2.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -39,6 +39,8 @@
 MArray2<T>&
 operator += (MArray2<T>& a, const T& s)
 {
+  if (a.is_shared ())
+    return a = a + s;
   DO_VS_OP2 (T, a, +=, s)
   return a;
 }
@@ -47,16 +49,40 @@
 MArray2<T>&
 operator -= (MArray2<T>& a, const T& s)
 {
+  if (a.is_shared ())
+    return a = a - s;
   DO_VS_OP2 (T, a, -=, s)
   return a;
 }
 
+template <class T>
+MArray2<T>&
+operator *= (MArray2<T>& a, const T& s)
+{
+  if (a.is_shared ())
+    return a = a * s;
+  DO_VS_OP2 (T, a, *=, s)
+  return a;
+}
+
+template <class T>
+MArray2<T>&
+operator /= (MArray2<T>& a, const T& s)
+{
+  if (a.is_shared ())
+    return a = a / s;
+  DO_VS_OP2 (T, a, /=, s)
+  return a;
+}
+
 // Element by element MArray2 by MArray2 ops.
 
 template <class T>
 MArray2<T>&
 operator += (MArray2<T>& a, const MArray2<T>& b)
 {
+  if (a.is_shared ())
+    return a = a + b;
   octave_idx_type r = a.rows ();
   octave_idx_type c = a.cols ();
   octave_idx_type br = b.rows ();
@@ -78,6 +104,8 @@
 MArray2<T>&
 operator -= (MArray2<T>& a, const MArray2<T>& b)
 {
+  if (a.is_shared ())
+    return a = a - b;
   octave_idx_type r = a.rows ();
   octave_idx_type c = a.cols ();
   octave_idx_type br = b.rows ();
--- a/liboctave/MArrayN.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/MArrayN.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -38,6 +38,8 @@
 MArrayN<T>&
 operator += (MArrayN<T>& a, const T& s)
 {
+  if (a.is_shared ())
+    return a = a + s;
   DO_VS_OP2 (T, a, +=, s)
   return a;
 }
@@ -46,16 +48,40 @@
 MArrayN<T>&
 operator -= (MArrayN<T>& a, const T& s)
 {
+  if (a.is_shared ())
+    return a = a - s;
   DO_VS_OP2 (T, a, -=, s)
   return a;
 }
 
+template <class T>
+MArrayN<T>&
+operator *= (MArrayN<T>& a, const T& s)
+{
+  if (a.is_shared ())
+    return a = a * s;
+  DO_VS_OP2 (T, a, *=, s)
+  return a;
+}
+
+template <class T>
+MArrayN<T>&
+operator /= (MArrayN<T>& a, const T& s)
+{
+  if (a.is_shared ())
+    return a = a / s;
+  DO_VS_OP2 (T, a, /=, s)
+  return a;
+}
+
 // Element by element MArrayN by MArrayN ops.
 
 template <class T>
 MArrayN<T>&
 operator += (MArrayN<T>& a, const MArrayN<T>& b)
 {
+  if (a.is_shared ())
+    return a = a + b;
   octave_idx_type l = a.length ();
 
   if (l > 0)
@@ -76,6 +102,8 @@
 MArrayN<T>&
 operator -= (MArrayN<T>& a, const MArrayN<T>& b)
 {
+  if (a.is_shared ())
+    return a = a - b;
   octave_idx_type l = a.length ();
 
   if (l > 0)
--- a/liboctave/fCNDArray.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/fCNDArray.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -36,6 +36,7 @@
 #include "functor.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
+#include "MArray-defs.h"
 #include "mx-base.h"
 #include "mx-op-defs.h"
 #include "oct-fftw.h"
@@ -1078,6 +1079,22 @@
 NDND_CMP_OPS(FloatComplexNDArray, std::real, FloatComplexNDArray, std::real)
 NDND_BOOL_OPS(FloatComplexNDArray, FloatComplexNDArray, static_cast<float> (0.0))
 
+FloatComplexNDArray& operator *= (FloatComplexNDArray& a, float s)
+{
+  if (a.is_shared ())
+    return a = a * s;
+  DO_VS_OP2 (FloatComplex, a, *=, s)
+  return a;
+}
+
+FloatComplexNDArray& operator /= (FloatComplexNDArray& a, float s)
+{
+  if (a.is_shared ())
+    return a = a / s;
+  DO_VS_OP2 (FloatComplex, a, /=, s)
+  return a;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/fCNDArray.h	Mon Aug 17 14:46:18 2009 +0200
+++ b/liboctave/fCNDArray.h	Wed Aug 19 13:47:59 2009 +0200
@@ -173,6 +173,9 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, FloatComplexNDArray, FloatComplex)
 
+extern OCTAVE_API FloatComplexNDArray& operator *= (FloatComplexNDArray& a, float s);
+extern OCTAVE_API FloatComplexNDArray& operator /= (FloatComplexNDArray& a, float s);
+
 #endif
 
 /*
--- a/src/ChangeLog	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/ChangeLog	Wed Aug 19 13:47:59 2009 +0200
@@ -1,3 +1,20 @@
+2009-08-17  Jaroslav Hajek  <highegg@gmail.com>
+
+	* OPERATORS/op-m-m.cc: Define and install += and -= operators.
+	* OPERATORS/op-fm-fm.cc: Ditto.
+	* OPERATORS/op-cm-cm.cc: Ditto.
+	* OPERATORS/op-fcm-fcm.cc: Ditto.
+	* OPERATORS/op-m-s.cc: Define and install +=,-=,*=,/= operators.
+	* OPERATORS/op-fm-fs.cc: Ditto.
+	* OPERATORS/op-cm-cs.cc: Ditto.
+	* OPERATORS/op-fcm-fcs.cc: Ditto.
+	* OPERATORS/op-cm-s.cc: Define and install *=,/= operators.
+	* OPERATORS/op-fcm-fs.cc: Ditto.
+	* ops.h (DEFNDASSIGNOP_OP): New macro.
+	* ov.cc (octave_value::assign (assign_op, const octave_value&)):
+	Try looking up specialized handlers if the value is not shared.
+	* ov-base-mat.h (octave_base_matrix::matrix_ref): New method.
+
 2009-08-17  Jaroslav Hajek  <highegg@gmail.com>
 
 	* oct-obj.h (octave_value_list::octave_value_list (octave_idx_type)):
--- a/src/OPERATORS/op-cm-cm.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-cm-cm.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -163,6 +163,9 @@
 
 DEFNULLASSIGNOP_FN (null_assign, complex_matrix, delete_elements)
 
+DEFNDASSIGNOP_OP (assign_add, complex_matrix, complex_matrix, complex_array, +=)
+DEFNDASSIGNOP_OP (assign_sub, complex_matrix, complex_matrix, complex_array, -=)
+
 CONVDECL (complex_matrix_to_float_complex_matrix)
 {
   CAST_CONV_ARG (const octave_complex_matrix&);
@@ -213,6 +216,9 @@
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, octave_null_str, null_assign);
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, octave_null_sq_str, null_assign);
 
+  INSTALL_ASSIGNOP (op_add_eq, octave_complex_matrix, octave_complex_matrix, assign_add);
+  INSTALL_ASSIGNOP (op_sub_eq, octave_complex_matrix, octave_complex_matrix, assign_sub);
+
   INSTALL_CONVOP (octave_complex_matrix, octave_float_complex_matrix, 
 		  complex_matrix_to_float_complex_matrix);
 }
--- a/src/OPERATORS/op-cm-cs.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-cm-cs.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -107,6 +107,11 @@
 DEFNDASSIGNOP_FN (assign, complex_matrix, complex, complex, assign)
 DEFNDASSIGNOP_FN (sgl_assign, float_complex_matrix, complex, float_complex, assign)
 
+DEFNDASSIGNOP_OP (assign_add, complex_matrix, complex_scalar, complex, +=)
+DEFNDASSIGNOP_OP (assign_sub, complex_matrix, complex_scalar, complex, -=)
+DEFNDASSIGNOP_OP (assign_mul, complex_matrix, complex_scalar, complex, *=)
+DEFNDASSIGNOP_OP (assign_div, complex_matrix, complex_scalar, complex, /=)
+
 void
 install_cm_cs_ops (void)
 {
@@ -133,6 +138,11 @@
 
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, octave_complex, assign);
   INSTALL_ASSIGNOP (op_asn_eq, octave_float_complex_matrix, octave_complex, sgl_assign);
+
+  INSTALL_ASSIGNOP (op_add_eq, octave_complex_matrix, octave_complex_scalar, assign_add);
+  INSTALL_ASSIGNOP (op_sub_eq, octave_complex_matrix, octave_complex_scalar, assign_sub);
+  INSTALL_ASSIGNOP (op_mul_eq, octave_complex_matrix, octave_complex_scalar, assign_mul);
+  INSTALL_ASSIGNOP (op_div_eq, octave_complex_matrix, octave_complex_scalar, assign_div);
 }
 
 /*
--- a/src/OPERATORS/op-cm-s.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-cm-s.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -110,6 +110,9 @@
 
 DEFNDASSIGNOP_FN (assign, complex_matrix, scalar, complex_array, assign)
 
+DEFNDASSIGNOP_OP (assign_mul, complex_matrix, scalar, scalar, *=)
+DEFNDASSIGNOP_OP (assign_div, complex_matrix, scalar, scalar, /=)
+
 void
 install_cm_s_ops (void)
 {
@@ -135,6 +138,9 @@
   INSTALL_CATOP (octave_complex_matrix, octave_scalar, cm_s);
 
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, octave_scalar, assign);
+
+  INSTALL_ASSIGNOP (op_mul_eq, octave_complex_matrix, octave_scalar, assign_mul);
+  INSTALL_ASSIGNOP (op_div_eq, octave_complex_matrix, octave_scalar, assign_div);
 }
 
 /*
--- a/src/OPERATORS/op-fcm-fcm.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-fcm-fcm.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -189,6 +189,11 @@
 
 DEFNULLASSIGNOP_FN (null_assign, float_complex_matrix, delete_elements)
 
+DEFNDASSIGNOP_OP (assign_add, float_complex_matrix, 
+                  float_complex_matrix, float_complex_array, +=)
+DEFNDASSIGNOP_OP (assign_sub, float_complex_matrix, 
+                  float_complex_matrix, float_complex_array, -=)
+
 CONVDECL (float_complex_matrix_to_complex_matrix)
 {
   CAST_CONV_ARG (const octave_float_complex_matrix&);
@@ -272,6 +277,11 @@
   INSTALL_ASSIGNOP (op_asn_eq, octave_float_complex_matrix, 
                     octave_null_sq_str, null_assign);
 
+  INSTALL_ASSIGNOP (op_add_eq, octave_float_complex_matrix,
+                    octave_float_complex_matrix, assign_add);
+  INSTALL_ASSIGNOP (op_sub_eq, octave_float_complex_matrix,
+                    octave_float_complex_matrix, assign_sub);
+
   INSTALL_CONVOP (octave_float_complex_matrix, octave_complex_matrix, 
 		  float_complex_matrix_to_complex_matrix);
 }
--- a/src/OPERATORS/op-fcm-fcs.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-fcm-fcs.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -134,6 +134,15 @@
 DEFNDASSIGNOP_FN (dbl_assign, complex_matrix, float_complex, 
 		  complex, assign)
 
+DEFNDASSIGNOP_OP (assign_add, float_complex_matrix, float_complex_scalar,
+                  float_complex, +=)
+DEFNDASSIGNOP_OP (assign_sub, float_complex_matrix, float_complex_scalar,
+                  float_complex, -=)
+DEFNDASSIGNOP_OP (assign_mul, float_complex_matrix, float_complex_scalar,
+                  float_complex, *=)
+DEFNDASSIGNOP_OP (assign_div, float_complex_matrix, float_complex_scalar,
+                  float_complex, /=)
+
 void
 install_fcm_fcs_ops (void)
 {
@@ -176,6 +185,15 @@
 		    octave_float_complex, assign);
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, 
 		    octave_float_complex, dbl_assign);
+
+  INSTALL_ASSIGNOP (op_add_eq, octave_float_complex_matrix,
+                    octave_float_complex_scalar, assign_add);
+  INSTALL_ASSIGNOP (op_sub_eq, octave_float_complex_matrix,
+                    octave_float_complex_scalar, assign_sub);
+  INSTALL_ASSIGNOP (op_mul_eq, octave_float_complex_matrix,
+                    octave_float_complex_scalar, assign_mul);
+  INSTALL_ASSIGNOP (op_div_eq, octave_float_complex_matrix,
+                    octave_float_complex_scalar, assign_div);
 }
 
 /*
--- a/src/OPERATORS/op-fcm-fs.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-fcm-fs.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -130,6 +130,11 @@
 DEFNDASSIGNOP_FN (assign, float_complex_matrix, float_scalar, float_complex_array, assign)
 DEFNDASSIGNOP_FN (dbl_assign, complex_matrix, float_scalar, complex_array, assign)
 
+DEFNDASSIGNOP_OP (assign_mul, float_complex_matrix, float_scalar,
+                  float_scalar, *=)
+DEFNDASSIGNOP_OP (assign_div, float_complex_matrix, float_scalar,
+                  float_scalar, /=)
+
 void
 install_fcm_fs_ops (void)
 {
@@ -160,6 +165,11 @@
 		    octave_float_scalar, assign);
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, 
 		    octave_float_scalar, dbl_assign);
+
+  INSTALL_ASSIGNOP (op_mul_eq, octave_float_complex_matrix,
+                    octave_float_scalar, assign_mul);
+  INSTALL_ASSIGNOP (op_div_eq, octave_float_complex_matrix,
+                    octave_float_scalar, assign_div);
 }
 
 /*
--- a/src/OPERATORS/op-fm-fm.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-fm-fm.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -165,6 +165,9 @@
 
 DEFNULLASSIGNOP_FN (null_assign, float_matrix, delete_elements)
 
+DEFNDASSIGNOP_OP (assign_add, float_matrix, float_matrix, float_array, +=)
+DEFNDASSIGNOP_OP (assign_sub, float_matrix, float_matrix, float_array, -=)
+
 CONVDECL (float_matrix_to_matrix)
 {
   CAST_CONV_ARG (const octave_float_matrix&);
@@ -224,6 +227,9 @@
   INSTALL_ASSIGNOP (op_asn_eq, octave_float_matrix, octave_null_str, null_assign);
   INSTALL_ASSIGNOP (op_asn_eq, octave_float_matrix, octave_null_sq_str, null_assign);
 
+  INSTALL_ASSIGNOP (op_add_eq, octave_float_matrix, octave_float_matrix, assign_add);
+  INSTALL_ASSIGNOP (op_sub_eq, octave_float_matrix, octave_float_matrix, assign_sub);
+
   INSTALL_CONVOP (octave_float_matrix, octave_matrix, float_matrix_to_matrix);
 }
 
--- a/src/OPERATORS/op-fm-fs.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-fm-fs.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -122,6 +122,11 @@
 DEFNDASSIGNOP_FN (assign, float_matrix, float_scalar, float_scalar, assign)
 DEFNDASSIGNOP_FN (dbl_assign, matrix, float_scalar, scalar, assign)
 
+DEFNDASSIGNOP_OP (assign_add, float_matrix, float_scalar, float_scalar, +=)
+DEFNDASSIGNOP_OP (assign_sub, float_matrix, float_scalar, float_scalar, -=)
+DEFNDASSIGNOP_OP (assign_mul, float_matrix, float_scalar, float_scalar, *=)
+DEFNDASSIGNOP_OP (assign_div, float_matrix, float_scalar, float_scalar, /=)
+
 void
 install_fm_fs_ops (void)
 {
@@ -150,6 +155,11 @@
 
   INSTALL_ASSIGNOP (op_asn_eq, octave_float_matrix, octave_float_scalar, assign);
   INSTALL_ASSIGNOP (op_asn_eq, octave_matrix, octave_float_scalar, dbl_assign);
+
+  INSTALL_ASSIGNOP (op_add_eq, octave_float_matrix, octave_float_scalar, assign_add);
+  INSTALL_ASSIGNOP (op_sub_eq, octave_float_matrix, octave_float_scalar, assign_sub);
+  INSTALL_ASSIGNOP (op_mul_eq, octave_float_matrix, octave_float_scalar, assign_mul);
+  INSTALL_ASSIGNOP (op_div_eq, octave_float_matrix, octave_float_scalar, assign_div);
 }
 
 /*
--- a/src/OPERATORS/op-int.h	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-int.h	Wed Aug 19 13:47:59 2009 +0200
@@ -584,6 +584,12 @@
 #define OCTAVE_MS_INT_ASSIGN_OPS(PFX, TM, TS, TE) \
   DEFNDASSIGNOP_FN (PFX ## _assign, TM ## matrix, TS ## scalar, TM ## scalar, assign)
 
+#define OCTAVE_MS_INT_ASSIGNEQ_OPS(PFX, TM) \
+  DEFNDASSIGNOP_OP (PFX ## _assign_add, TM ## matrix, TM ## scalar, TM ## scalar, +=) \
+  DEFNDASSIGNOP_OP (PFX ## _assign_sub, TM ## matrix, TM ## scalar, TM ## scalar, -=) \
+  DEFNDASSIGNOP_OP (PFX ## _assign_mul, TM ## matrix, TM ## scalar, TM ## scalar, *=) \
+  DEFNDASSIGNOP_OP (PFX ## _assign_div, TM ## matrix, TM ## scalar, TM ## scalar, /=)
+
 #define OCTAVE_MS_POW_OPS(T1, T2) \
 octave_value elem_xpow (T1 ## NDArray a, octave_ ## T2  b) \
 { \
@@ -659,6 +665,7 @@
   OCTAVE_MS_INT_BOOL_OPS (mfx, TYPE ## _, float_) \
   OCTAVE_MS_INT_BOOL_OPS (mfxs, float_, TYPE ## _) \
   OCTAVE_MS_INT_ASSIGN_OPS (ms, TYPE ## _, TYPE ## _, TYPE ## _) \
+  OCTAVE_MS_INT_ASSIGNEQ_OPS (mse, TYPE ## _) \
   OCTAVE_MS_INT_ASSIGN_OPS (mx, TYPE ## _, , ) \
   OCTAVE_MS_INT_ASSIGN_OPS (mfx, TYPE ## _, float_, float_)
 
@@ -747,6 +754,10 @@
 #define OCTAVE_MM_INT_ASSIGN_OPS(PFX, TLHS, TRHS, TE) \
   DEFNDASSIGNOP_FN (PFX ## _assign, TLHS ## matrix, TRHS ## matrix, TLHS ## array, assign)
 
+#define OCTAVE_MM_INT_ASSIGNEQ_OPS(PFX, TM) \
+  DEFNDASSIGNOP_OP (PFX ## _assign_add, TM ## matrix, TM ## matrix, TM ## array, +=) \
+  DEFNDASSIGNOP_OP (PFX ## _assign_sub, TM ## matrix, TM ## matrix, TM ## array, -=)
+
 #define OCTAVE_MM_POW_OPS(T1, T2) \
   octave_value \
   elem_xpow (const T1 ## NDArray& a, const T2 ## NDArray& b) \
@@ -871,6 +882,7 @@
   OCTAVE_MM_INT_BOOL_OPS (mmfx, TYPE ## _, float_) \
   OCTAVE_MM_INT_BOOL_OPS (mfxm, float_, TYPE ## _) \
   OCTAVE_MM_INT_ASSIGN_OPS (mm, TYPE ## _, TYPE ## _, TYPE ## _) \
+  OCTAVE_MM_INT_ASSIGNEQ_OPS (mme, TYPE ## _) \
   OCTAVE_MM_INT_ASSIGN_OPS (mmx, TYPE ## _, , ) \
   OCTAVE_MM_INT_ASSIGN_OPS (mmfx, TYPE ## _, float_, float_) \
   OCTAVE_MM_CONV(TYPE ## _, complex_) \
@@ -1045,6 +1057,12 @@
 #define OCTAVE_INSTALL_MS_INT_ASSIGN_OPS(PFX, TLHS, TRHS) \
   INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign)
 
+#define OCTAVE_INSTALL_MS_INT_ASSIGNEQ_OPS(PFX, TLHS, TRHS) \
+  INSTALL_ASSIGNOP (op_add_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign_add) \
+  INSTALL_ASSIGNOP (op_sub_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign_sub) \
+  INSTALL_ASSIGNOP (op_mul_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign_mul) \
+  INSTALL_ASSIGNOP (op_div_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## scalar, PFX ## _assign_div)
+
 #define OCTAVE_INSTALL_MS_INT_OPS(TYPE) \
   OCTAVE_INSTALL_MS_INT_ARITH_OPS (ms, TYPE ## _, TYPE ## _) \
   OCTAVE_INSTALL_MS_INT_ARITH_OPS (msx, TYPE ## _, ) \
@@ -1062,6 +1080,7 @@
   OCTAVE_INSTALL_MS_INT_BOOL_OPS (mfx, TYPE ## _, float_) \
   OCTAVE_INSTALL_MS_INT_BOOL_OPS (mfxs, float_, TYPE ## _) \
   OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (ms, TYPE ## _, TYPE ## _) \
+  OCTAVE_INSTALL_MS_INT_ASSIGNEQ_OPS (mse, TYPE ## _, TYPE ## _) \
   OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mx, TYPE ## _, ) \
   OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mfx, TYPE ## _, float_) \
   INSTALL_ASSIGNCONV (octave_ ## TYPE ## _matrix, octave_complex_scalar, octave_complex_matrix) \
@@ -1108,6 +1127,10 @@
 #define OCTAVE_INSTALL_MM_INT_ASSIGN_OPS(PFX, TLHS, TRHS) \
   INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## matrix, PFX ## _assign)
 
+#define OCTAVE_INSTALL_MM_INT_ASSIGNEQ_OPS(PFX, TLHS, TRHS) \
+  INSTALL_ASSIGNOP (op_add_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## matrix, PFX ## _assign_add) \
+  INSTALL_ASSIGNOP (op_sub_eq, octave_ ## TLHS ## matrix, octave_ ## TRHS ## matrix, PFX ## _assign_sub)
+
 #define OCTAVE_INSTALL_MM_INT_OPS(TYPE) \
   OCTAVE_INSTALL_M_INT_UNOPS (TYPE) \
   OCTAVE_INSTALL_MM_INT_ARITH_OPS (mm, TYPE ##_, TYPE ## _) \
@@ -1126,6 +1149,7 @@
   OCTAVE_INSTALL_MM_INT_BOOL_OPS (mmfx, TYPE ## _, float_) \
   OCTAVE_INSTALL_MM_INT_BOOL_OPS (mfxm, float_, TYPE ## _) \
   OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mm, TYPE ## _, TYPE ## _) \
+  OCTAVE_INSTALL_MM_INT_ASSIGNEQ_OPS (mme, TYPE ## _, TYPE ## _) \
   OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmx, TYPE ## _, ) \
   OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmfx, TYPE ## _, float_) \
   INSTALL_WIDENOP (octave_ ## TYPE ## _matrix, octave_complex_matrix, TYPE ## _m_complex_m_conv) \
--- a/src/OPERATORS/op-m-m.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-m-m.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -138,6 +138,9 @@
 
 DEFNULLASSIGNOP_FN (null_assign, matrix, delete_elements)
 
+DEFNDASSIGNOP_OP (assign_add, matrix, matrix, array, +=)
+DEFNDASSIGNOP_OP (assign_sub, matrix, matrix, array, -=)
+
 CONVDECL (matrix_to_float_matrix)
 {
   CAST_CONV_ARG (const octave_matrix&);
@@ -193,6 +196,9 @@
   INSTALL_ASSIGNOP (op_asn_eq, octave_matrix, octave_null_str, null_assign);
   INSTALL_ASSIGNOP (op_asn_eq, octave_matrix, octave_null_sq_str, null_assign);
 
+  INSTALL_ASSIGNOP (op_add_eq, octave_matrix, octave_matrix, assign_add);
+  INSTALL_ASSIGNOP (op_sub_eq, octave_matrix, octave_matrix, assign_sub);
+
   INSTALL_CONVOP (octave_matrix, octave_float_matrix, matrix_to_float_matrix);
 }
 
--- a/src/OPERATORS/op-m-s.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/OPERATORS/op-m-s.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -108,6 +108,11 @@
 DEFNDASSIGNOP_FN (assign, matrix, scalar, scalar, assign)
 DEFNDASSIGNOP_FN (sgl_assign, float_matrix, scalar, float_scalar, assign)
 
+DEFNDASSIGNOP_OP (assign_add, matrix, scalar, scalar, +=)
+DEFNDASSIGNOP_OP (assign_sub, matrix, scalar, scalar, -=)
+DEFNDASSIGNOP_OP (assign_mul, matrix, scalar, scalar, *=)
+DEFNDASSIGNOP_OP (assign_div, matrix, scalar, scalar, /=)
+
 void
 install_m_s_ops (void)
 {
@@ -140,6 +145,11 @@
 
   INSTALL_ASSIGNOP (op_asn_eq, octave_matrix, octave_scalar, assign);
   INSTALL_ASSIGNOP (op_asn_eq, octave_float_matrix, octave_scalar, sgl_assign);
+
+  INSTALL_ASSIGNOP (op_add_eq, octave_matrix, octave_scalar, assign_add);
+  INSTALL_ASSIGNOP (op_sub_eq, octave_matrix, octave_scalar, assign_sub);
+  INSTALL_ASSIGNOP (op_mul_eq, octave_matrix, octave_scalar, assign_mul);
+  INSTALL_ASSIGNOP (op_div_eq, octave_matrix, octave_scalar, assign_div);
 }
 
 /*
--- a/src/ops.h	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/ops.h	Wed Aug 19 13:47:59 2009 +0200
@@ -201,6 +201,18 @@
     return octave_value (); \
   }
 
+// FIXME: the following currently doesn't handle index.
+#define DEFNDASSIGNOP_OP(name, t1, t2, f, op) \
+  ASSIGNOPDECL (name) \
+  { \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+ \
+    assert (idx.empty ()); \
+    v1.matrix_ref () op v2.CONCAT2(f, _value) (); \
+ \
+    return octave_value (); \
+  }
+
 #define DEFASSIGNANYOP_FN(name, t1, f) \
   ASSIGNANYOPDECL (name) \
   { \
--- a/src/ov-base-mat.h	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/ov-base-mat.h	Wed Aug 19 13:47:59 2009 +0200
@@ -154,6 +154,12 @@
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
+  MT& matrix_ref (void)
+    {
+      clear_cached_info ();
+      return matrix;
+    }
+
 protected:
 
   MT matrix;
--- a/src/ov.cc	Mon Aug 17 14:46:18 2009 +0200
+++ b/src/ov.cc	Wed Aug 19 13:47:59 2009 +0200
@@ -1195,10 +1195,6 @@
 
   if (op != op_asn_eq)
     {
-      // FIXME -- only do the following stuff if we can't find
-      // a specific function to call to handle the op= operation for
-      // the types we have.
-
       octave_value t = subsref (type, idx);
 
       if (! error_state)
@@ -1236,19 +1232,41 @@
     operator = (rhs.storable_value ());
   else
     {
-      // FIXME -- only do the following stuff if we can't find
-      // a specific function to call to handle the op= operation for
-      // the types we have.
-
-      binary_op binop = op_eq_to_binary_op (op);
-
-      if (! error_state)
+      octave_value_typeinfo::assign_op_fcn f = 0;
+      
+      // Only attempt to operate in-place if this variable is unshared.
+      if (rep->count == 1)
+        {
+          int tthis = this->type_id ();
+          int trhs = rhs.type_id ();
+
+	  f = octave_value_typeinfo::lookup_assign_op (op, tthis, trhs);
+        }
+
+      if (f)
 	{
-	  octave_value t = do_binary_op (binop, *this, rhs);
-
-	  if (! error_state)
-	    operator = (t);
+	  try
+	    {
+	      f (*rep, octave_value_list (), *rhs.rep);
+	    }
+	  catch (octave_execution_exception)
+	    {
+	      gripe_library_execution_error ();
+	    }
 	}
+      else
+        {
+
+          binary_op binop = op_eq_to_binary_op (op);
+
+          if (! error_state)
+            {
+              octave_value t = do_binary_op (binop, *this, rhs);
+
+              if (! error_state)
+                operator = (t);
+            }
+        }
 
       if (error_state)
 	gripe_assign_failed_or_no_method (assign_op_as_string (op),