changeset 8366:8b1a2555c4e2

implement diagonal matrix objects * * *
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 03 Dec 2008 13:32:57 +0100
parents 65ca196fff28
children 445d27d79f4e
files liboctave/CDiagMatrix.cc liboctave/CDiagMatrix.h liboctave/CSparse.cc liboctave/CSparse.h liboctave/ChangeLog liboctave/DiagArray2.cc liboctave/DiagArray2.h liboctave/MDiagArray2.h liboctave/dDiagMatrix.cc liboctave/dDiagMatrix.h liboctave/dSparse.cc liboctave/dSparse.h liboctave/fCDiagMatrix.cc liboctave/fCDiagMatrix.h liboctave/fDiagMatrix.cc liboctave/fDiagMatrix.h liboctave/mx-op-defs.h src/ChangeLog src/DLD-FUNCTIONS/inv.cc src/Makefile.in src/OPERATORS/op-cdm-cdm.cc src/OPERATORS/op-cdm-cm.cc src/OPERATORS/op-cdm-cs.cc src/OPERATORS/op-cdm-dm.cc src/OPERATORS/op-cdm-m.cc src/OPERATORS/op-cdm-s.cc src/OPERATORS/op-cm-cdm.cc src/OPERATORS/op-cm-dm.cc src/OPERATORS/op-dm-cdm.cc src/OPERATORS/op-dm-cm.cc src/OPERATORS/op-dm-cs.cc src/OPERATORS/op-dm-dm.cc src/OPERATORS/op-dm-m.cc src/OPERATORS/op-dm-s.cc src/OPERATORS/op-dm-template.cc src/OPERATORS/op-dms-template.cc src/OPERATORS/op-fcdm-fcdm.cc src/OPERATORS/op-fcdm-fcm.cc src/OPERATORS/op-fcdm-fcs.cc src/OPERATORS/op-fcdm-fdm.cc src/OPERATORS/op-fcdm-fm.cc src/OPERATORS/op-fcdm-fs.cc src/OPERATORS/op-fcm-fcdm.cc src/OPERATORS/op-fcm-fdm.cc src/OPERATORS/op-fdm-fcdm.cc src/OPERATORS/op-fdm-fcm.cc src/OPERATORS/op-fdm-fcs.cc src/OPERATORS/op-fdm-fdm.cc src/OPERATORS/op-fdm-fm.cc src/OPERATORS/op-fdm-fs.cc src/OPERATORS/op-fm-fcdm.cc src/OPERATORS/op-fm-fdm.cc src/OPERATORS/op-m-cdm.cc src/OPERATORS/op-m-dm.cc src/data.cc src/mappers.cc src/ops.h src/ov-base-diag.cc src/ov-base-diag.h src/ov-base.h src/ov-cx-diag.cc src/ov-cx-diag.h src/ov-cx-mat.cc src/ov-cx-mat.h src/ov-flt-cx-diag.cc src/ov-flt-cx-diag.h src/ov-flt-cx-mat.cc src/ov-flt-cx-mat.h src/ov-flt-re-diag.cc src/ov-flt-re-diag.h src/ov-flt-re-mat.cc src/ov-flt-re-mat.h src/ov-range.cc src/ov-range.h src/ov-re-diag.cc src/ov-re-diag.h src/ov-re-mat.cc src/ov-re-mat.h src/ov.cc src/ov.h src/xdiv.cc src/xdiv.h test/ChangeLog test/build_sparse_tests.sh
diffstat 84 files changed, 4156 insertions(+), 152 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/CDiagMatrix.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/CDiagMatrix.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -232,6 +232,15 @@
   return *this;
 }
 
+DiagMatrix
+ComplexDiagMatrix::abs (void) const
+{
+  DiagMatrix retval (rows (), cols ());
+  for (octave_idx_type i = 0; i < rows (); i++)
+    retval(i, i) = std::abs (elem (i, i));
+  return retval;
+}
+
 ComplexDiagMatrix
 conj (const ComplexDiagMatrix& a)
 {
@@ -378,6 +387,21 @@
   return retval;
 }
 
+bool
+ComplexDiagMatrix::all_elements_are_real (void) const
+{
+  octave_idx_type len = length ();
+  for (octave_idx_type i = 0; i < len; i++)
+    {
+      double ip = std::imag (elem (i, i));
+
+      if (ip != 0.0 || lo_ieee_signbit (ip))
+        return false;
+    }
+
+  return true;
+}
+
 // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
 ComplexDiagMatrix&
@@ -431,14 +455,7 @@
       Complex a_element = a.elem (i, i);
       double b_element = b.elem (i, i);
 
-      if (a_element == 0.0 || b_element == 0.0)
-        c.elem (i, i) = 0.0;
-      else if (a_element == 1.0)
-        c.elem (i, i) = b_element;
-      else if (b_element == 1.0)
-        c.elem (i, i) = a_element;
-      else
-        c.elem (i, i) = a_element * b_element;
+      c.elem (i, i) = a_element * b_element;
     }
 
   return c;
@@ -471,14 +488,40 @@
       double a_element = a.elem (i, i);
       Complex b_element = b.elem (i, i);
 
-      if (a_element == 0.0 || b_element == 0.0)
-        c.elem (i, i) = 0.0;
-      else if (a_element == 1.0)
-        c.elem (i, i) = b_element;
-      else if (b_element == 1.0)
-        c.elem (i, i) = a_element;
-      else
-        c.elem (i, i) = a_element * b_element;
+      c.elem (i, i) = a_element * b_element;
+    }
+
+  return c;
+}
+
+ComplexDiagMatrix
+operator * (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)
+{
+  octave_idx_type a_nr = a.rows ();
+  octave_idx_type a_nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (a_nc != b_nr)
+    {
+      gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
+      return ComplexDiagMatrix ();
+    }
+
+  if (a_nr == 0 || a_nc == 0 || b_nc == 0)
+    return ComplexDiagMatrix (a_nr, a_nc, 0.0);
+
+  ComplexDiagMatrix c (a_nr, b_nc);
+
+  octave_idx_type len = a_nr < b_nc ? a_nr : b_nc;
+
+  for (octave_idx_type i = 0; i < len; i++)
+    {
+      Complex a_element = a.elem (i, i);
+      Complex b_element = b.elem (i, i);
+
+      c.elem (i, i) = a_element * b_element;
     }
 
   return c;
--- a/liboctave/CDiagMatrix.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/CDiagMatrix.h	Wed Dec 03 13:32:57 2008 +0100
@@ -65,6 +65,10 @@
   ComplexDiagMatrix (const ComplexDiagMatrix& a)
     : MDiagArray2<Complex> (a) { }
 
+  template <class U>
+  ComplexDiagMatrix (const DiagArray2<U>& a) 
+    : MDiagArray2<Complex> (a) { }
+
   ComplexDiagMatrix& operator = (const ComplexDiagMatrix& a)
     {
       MDiagArray2<Complex>::operator = (a);
@@ -89,6 +93,7 @@
 
   ComplexDiagMatrix hermitian (void) const { return MDiagArray2<Complex>::hermitian (std::conj); }
   ComplexDiagMatrix transpose (void) const { return MDiagArray2<Complex>::transpose(); }
+  DiagMatrix abs (void) const; 
 
   friend ComplexDiagMatrix conj (const ComplexDiagMatrix& a);
 
@@ -107,6 +112,8 @@
   ComplexDiagMatrix inverse (int& info) const;
   ComplexDiagMatrix inverse (void) const;
 
+  bool all_elements_are_real (void) const;
+
   // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
   ComplexDiagMatrix& operator += (const DiagMatrix& a);
@@ -126,6 +133,8 @@
     : MDiagArray2<Complex> (d, nr, nc) { }
 };
 
+ComplexDiagMatrix conj (const ComplexDiagMatrix& a);
+
 // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
 ComplexDiagMatrix
--- a/liboctave/CSparse.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/CSparse.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -144,6 +144,22 @@
     }
 }
 
+SparseComplexMatrix::SparseComplexMatrix (const ComplexDiagMatrix& a)
+  : MSparse<Complex> (a.rows (), a.cols (), a.nnz ())
+{
+  octave_idx_type nz = a.nnz (), l = a.length ();
+  for (octave_idx_type i = 0, j = 0; i < l; i++)
+    {
+      if (a(i, i) != Complex (0.0, 0.0))
+        {
+          data (j) = a(i, i);
+          ridx (j) = i;
+          cidx (j) = j;
+          j++;
+        }
+    }
+  cidx (nz) = nz;
+}
 bool
 SparseComplexMatrix::operator == (const SparseComplexMatrix& a) const
 {
--- a/liboctave/CSparse.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/CSparse.h	Wed Dec 03 13:32:57 2008 +0100
@@ -90,6 +90,8 @@
 
   explicit SparseComplexMatrix (const SparseBoolMatrix& a);
 
+  explicit SparseComplexMatrix (const ComplexDiagMatrix& a);
+
   SparseComplexMatrix (octave_idx_type r, octave_idx_type c, octave_idx_type num_nz) 
     : MSparse<Complex> (r, c, num_nz) { }
 
--- a/liboctave/ChangeLog	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/ChangeLog	Wed Dec 03 13:32:57 2008 +0100
@@ -1,3 +1,71 @@
+2008-12-01  Jaroslav Hajek  <highegg@gmail.com>
+
+	* DiagArray2.h (DiagArray2<T>::DiagArray2<T> (const DiagArray2<U>&)): New template
+	constructor.
+	(DiagArray2<T>::elem, xelem, operator ()): Move to header file to
+	enable inlining.
+	* DiagArray2.cc (DiagArray2<T>::elem, xelem, operator ()): Remove
+	implementations.
+	* MDiagArray2.h (MDiagArray2<T>::MDiagArray2<T> (const DiagArray2<U>&)): New template
+	constructor.
+	(MDiagArray2<T>::nnz): New method.
+	* MDiagArray2.cc (MDiagArray2<T>::nnz): Implement it.
+
+	* dDiagMatrix.h (DiagMatrix::DiagMatrix (const DiagArray2<U>&)): New template
+	constructor.
+	(DiagMatrix::abs): New method decl.
+	(real (const ComplexDiagMatrix&), imag (const ComplexDiagMatrix&)):
+	New decls.
+	* dDiagMatrix.cc (DiagMatrix::abs): New method.
+	(operator *(const DiagMatrix&, const DiagMatrix&)): Optimize.
+	(real (const ComplexDiagMatrix&), imag (const ComplexDiagMatrix&)):
+	New functions.
+
+	* fDiagMatrix.h (FloatDiagMatrix::FloatDiagMatrix (const DiagArray2<U>&)): New template
+	constructor.
+	(FloatDiagMatrix::abs): New method decl.
+	(real (const FloatComplexDiagMatrix&), imag (const FloatComplexDiagMatrix&)):
+	New decls.
+	* fDiagMatrix.cc (FloatDiagMatrix::abs): New method.
+	(operator *(const FloatDiagMatrix&, const FloatDiagMatrix&)): Optimize.
+	(real (const FloatComplexDiagMatrix&), imag (const FloatComplexDiagMatrix&)):
+	New functions.
+	
+	* CDiagMatrix.h (ComplexDiagMatrix::ComplexDiagMatrix (const DiagArray2<U>&)): New template
+	constructor.
+	(ComplexDiagMatrix::abs): New method decl.
+	(conj (const ComplexDiagMatrix&)): Add missing decl.
+	(ComplexDiagMatrix::all_elements_are_real): New method decl.
+
+	* CDiagMatrix.cc (CDiagMatrix::abs): New method.
+	(operator *(const DiagMatrix&, const ComplexDiagMatrix&)): Optimize.
+	(operator *(const ComplexDiagMatrix&, const DiagMatrix&)): Optimize.
+	(operator *(const ComplexDiagMatrix&, const ComplexDiagMatrix&)): Optimize.
+	(ComplexDiagMatrix::all_elements_are_real): New method.
+
+	* fCDiagMatrix.h (FloatComplexDiagMatrix::FloatComplexDiagMatrix (const DiagArray2<U>&)): New template
+	constructor.
+	(FloatComplexDiagMatrix::abs): New method decl.
+	(conj (const FloatComplexDiagMatrix&)): Add missing decl.
+	(FloatComplexDiagMatrix::all_elements_are_real): New method decl.
+
+	* fCDiagMatrix.cc (CDiagMatrix::abs): New method.
+	(operator *(const FloatDiagMatrix&, const FloatComplexDiagMatrix&)): Optimize.
+	(operator *(const FloatComplexDiagMatrix&, const FloatDiagMatrix&)): Optimize.
+	(operator *(const ComplexDiagMatrix&, const ComplexDiagMatrix&)): Optimize.
+	(FloatComplexDiagMatrix::all_elements_are_real): New method.
+
+	* dSparse.cc (SparseMatrix::SparseMatrix (const DiagMatrix&)): New
+	constructor.
+	* dSparse.h (SparseMatrix::SparseMatrix (const DiagMatrix&)): Declare
+	it.
+
+	* CSparse.cc (SparseComplexMatrix::SparseComplexMatrix (const ComplexDiagMatrix&)): 
+	New constructor.
+	* CSparse.h (SparseComplexMatrix::SparseComplexMatrix (const ComplexDiagMatrix&)): 
+	Declare it.
+	* mx-op-defs.h (DMM_MULTIPLY_OP, MDM_MULTIPLY_OP): Optimize.
+
 2008-11-21  Jarkko Kaleva  <d3roga@gmail.com>
 
 	* EIG.h (EIG::EIG (const Matrix& a, const Matrix& b, 
--- a/liboctave/DiagArray2.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/DiagArray2.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -59,13 +59,6 @@
 
 template <class T>
 T
-DiagArray2<T>::elem (octave_idx_type r, octave_idx_type c) const
-{
-  return (r == c) ? Array<T>::xelem (r) : T (0);
-}
-
-template <class T>
-T
 DiagArray2<T>::checkelem (octave_idx_type r, octave_idx_type c) const
 {
   if (r < 0 || c < 0 || r >= this->dim1 () || c >= this->dim2 ())
@@ -77,33 +70,6 @@
 }
 
 template <class T>
-T
-DiagArray2<T>::operator () (octave_idx_type r, octave_idx_type c) const
-{
-  if (r < 0 || c < 0 || r >= this->dim1 () || c >= this->dim2 ())
-    {
-      (*current_liboctave_error_handler) ("range error in DiagArray2");
-      return T ();
-    }
-  return (r == c) ? Array<T>::xelem (r) : T (0);
-}
-
-template <class T>
-T&
-DiagArray2<T>::xelem (octave_idx_type r, octave_idx_type c)
-{
-  static T foo (0);
-  return (r == c) ? Array<T>::xelem (r) : foo;
-}
-
-template <class T>
-T
-DiagArray2<T>::xelem (octave_idx_type r, octave_idx_type c) const
-{
-  return (r == c) ? Array<T>::xelem (r) : T (0);
-}
-
-template <class T>
 void
 DiagArray2<T>::resize (octave_idx_type r, octave_idx_type c)
 {
--- a/liboctave/DiagArray2.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/DiagArray2.h	Wed Dec 03 13:32:57 2008 +0100
@@ -130,6 +130,10 @@
   DiagArray2 (const DiagArray2<T>& a) : Array<T> (a)
     { this->dimensions = a.dims (); }
 
+  template <class U>
+  DiagArray2 (const DiagArray2<U>& a) : Array<T> (a)
+    { this->dimensions = a.dims (); }
+
   ~DiagArray2 (void) { }
 
   DiagArray2<T>& operator = (const DiagArray2<T>& a)
@@ -167,14 +171,33 @@
 	return Proxy (this, r, c);
   }
 
-  T elem (octave_idx_type r, octave_idx_type c) const;
+  T elem (octave_idx_type r, octave_idx_type c) const
+    {
+      return (r == c) ? Array<T>::xelem (r) : T (0);
+    }
+
   T checkelem (octave_idx_type r, octave_idx_type c) const;
-  T operator () (octave_idx_type r, octave_idx_type c) const;
+  T operator () (octave_idx_type r, octave_idx_type c) const
+    {
+#if defined (BOUNDS_CHECKING)
+      return checkelem (r, c);
+#else
+      return elem (r, c);
+#endif
+    }
 
   // No checking.
 
-  T& xelem (octave_idx_type r, octave_idx_type c);
-  T xelem (octave_idx_type r, octave_idx_type c) const;
+  T& xelem (octave_idx_type r, octave_idx_type c)
+    {
+      static T foo (0);
+      return (r == c) ? Array<T>::xelem (r) : foo;
+    }
+
+  T xelem (octave_idx_type r, octave_idx_type c) const
+    {
+      return (r == c) ? Array<T>::xelem (r) : T (0);
+    }
 
   void resize (octave_idx_type n, octave_idx_type m);
   void resize (octave_idx_type n, octave_idx_type m, const T& val);
--- a/liboctave/MDiagArray2.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/MDiagArray2.h	Wed Dec 03 13:32:57 2008 +0100
@@ -56,6 +56,9 @@
 
   MDiagArray2 (const DiagArray2<T>& a) : DiagArray2<T> (a) { }
 
+  template <class U>
+  MDiagArray2 (const DiagArray2<U>& a) : DiagArray2<T> (a) { }
+
   explicit MDiagArray2 (const Array<T>& a) : DiagArray2<T> (a) { }
 
   ~MDiagArray2 (void) { }
@@ -81,6 +84,23 @@
       return retval;
     }
 
+  octave_idx_type nnz (void) const
+    {
+      octave_idx_type retval = 0;
+
+      const T *d = this->Array<T>::data ();
+
+      octave_idx_type nel = this->Array<T>::numel ();
+
+      for (octave_idx_type i = 0; i < nel; i++)
+	{
+	  if (d[i] != T ())
+	    retval++;
+	}
+
+      return retval;
+    }
+
   MDiagArray2<T> transpose (void) const { return DiagArray2<T>::transpose (); }
   MDiagArray2<T> hermitian (T (*fcn) (const T&) = 0) const { return DiagArray2<T>::hermitian (fcn); }
 
--- a/liboctave/dDiagMatrix.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/dDiagMatrix.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -139,6 +139,15 @@
 }
 
 DiagMatrix
+DiagMatrix::abs (void) const
+{
+  DiagMatrix retval (rows (), cols ());
+  for (octave_idx_type i = 0; i < rows (); i++)
+    retval(i, i) = std::abs (elem (i, i));
+  return retval;
+}
+
+DiagMatrix
 real (const ComplexDiagMatrix& a)
 {
   DiagMatrix retval;
@@ -309,7 +318,7 @@
 
   if (a_nc != b_nr)
     {
-      gripe_nonconformant ("operaotr *", a_nr, a_nc, b_nr, b_nc);
+      gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
       return DiagMatrix ();
     }
 
@@ -325,14 +334,7 @@
       double a_element = a.elem (i, i);
       double b_element = b.elem (i, i);
 
-      if (a_element == 0.0 || b_element == 0.0)
-        c.elem (i, i) = 0.0;
-      else if (a_element == 1.0)
-        c.elem (i, i) = b_element;
-      else if (b_element == 1.0)
-        c.elem (i, i) = a_element;
-      else
-        c.elem (i, i) = a_element * b_element;
+      c.elem (i, i) = a_element * b_element;
     }
 
   return c;
--- a/liboctave/dDiagMatrix.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/dDiagMatrix.h	Wed Dec 03 13:32:57 2008 +0100
@@ -50,6 +50,9 @@
 
   DiagMatrix (const MDiagArray2<double>& a) : MDiagArray2<double> (a) { }
 
+  template <class U>
+  DiagMatrix (const DiagArray2<U>& a) : MDiagArray2<double> (a) { }
+
   explicit DiagMatrix (const RowVector& a) : MDiagArray2<double> (a) { }
 
   explicit DiagMatrix (const ColumnVector& a) : MDiagArray2<double> (a) { }
@@ -71,6 +74,7 @@
   DiagMatrix& fill (const RowVector& a, octave_idx_type beg);
 
   DiagMatrix transpose (void) const { return MDiagArray2<double>::transpose(); }
+  DiagMatrix abs (void) const; 
 
   friend OCTAVE_API DiagMatrix real (const ComplexDiagMatrix& a);
   friend OCTAVE_API DiagMatrix imag (const ComplexDiagMatrix& a);
@@ -103,6 +107,9 @@
   DiagMatrix (double *d, octave_idx_type nr, octave_idx_type nc) : MDiagArray2<double> (d, nr, nc) { }
 };
 
+OCTAVE_API DiagMatrix real (const ComplexDiagMatrix& a);
+OCTAVE_API DiagMatrix imag (const ComplexDiagMatrix& a);
+
 // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
 DiagMatrix
--- a/liboctave/dSparse.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/dSparse.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -139,6 +139,23 @@
     }
 }
 
+SparseMatrix::SparseMatrix (const DiagMatrix& a)
+  : MSparse<double> (a.rows (), a.cols (), a.nnz ())
+{
+  octave_idx_type nz = a.nnz (), l = a.length ();
+  for (octave_idx_type i = 0, j = 0; i < l; i++)
+    {
+      if (a(i, i) != 0.0)
+        {
+          data (j) = a(i, i);
+          ridx (j) = i;
+          cidx (j) = j;
+          j++;
+        }
+    }
+  cidx (nz) = nz;
+}
+
 bool
 SparseMatrix::operator == (const SparseMatrix& a) const
 {
--- a/liboctave/dSparse.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/dSparse.h	Wed Dec 03 13:32:57 2008 +0100
@@ -29,6 +29,7 @@
 #include "CMatrix.h"
 #include "dColVector.h"
 #include "CColVector.h"
+#include "dDiagMatrix.h"
 
 #include "DET.h"
 #include "MSparse.h"
@@ -80,6 +81,8 @@
 			 octave_idx_type nc = -1, bool sum_terms = true)
     : MSparse<double> (a, r, c, nr, nc, sum_terms) { }
 
+  explicit SparseMatrix (const DiagMatrix& a);
+
   SparseMatrix (octave_idx_type r, octave_idx_type c, octave_idx_type num_nz) : MSparse<double> (r, c, num_nz) { }
 
   SparseMatrix& operator = (const SparseMatrix& a)
--- a/liboctave/fCDiagMatrix.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/fCDiagMatrix.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -232,6 +232,15 @@
   return *this;
 }
 
+FloatDiagMatrix
+FloatComplexDiagMatrix::abs (void) const
+{
+  FloatDiagMatrix retval (rows (), cols ());
+  for (octave_idx_type i = 0; i < rows (); i++)
+    retval(i, i) = std::abs (elem (i, i));
+  return retval;
+}
+
 FloatComplexDiagMatrix
 conj (const FloatComplexDiagMatrix& a)
 {
@@ -378,6 +387,21 @@
   return retval;
 }
 
+bool
+FloatComplexDiagMatrix::all_elements_are_real (void) const
+{
+  octave_idx_type len = length ();
+  for (octave_idx_type i = 0; i < len; i++)
+    {
+      float ip = std::imag (elem (i, i));
+
+      if (ip != 0.0 || lo_ieee_signbit (ip))
+        return false;
+    }
+
+  return true;
+}
+
 // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
 FloatComplexDiagMatrix&
@@ -484,6 +508,46 @@
   return c;
 }
 
+FloatComplexDiagMatrix
+operator * (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)
+{
+  octave_idx_type a_nr = a.rows ();
+  octave_idx_type a_nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (a_nc != b_nr)
+    {
+      gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
+      return FloatComplexDiagMatrix ();
+    }
+
+  if (a_nr == 0 || a_nc == 0 || b_nc == 0)
+    return FloatComplexDiagMatrix (a_nr, a_nc, 0.0);
+
+  FloatComplexDiagMatrix c (a_nr, b_nc);
+
+  octave_idx_type len = a_nr < b_nc ? a_nr : b_nc;
+
+  for (octave_idx_type i = 0; i < len; i++)
+    {
+      FloatComplex a_element = a.elem (i, i);
+      FloatComplex b_element = b.elem (i, i);
+
+      if (a_element == static_cast<float> (0.0) || b_element == static_cast<float> (0.0))
+        c.elem (i, i) = 0;
+      else if (a_element == static_cast<float> (1.0))
+        c.elem (i, i) = b_element;
+      else if (b_element == static_cast<float> (1.0))
+        c.elem (i, i) = a_element;
+      else
+        c.elem (i, i) = a_element * b_element;
+    }
+
+  return c;
+}
+
 // other operations
 
 FloatComplexColumnVector
--- a/liboctave/fCDiagMatrix.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/fCDiagMatrix.h	Wed Dec 03 13:32:57 2008 +0100
@@ -65,6 +65,10 @@
   FloatComplexDiagMatrix (const FloatComplexDiagMatrix& a)
     : MDiagArray2<FloatComplex> (a) { }
 
+  template <class U>
+  FloatComplexDiagMatrix (const DiagArray2<U>& a) 
+    : MDiagArray2<FloatComplex> (a) { }
+
   FloatComplexDiagMatrix& operator = (const FloatComplexDiagMatrix& a)
     {
       MDiagArray2<FloatComplex>::operator = (a);
@@ -89,6 +93,7 @@
 
   FloatComplexDiagMatrix hermitian (void) const { return MDiagArray2<FloatComplex>::hermitian (std::conj); }
   FloatComplexDiagMatrix transpose (void) const { return MDiagArray2<FloatComplex>::transpose(); }
+  FloatDiagMatrix abs (void) const; 
 
   friend FloatComplexDiagMatrix conj (const FloatComplexDiagMatrix& a);
 
@@ -107,6 +112,8 @@
   FloatComplexDiagMatrix inverse (int& info) const;
   FloatComplexDiagMatrix inverse (void) const;
 
+  bool all_elements_are_real (void) const;
+
   // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
   FloatComplexDiagMatrix& operator += (const FloatDiagMatrix& a);
@@ -126,6 +133,8 @@
     : MDiagArray2<FloatComplex> (d, nr, nc) { }
 };
 
+FloatComplexDiagMatrix conj (const FloatComplexDiagMatrix& a);
+
 // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
 FloatComplexDiagMatrix
--- a/liboctave/fDiagMatrix.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/fDiagMatrix.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -139,6 +139,15 @@
 }
 
 FloatDiagMatrix
+FloatDiagMatrix::abs (void) const
+{
+  FloatDiagMatrix retval (rows (), cols ());
+  for (octave_idx_type i = 0; i < rows (); i++)
+    retval(i, i) = std::abs (elem (i, i));
+  return retval;
+}
+
+FloatDiagMatrix
 real (const FloatComplexDiagMatrix& a)
 {
   FloatDiagMatrix retval;
--- a/liboctave/fDiagMatrix.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/fDiagMatrix.h	Wed Dec 03 13:32:57 2008 +0100
@@ -50,6 +50,9 @@
 
   FloatDiagMatrix (const MDiagArray2<float>& a) : MDiagArray2<float> (a) { }
 
+  template <class U>
+  FloatDiagMatrix (const DiagArray2<U>& a) : MDiagArray2<float> (a) { }
+
   explicit FloatDiagMatrix (const FloatRowVector& a) : MDiagArray2<float> (a) { }
 
   explicit FloatDiagMatrix (const FloatColumnVector& a) : MDiagArray2<float> (a) { }
@@ -71,6 +74,7 @@
   FloatDiagMatrix& fill (const FloatRowVector& a, octave_idx_type beg);
 
   FloatDiagMatrix transpose (void) const { return MDiagArray2<float>::transpose(); }
+  FloatDiagMatrix abs (void) const; 
 
   friend OCTAVE_API FloatDiagMatrix real (const FloatComplexDiagMatrix& a);
   friend OCTAVE_API FloatDiagMatrix imag (const FloatComplexDiagMatrix& a);
@@ -103,6 +107,9 @@
   FloatDiagMatrix (float *d, octave_idx_type nr, octave_idx_type nc) : MDiagArray2<float> (d, nr, nc) { }
 };
 
+OCTAVE_API FloatDiagMatrix real (const FloatComplexDiagMatrix& a);
+OCTAVE_API FloatDiagMatrix imag (const FloatComplexDiagMatrix& a);
+
 // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
 FloatDiagMatrix
--- a/liboctave/mx-op-defs.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/liboctave/mx-op-defs.h	Wed Dec 03 13:32:57 2008 +0100
@@ -1052,7 +1052,7 @@
     gripe_nonconformant ("operator *", m_nr, m_nc, dm_nr, dm_nc); \
   else \
     { \
-      r.resize (m_nr, dm_nc, R_ZERO); \
+      r = R (m_nr, dm_nc); \
  \
       if (m_nr > 0 && m_nc > 0 && dm_nc > 0) \
 	{ \
@@ -1060,8 +1060,9 @@
  \
 	  for (int j = 0; j < len; j++) \
 	    { \
+              const DM::element_type djj = dm.elem (j, j); \
 	      for (int i = 0; i < m_nr; i++) \
-	      r.elem(i, j) = dm.elem(j, j) * m.elem(i, j); \
+	        r.xelem (i, j) = djj * m.elem (i, j); \
 	    } \
 	} \
     } \
@@ -1132,7 +1133,7 @@
     gripe_nonconformant ("operator *", dm_nr, dm_nc, m_nr, m_nc); \
   else \
     { \
-      r.resize (dm_nr, m_nc, R_ZERO); \
+      r = R (dm_nr, m_nc); \
  \
       if (dm_nr > 0 && dm_nc > 0 && m_nc > 0) \
 	{ \
@@ -1141,7 +1142,7 @@
 	  for (int i = 0; i < len; i++) \
 	    { \
 	      for (int j = 0; j < m_nc; j++) \
-	        r.elem(i, j) = dm.elem(i, i) * m.elem(i, j); \
+	        r.xelem (i, j) = dm.elem (i, i) * m.elem (i, j); \
 	    } \
 	} \
     } \
--- a/src/ChangeLog	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ChangeLog	Wed Dec 03 13:32:57 2008 +0100
@@ -2,8 +2,77 @@
 
 	* debug.cc (bp_table::do_get_breakpoint_list): Style fixes.
 
+2008-12-01  Jaroslav Hajek  <highegg@gmail.com>
+
+	* ov-base.h (octave_base_value::is_diag_matrix): New virtual method.
+	* ops.h (CONCAT2, CONCAT3): New macros. Use CONCAT macros instead of 
+	direct token pasting to avoid disabling argument prescan.
+	* xdiv.cc, xdiv.h: Implement xdiv and xleftdiv overloads for diagonal
+	and mixed dense-diagonal operands.
+
+	* ov-re-diag.h: New source.
+	* ov-re-diag.cc: New source.
+	* ov-flt-re-diag.h: New source.
+	* ov-flt-re-diag.cc: New source.
+	* ov-base-diag.h: New source.
+	* ov-base-diag.cc: New source.
+	* OPERATORS/op-m-dm.cc: New source.
+	* OPERATORS/op-m-cdm.cc: New source.
+	* OPERATORS/op-fm-fdm.cc: New source.
+	* OPERATORS/op-fm-fcdm.cc: New source.
+	* OPERATORS/op-fdm-fs.cc: New source.
+	* OPERATORS/op-fdm-fm.cc: New source.
+	* OPERATORS/op-fdm-fdm.cc: New source.
+	* OPERATORS/op-fdm-fcs.cc: New source.
+	* OPERATORS/op-fdm-fcm.cc: New source.
+	* OPERATORS/op-fdm-fcdm.cc: New source.
+	* OPERATORS/op-fcm-fdm.cc: New source.
+	* OPERATORS/op-fcm-fcdm.cc: New source.
+	* OPERATORS/op-fcdm-fs.cc: New source.
+	* OPERATORS/op-fcdm-fm.cc: New source.
+	* OPERATORS/op-fcdm-fdm.cc: New source.
+	* OPERATORS/op-fcdm-fcs.cc: New source.
+	* OPERATORS/op-fcdm-fcm.cc: New source.
+	* OPERATORS/op-fcdm-fcdm.cc: New source.
+	* OPERATORS/op-dms-template.cc: New source.
+	* OPERATORS/op-dm-template.cc: New source.
+	* OPERATORS/op-dm-s.cc: New source.
+	* OPERATORS/op-dm-m.cc: New source.
+	* OPERATORS/op-dm-dm.cc: New source.
+	* OPERATORS/op-dm-cs.cc: New source.
+	* OPERATORS/op-dm-cm.cc: New source.
+	* OPERATORS/op-dm-cdm.cc: New source.
+	* OPERATORS/op-cm-dm.cc: New source.
+	* OPERATORS/op-cm-cdm.cc: New source.
+	* OPERATORS/op-cdm-s.cc: New source.
+	* OPERATORS/op-cdm-m.cc: New source.
+	* OPERATORS/op-cdm-dm.cc: New source.
+	* OPERATORS/op-cdm-cs.cc: New source.
+	* OPERATORS/op-cdm-cm.cc: New source.
+	* OPERATORS/op-cdm-cdm.cc: New source.
+	* Makefile.in: Include them.
+
+	* ov-re-mat.cc (octave_matrix::diag): New method override.
+	* ov-re-mat.h: Declare it.
+	* ov-cx-mat.cc: Likewise with octave_complex_matrix.
+	* ov-cx-mat.h: Likewise with octave_complex_matrix.
+	* ov-flt-re-mat.cc: Likewise with octave_float_matrix.
+	* ov-flt-re-mat.h: Likewise with octave_float_matrix.
+	* ov-flt-cx-mat.cc: Likewise with octave_float_complex_matrix.
+	* ov-flt-cx-mat.h: Likewise with octave_float_complex_matrix.
+	* ov.cc (octave_value::octave_value (const DiagMatrix&))
+	(octave_value::octave_value (const FloatDiagMatrix&))
+	(octave_value::octave_value (const ComplexDiagMatrix&))
+	(octave_value::octave_value (const FloatComplexDiagMatrix&)):
+	Construct a diagonal matrix object.
+	* data.cc (Fdiag): Support explicit dimensions. Fix tests.
+	(Feye): Return diagonal matrix objects if possible. Fix tests.
+	* mappers.cc (Freal, Fimag): Fix tests.
+	* DLD-FUNCTIONS/inv.cc (Finv): Handle diagonal matrix objects.
+	* ov-range.h (octave_range::diag): Declare only.
+	* ov-range.cc (octave_range::diag): Return DiagMatrix if possible.
+
 2008-11-25  Jaroslav Hajek  <highegg@gmail.com>
-
 	* ov.cc (octave_value::is_equal): New member function.
 	* ov.h: Declare it.
 	* pt-select.cc (tree_switch_case::label_matches): Call
--- a/src/DLD-FUNCTIONS/inv.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/DLD-FUNCTIONS/inv.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -29,6 +29,11 @@
 #include "error.h"
 #include "gripes.h"
 #include "oct-obj.h"
+#include "ops.h"
+#include "ov-re-diag.h"
+#include "ov-cx-diag.h"
+#include "ov-flt-re-diag.h"
+#include "ov-flt-cx-diag.h"
 #include "utils.h"
 
 DEFUN_DLD (inv, args, nargout,
@@ -80,7 +85,39 @@
   float frcond = 0.0;
   bool isfloat = arg.is_single_type ();
 
-  if (isfloat)
+  if (arg.is_diag_matrix ())
+    {
+      rcond = 1.0;
+      frcond = 1.0f;
+      const octave_base_value& a = arg.get_rep ();
+      if (arg.is_complex_type ())
+        {
+          if (isfloat)
+            {
+              CAST_CONV_ARG (const octave_float_complex_diag_matrix&);
+              result = v.float_complex_diag_matrix_value ().inverse (info);
+            }
+          else
+            {
+              CAST_CONV_ARG (const octave_complex_diag_matrix&);
+              result = v.complex_diag_matrix_value ().inverse (info);
+            }
+        }
+      else
+        {
+          if (isfloat)
+            {
+              CAST_CONV_ARG (const octave_float_diag_matrix&);
+              result = v.float_diag_matrix_value ().inverse (info);
+            }
+          else
+            {
+              CAST_CONV_ARG (const octave_diag_matrix&);
+              result = v.diag_matrix_value ().inverse (info);
+            }
+        }
+    }
+  else if (isfloat)
     {
       if (arg.is_real_type ())
 	{
--- a/src/Makefile.in	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/Makefile.in	Wed Dec 03 13:32:57 2008 +0100
@@ -101,6 +101,7 @@
 	ov-struct.h ov-scalar.h ov-range.h ov-complex.h \
 	ov-colon.h ov-base.h ov-base-mat.h ov-base-scalar.h \
 	ov-str-mat.h ov-bool-mat.h ov-null-mat.h ov-bool.h \
+	ov-base-diag.h ov-re-diag.h ov-flt-re-diag.h ov-cx-diag.h ov-flt-cx-diag.h \
 	ov-cell.h ov.h ov-fcn.h ov-builtin.h ov-dld-fcn.h \
 	ov-mex-fcn.h ov-usr-fcn.h ov-fcn-handle.h \
 	ov-fcn-inline.h ov-class.h ov-typeinfo.h ov-type-conv.h \
@@ -160,15 +161,26 @@
 	op-fm-fcs.cc op-fm-fm.cc op-fm-fs.cc op-fs-fcm.cc \
 	op-fs-fcs.cc op-fs-fm.cc op-fs-fs.cc 
 
+DIAG_OP_XSRC := op-cdm-cdm.cc op-cdm-cm.cc op-cdm-cs.cc op-cdm-dm.cc \
+	op-cdm-m.cc op-cdm-s.cc op-cm-cdm.cc op-cm-dm.cc op-dm-cdm.cc \
+	op-dm-cm.cc op-dm-cs.cc op-dm-dm.cc op-dm-m.cc op-dm-s.cc \
+	op-m-cdm.cc op-m-dm.cc
+
+FDIAG_OP_XSRC := op-fcdm-fcdm.cc op-fcdm-fcm.cc op-fcdm-fcs.cc op-fcdm-fdm.cc \
+	op-fcdm-fm.cc op-fcdm-fs.cc op-fcm-fcdm.cc op-fcm-fdm.cc \
+	op-fdm-fcdm.cc op-fdm-fcm.cc op-fdm-fcs.cc op-fdm-fdm.cc \
+	op-fdm-fm.cc op-fdm-fs.cc op-fm-fcdm.cc op-fm-fdm.cc
+
 OP_XSRC :=  op-b-b.cc op-b-bm.cc op-bm-b.cc op-bm-bm.cc op-cell.cc \
 	op-chm.cc op-class.cc op-list.cc op-range.cc op-str-m.cc \
 	op-str-s.cc op-str-str.cc op-struct.cc \
 	$(DOUBLE_OP_XSRC) $(FLOAT_OP_XSRC) $(INTTYPE_OP_XSRC) \
-	$(SPARSE_OP_XSRC)
+	$(SPARSE_OP_XSRC) $(DIAG_OP_XSRC) $(FDIAG_OP_XSRC)
 
 OP_SRC := $(addprefix OPERATORS/, $(OP_XSRC))
 
-OP_INCLUDES := OPERATORS/op-int.h
+OP_INCLUDES := OPERATORS/op-int.h \
+	OPERATORS/op-dm-template.cc OPERATORS/op-dms-template.cc
 
 OV_INTTYPE_SRC := \
 	ov-int8.cc ov-int16.cc ov-int32.cc ov-int64.cc \
@@ -186,6 +198,7 @@
 	ov-mex-fcn.cc ov-usr-fcn.cc ov-fcn-handle.cc ov-fcn-inline.cc \
 	ov-class.cc ov-typeinfo.cc \
 	ov-flt-re-mat.cc ov-flt-cx-mat.cc ov-float.cc ov-flt-complex.cc \
+	ov-re-diag.cc ov-flt-re-diag.cc ov-cx-diag.cc ov-flt-cx-diag.cc \
 	$(OV_INTTYPE_SRC) \
 	$(OV_SPARSE_SRC)
 
@@ -215,7 +228,7 @@
 
 BUILT_EXTRAS := graphics.h mxarray.h
 
-EXTRAS := ov-base-int.cc ov-base-mat.cc ov-base-scalar.cc graphics-props.cc
+EXTRAS := ov-base-int.cc ov-base-mat.cc ov-base-diag.cc ov-base-scalar.cc graphics-props.cc
 
 EXTRA_OBJECTS := oct-errno.o octave.o builtins.o ops.o
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-cdm-cdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,109 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gripes.h"
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-cx-mat.h"
+#include "ov-cx-diag.h"
+#include "ov-flt-cx-diag.h"
+#include "ov-typeinfo.h"
+#include "ops.h"
+#include "xdiv.h"
+#include "xpow.h"
+
+// matrix unary ops.
+
+DEFUNOP_OP (uplus, complex_diag_matrix, /* no-op */)
+DEFUNOP_OP (uminus, complex_diag_matrix, -)
+
+DEFUNOP (transpose, complex_diag_matrix)
+{
+  CAST_UNOP_ARG (const octave_complex_diag_matrix&);
+  return octave_value (v.complex_diag_matrix_value().transpose ());
+}
+
+DEFUNOP (hermitian, complex_diag_matrix)
+{
+  CAST_UNOP_ARG (const octave_complex_diag_matrix&);
+  return octave_value (v.complex_diag_matrix_value().hermitian ());
+}
+
+// matrix by matrix ops.
+
+DEFBINOP_OP (add, complex_diag_matrix, complex_diag_matrix, +)
+DEFBINOP_OP (sub, complex_diag_matrix, complex_diag_matrix, -)
+DEFBINOP_OP (mul, complex_diag_matrix, complex_diag_matrix, *)
+
+DEFBINOP (div, complex_diag_matrix, complex_diag_matrix)
+{
+  CAST_BINOP_ARGS (const octave_complex_diag_matrix&, const octave_complex_diag_matrix&);
+  
+  return xdiv (v1.complex_diag_matrix_value (), 
+               v2.complex_diag_matrix_value ());
+}
+
+DEFBINOP (ldiv, complex_diag_matrix, complex_diag_matrix)
+{
+  CAST_BINOP_ARGS (const octave_complex_diag_matrix&, const octave_complex_diag_matrix&);
+  
+  return xleftdiv (v1.complex_diag_matrix_value (),
+                   v2.complex_diag_matrix_value ());
+}
+
+CONVDECL (complex_diag_matrix_to_complex_matrix)
+{
+  CAST_CONV_ARG (const octave_complex_diag_matrix&);
+
+  return new octave_complex_matrix (v.complex_matrix_value ());
+}
+
+CONVDECL (complex_diag_matrix_to_float_complex_diag_matrix)
+{
+  CAST_CONV_ARG (const octave_complex_diag_matrix&);
+
+  return new octave_float_complex_diag_matrix (v.float_complex_diag_matrix_value ());
+}
+
+void
+install_cdm_cdm_ops (void)
+{
+  INSTALL_UNOP (op_uplus, octave_complex_diag_matrix, uplus);
+  INSTALL_UNOP (op_uminus, octave_complex_diag_matrix, uminus);
+  INSTALL_UNOP (op_transpose, octave_complex_diag_matrix, transpose);
+  INSTALL_UNOP (op_hermitian, octave_complex_diag_matrix, hermitian);
+
+  INSTALL_BINOP (op_add, octave_complex_diag_matrix, octave_complex_diag_matrix, add);
+  INSTALL_BINOP (op_sub, octave_complex_diag_matrix, octave_complex_diag_matrix, sub);
+  INSTALL_BINOP (op_mul, octave_complex_diag_matrix, octave_complex_diag_matrix, mul);
+  INSTALL_BINOP (op_div, octave_complex_diag_matrix, octave_complex_diag_matrix, div);
+  INSTALL_BINOP (op_ldiv, octave_complex_diag_matrix, octave_complex_diag_matrix, ldiv);
+
+  INSTALL_CONVOP (octave_complex_diag_matrix, octave_complex_matrix, complex_diag_matrix_to_complex_matrix);
+  INSTALL_CONVOP (octave_complex_diag_matrix, octave_float_complex_diag_matrix, 
+                  complex_diag_matrix_to_float_complex_diag_matrix);
+  INSTALL_ASSIGNCONV (octave_complex_diag_matrix, octave_complex_matrix, octave_complex_matrix);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-cdm-cm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-cx-diag.h"
+#define RINCLUDE "ov-cx-mat.h"
+
+#define LMATRIX complex_diag_matrix
+#define RMATRIX complex_matrix
+
+#define LSHORT cdm
+#define RSHORT cm
+
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-cdm-cs.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,33 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define SINCLUDE "ov-complex.h"
+#define MINCLUDE "ov-cx-diag.h"
+
+#define SCALAR complex
+#define MATRIX complex_diag_matrix
+
+#define SSHORT cs
+#define MSHORT cdm
+
+#include "op-dms-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-cdm-dm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,37 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-cx-diag.h"
+#define RINCLUDE "ov-re-diag.h"
+
+#define LMATRIX complex_diag_matrix
+#define RMATRIX diag_matrix
+#define RDMATRIX LMATRIX
+
+#define LSHORT cdm
+#define RSHORT dm
+
+#define DEFINEDIV
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-cdm-m.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,36 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-cx-diag.h"
+#define RINCLUDE "ov-re-mat.h"
+
+#define LMATRIX complex_diag_matrix
+#define RMATRIX matrix
+#define RDMATRIX complex_matrix
+
+#define LSHORT cdm
+#define RSHORT m
+
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-cdm-s.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,34 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define SINCLUDE "ov-scalar.h"
+#define MINCLUDE "ov-cx-diag.h"
+
+#define SCALAR scalar
+#define SCALARV complex
+#define MATRIX complex_diag_matrix
+
+#define SSHORT s
+#define MSHORT cdm
+
+#include "op-dms-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-cm-cdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-cx-mat.h"
+#define RINCLUDE "ov-cx-diag.h"
+
+#define LMATRIX complex_matrix
+#define RMATRIX complex_diag_matrix
+
+#define LSHORT cm
+#define RSHORT cdm
+
+#define DEFINEDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-cm-dm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-cx-mat.h"
+#define RINCLUDE "ov-re-diag.h"
+
+#define LMATRIX complex_matrix
+#define RMATRIX diag_matrix
+
+#define LSHORT cm
+#define RSHORT dm
+
+#define DEFINEDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-dm-cdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,37 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-re-diag.h"
+#define RINCLUDE "ov-cx-diag.h"
+
+#define LMATRIX diag_matrix
+#define RMATRIX complex_diag_matrix
+#define LDMATRIX RMATRIX
+
+#define LSHORT dm
+#define RSHORT cdm
+
+#define DEFINEDIV
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-dm-cm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-re-diag.h"
+#define RINCLUDE "ov-cx-mat.h"
+
+#define LMATRIX diag_matrix
+#define RMATRIX complex_matrix
+
+#define LSHORT dm
+#define RSHORT cm
+
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-dm-cs.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,34 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define SINCLUDE "ov-complex.h"
+#define MINCLUDE "ov-re-diag.h"
+
+#define SCALAR complex
+#define MATRIX diag_matrix
+#define MATRIXV complex_diag_matrix
+
+#define SSHORT cs
+#define MSHORT dm
+
+#include "op-dms-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-dm-dm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,102 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gripes.h"
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-re-mat.h"
+#include "ov-re-diag.h"
+#include "ov-flt-re-diag.h"
+#include "ov-typeinfo.h"
+#include "ops.h"
+#include "xdiv.h"
+#include "xpow.h"
+
+// matrix unary ops.
+
+DEFUNOP_OP (uplus, diag_matrix, /* no-op */)
+DEFUNOP_OP (uminus, diag_matrix, -)
+
+DEFUNOP (transpose, diag_matrix)
+{
+  CAST_UNOP_ARG (const octave_diag_matrix&);
+  return octave_value (v.diag_matrix_value().transpose ());
+}
+
+// matrix by matrix ops.
+
+DEFBINOP_OP (add, diag_matrix, diag_matrix, +)
+DEFBINOP_OP (sub, diag_matrix, diag_matrix, -)
+DEFBINOP_OP (mul, diag_matrix, diag_matrix, *)
+
+DEFBINOP (div, diag_matrix, diag_matrix)
+{
+  CAST_BINOP_ARGS (const octave_diag_matrix&, const octave_diag_matrix&);
+  
+  return xdiv (v1.diag_matrix_value (), 
+               v2.diag_matrix_value ());
+}
+
+DEFBINOP (ldiv, diag_matrix, diag_matrix)
+{
+  CAST_BINOP_ARGS (const octave_diag_matrix&, const octave_diag_matrix&);
+  
+  return xleftdiv (v1.diag_matrix_value (),
+                   v2.diag_matrix_value ());
+}
+
+CONVDECL (diag_matrix_to_matrix)
+{
+  CAST_CONV_ARG (const octave_diag_matrix&);
+
+  return new octave_matrix (v.matrix_value ());
+}
+
+CONVDECL (diag_matrix_to_float_diag_matrix)
+{
+  CAST_CONV_ARG (const octave_diag_matrix&);
+
+  return new octave_float_diag_matrix (v.float_diag_matrix_value ());
+}
+
+void
+install_dm_dm_ops (void)
+{
+  INSTALL_UNOP (op_uplus, octave_diag_matrix, uplus);
+  INSTALL_UNOP (op_uminus, octave_diag_matrix, uminus);
+  INSTALL_UNOP (op_transpose, octave_diag_matrix, transpose);
+  INSTALL_UNOP (op_hermitian, octave_diag_matrix, transpose);
+
+  INSTALL_BINOP (op_add, octave_diag_matrix, octave_diag_matrix, add);
+  INSTALL_BINOP (op_sub, octave_diag_matrix, octave_diag_matrix, sub);
+  INSTALL_BINOP (op_mul, octave_diag_matrix, octave_diag_matrix, mul);
+  INSTALL_BINOP (op_div, octave_diag_matrix, octave_diag_matrix, div);
+  INSTALL_BINOP (op_ldiv, octave_diag_matrix, octave_diag_matrix, ldiv);
+
+  INSTALL_CONVOP (octave_diag_matrix, octave_matrix, diag_matrix_to_matrix);
+  INSTALL_CONVOP (octave_diag_matrix, octave_float_diag_matrix, diag_matrix_to_float_diag_matrix);
+  INSTALL_ASSIGNCONV (octave_diag_matrix, octave_matrix, octave_matrix);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-dm-m.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-re-diag.h"
+#define RINCLUDE "ov-re-mat.h"
+
+#define LMATRIX diag_matrix
+#define RMATRIX matrix
+
+#define LSHORT dm
+#define RSHORT m
+
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-dm-s.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,33 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define SINCLUDE "ov-scalar.h"
+#define MINCLUDE "ov-re-diag.h"
+
+#define SCALAR scalar
+#define MATRIX diag_matrix
+
+#define SSHORT s
+#define MSHORT dm
+
+#include "op-dms-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-dm-template.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,88 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ops.h"
+#include "xdiv.h"
+#include LINCLUDE
+#include RINCLUDE
+
+// matrix by diag matrix ops.
+
+DEFBINOP_OP (add, LMATRIX, RMATRIX, +)
+DEFBINOP_OP (sub, LMATRIX, RMATRIX, -)
+DEFBINOP_OP (mul, LMATRIX, RMATRIX, *)
+
+#ifndef LDMATRIX
+#define LDMATRIX LMATRIX
+#endif
+
+#ifndef RDMATRIX
+#define RDMATRIX RMATRIX
+#endif
+
+#define OCTAVE_LMATRIX CONCAT2(octave_, LMATRIX)
+#define OCTAVE_RMATRIX CONCAT2(octave_, RMATRIX)
+#define LMATRIX_VALUE CONCAT2(LMATRIX, _value)
+#define RMATRIX_VALUE CONCAT2(RMATRIX, _value)
+#define LDMATRIX_VALUE CONCAT2(LDMATRIX, _value)
+#define RDMATRIX_VALUE CONCAT2(RDMATRIX, _value)
+
+#ifdef DEFINEDIV
+DEFBINOP (div, LMATRIX, RMATRIX)
+{
+  CAST_BINOP_ARGS (const OCTAVE_LMATRIX&, const OCTAVE_RMATRIX&);
+
+  return xdiv (v1.LDMATRIX_VALUE (), v2.RMATRIX_VALUE ());
+}
+#endif
+
+#ifdef DEFINELDIV
+DEFBINOP (ldiv, LMATRIX, RMATRIX)
+{
+  CAST_BINOP_ARGS (const OCTAVE_LMATRIX&, const OCTAVE_RMATRIX&);
+
+  return xleftdiv (v1.LMATRIX_VALUE (), v2.RDMATRIX_VALUE ());
+}
+#endif
+
+#define SHORT_NAME CONCAT3(LSHORT, _, RSHORT)
+#define INST_NAME CONCAT3(install_, SHORT_NAME, _ops)
+
+void
+INST_NAME (void)
+{
+  INSTALL_BINOP (op_add, OCTAVE_LMATRIX, OCTAVE_RMATRIX, add);
+  INSTALL_BINOP (op_sub, OCTAVE_LMATRIX, OCTAVE_RMATRIX, sub);
+  INSTALL_BINOP (op_mul, OCTAVE_LMATRIX, OCTAVE_RMATRIX, mul);
+#ifdef DEFINEDIV
+  INSTALL_BINOP (op_div, OCTAVE_LMATRIX, OCTAVE_RMATRIX, div);
+#endif
+#ifdef DEFINELDIV
+  INSTALL_BINOP (op_ldiv, OCTAVE_LMATRIX, OCTAVE_RMATRIX, ldiv);
+#endif
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-dms-template.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,75 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ops.h"
+#include SINCLUDE
+#include MINCLUDE
+
+// matrix by diag matrix ops.
+
+#ifndef SCALARV
+#define SCALARV SCALAR
+#endif
+
+#ifndef MATRIXV
+#define MATRIXV MATRIX
+#endif
+
+DEFNDBINOP_OP (sdmadd, SCALAR, MATRIX, SCALARV, MATRIXV, +)
+DEFNDBINOP_OP (sdmsub, SCALAR, MATRIX, SCALARV, MATRIXV, -)
+DEFNDBINOP_OP (sdmmul, SCALAR, MATRIX, SCALARV, MATRIXV, *)
+DEFNDBINOP_OP (dmsadd, MATRIX, SCALAR, MATRIXV, SCALARV, +)
+DEFNDBINOP_OP (dmssub, MATRIX, SCALAR, MATRIXV, SCALARV, -)
+DEFNDBINOP_OP (dmsmul, MATRIX, SCALAR, MATRIXV, SCALARV, *)
+DEFNDBINOP_OP (dmsdiv, MATRIX, SCALAR, MATRIXV, SCALARV, /)
+
+#define OCTAVE_MATRIX CONCAT2(octave_, MATRIX)
+#define OCTAVE_SCALAR CONCAT2(octave_, SCALAR)
+#define MATRIX_VALUE CONCAT2(MATRIXV, _value)
+#define SCALAR_VALUE CONCAT2(SCALARV, _value)
+
+DEFBINOP (sdmldiv, SCALAR, MATRIX)
+{
+  CAST_BINOP_ARGS (const OCTAVE_SCALAR&, const OCTAVE_MATRIX&);
+
+  return v2.MATRIX_VALUE () / v1.SCALAR_VALUE ();
+}
+
+#define SHORT_NAME CONCAT3(MSHORT, _, SSHORT)
+#define INST_NAME CONCAT3(install_, SHORT_NAME, _ops)
+
+void
+INST_NAME (void)
+{
+  INSTALL_BINOP (op_add, OCTAVE_MATRIX, OCTAVE_SCALAR, dmsadd);
+  INSTALL_BINOP (op_sub, OCTAVE_MATRIX, OCTAVE_SCALAR, dmssub);
+  INSTALL_BINOP (op_mul, OCTAVE_MATRIX, OCTAVE_SCALAR, dmsmul);
+  INSTALL_BINOP (op_div, OCTAVE_MATRIX, OCTAVE_SCALAR, dmsdiv);
+  INSTALL_BINOP (op_add, OCTAVE_SCALAR, OCTAVE_MATRIX, sdmadd);
+  INSTALL_BINOP (op_sub, OCTAVE_SCALAR, OCTAVE_MATRIX, sdmsub);
+  INSTALL_BINOP (op_mul, OCTAVE_SCALAR, OCTAVE_MATRIX, sdmmul);
+  INSTALL_BINOP (op_ldiv, OCTAVE_SCALAR, OCTAVE_MATRIX, sdmldiv);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fcdm-fcdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,109 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gripes.h"
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-flt-cx-mat.h"
+#include "ov-flt-cx-diag.h"
+#include "ov-cx-diag.h"
+#include "ov-typeinfo.h"
+#include "ops.h"
+#include "xdiv.h"
+#include "xpow.h"
+
+// matrix unary ops.
+
+DEFUNOP_OP (uplus, float_complex_diag_matrix, /* no-op */)
+DEFUNOP_OP (uminus, float_complex_diag_matrix, -)
+
+DEFUNOP (transpose, float_complex_diag_matrix)
+{
+  CAST_UNOP_ARG (const octave_float_complex_diag_matrix&);
+  return octave_value (v.float_complex_diag_matrix_value().transpose ());
+}
+
+DEFUNOP (hermitian, float_complex_diag_matrix)
+{
+  CAST_UNOP_ARG (const octave_float_complex_diag_matrix&);
+  return octave_value (v.float_complex_diag_matrix_value().hermitian ());
+}
+
+// matrix by matrix ops.
+
+DEFBINOP_OP (add, float_complex_diag_matrix, float_complex_diag_matrix, +)
+DEFBINOP_OP (sub, float_complex_diag_matrix, float_complex_diag_matrix, -)
+DEFBINOP_OP (mul, float_complex_diag_matrix, float_complex_diag_matrix, *)
+
+DEFBINOP (div, float_complex_diag_matrix, float_complex_diag_matrix)
+{
+  CAST_BINOP_ARGS (const octave_float_complex_diag_matrix&, const octave_float_complex_diag_matrix&);
+  
+  return xdiv (v1.float_complex_diag_matrix_value (), 
+               v2.float_complex_diag_matrix_value ());
+}
+
+DEFBINOP (ldiv, float_complex_diag_matrix, float_complex_diag_matrix)
+{
+  CAST_BINOP_ARGS (const octave_float_complex_diag_matrix&, const octave_float_complex_diag_matrix&);
+  
+  return xleftdiv (v1.float_complex_diag_matrix_value (),
+                   v2.float_complex_diag_matrix_value ());
+}
+
+CONVDECL (float_complex_diag_matrix_to_float_complex_matrix)
+{
+  CAST_CONV_ARG (const octave_float_complex_diag_matrix&);
+
+  return new octave_float_complex_matrix (v.float_complex_matrix_value ());
+}
+
+CONVDECL (float_complex_diag_matrix_to_complex_diag_matrix)
+{
+  CAST_CONV_ARG (const octave_float_complex_diag_matrix&);
+
+  return new octave_complex_diag_matrix (v.complex_diag_matrix_value ());
+}
+
+void
+install_fcdm_fcdm_ops (void)
+{
+  INSTALL_UNOP (op_uplus, octave_float_complex_diag_matrix, uplus);
+  INSTALL_UNOP (op_uminus, octave_float_complex_diag_matrix, uminus);
+  INSTALL_UNOP (op_transpose, octave_float_complex_diag_matrix, transpose);
+  INSTALL_UNOP (op_hermitian, octave_float_complex_diag_matrix, hermitian);
+
+  INSTALL_BINOP (op_add, octave_float_complex_diag_matrix, octave_float_complex_diag_matrix, add);
+  INSTALL_BINOP (op_sub, octave_float_complex_diag_matrix, octave_float_complex_diag_matrix, sub);
+  INSTALL_BINOP (op_mul, octave_float_complex_diag_matrix, octave_float_complex_diag_matrix, mul);
+  INSTALL_BINOP (op_div, octave_float_complex_diag_matrix, octave_float_complex_diag_matrix, div);
+  INSTALL_BINOP (op_ldiv, octave_float_complex_diag_matrix, octave_float_complex_diag_matrix, ldiv);
+
+  INSTALL_CONVOP (octave_float_complex_diag_matrix, octave_complex_diag_matrix, float_complex_diag_matrix_to_complex_diag_matrix);
+  INSTALL_CONVOP (octave_float_complex_diag_matrix, octave_float_complex_matrix, 
+                  float_complex_diag_matrix_to_float_complex_matrix);
+  INSTALL_ASSIGNCONV (octave_float_complex_diag_matrix, octave_float_complex_matrix, octave_float_complex_matrix);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fcdm-fcm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-flt-cx-diag.h"
+#define RINCLUDE "ov-flt-cx-mat.h"
+
+#define LMATRIX float_complex_diag_matrix
+#define RMATRIX float_complex_matrix
+
+#define LSHORT fcdm
+#define RSHORT fcm
+
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fcdm-fcs.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,33 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define SINCLUDE "ov-flt-complex.h"
+#define MINCLUDE "ov-flt-cx-diag.h"
+
+#define SCALAR float_complex
+#define MATRIX float_complex_diag_matrix
+
+#define SSHORT fcs
+#define MSHORT fcdm
+
+#include "op-dms-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fcdm-fdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,51 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gripes.h"
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-flt-cx-diag.h"
+#include "ov-flt-re-diag.h"
+#include "ov-typeinfo.h"
+#include "ops.h"
+#include "xdiv.h"
+#include "xpow.h"
+
+#define LINCLUDE "ov-flt-cx-diag.h"
+#define RINCLUDE "ov-flt-re-diag.h"
+
+#define LMATRIX float_complex_diag_matrix
+#define RMATRIX float_diag_matrix
+#define RDMATRIX LMATRIX
+
+#define LSHORT fcdm
+#define RSHORT fdm
+
+#define DEFINEDIV
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fcdm-fm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,36 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-flt-cx-diag.h"
+#define RINCLUDE "ov-flt-re-mat.h"
+
+#define LMATRIX float_complex_diag_matrix
+#define RMATRIX float_matrix
+#define RDMATRIX float_complex_matrix
+
+#define LSHORT fcdm
+#define RSHORT fm
+
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fcdm-fs.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,34 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define SINCLUDE "ov-float.h"
+#define MINCLUDE "ov-flt-cx-diag.h"
+
+#define SCALAR float_scalar
+#define SCALARV float_complex
+#define MATRIX float_complex_diag_matrix
+
+#define SSHORT fs
+#define MSHORT fcdm
+
+#include "op-dms-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fcm-fcdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-flt-cx-mat.h"
+#define RINCLUDE "ov-flt-cx-diag.h"
+
+#define LMATRIX float_complex_matrix
+#define RMATRIX float_complex_diag_matrix
+
+#define LSHORT fcm
+#define RSHORT fcdm
+
+#define DEFINEDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fcm-fdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-flt-cx-mat.h"
+#define RINCLUDE "ov-flt-re-diag.h"
+
+#define LMATRIX float_complex_matrix
+#define RMATRIX float_diag_matrix
+
+#define LSHORT fcm
+#define RSHORT fdm
+
+#define DEFINEDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fdm-fcdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,37 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-flt-re-diag.h"
+#define RINCLUDE "ov-flt-cx-diag.h"
+
+#define LMATRIX float_diag_matrix
+#define RMATRIX float_complex_diag_matrix
+#define LDMATRIX RMATRIX
+
+#define LSHORT fdm
+#define RSHORT fcdm
+
+#define DEFINEDIV
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fdm-fcm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-flt-re-diag.h"
+#define RINCLUDE "ov-flt-cx-mat.h"
+
+#define LMATRIX float_diag_matrix
+#define RMATRIX float_complex_matrix
+
+#define LSHORT fdm
+#define RSHORT fcm
+
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fdm-fcs.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,34 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define SINCLUDE "ov-flt-complex.h"
+#define MINCLUDE "ov-flt-re-diag.h"
+
+#define SCALAR float_complex
+#define MATRIX float_diag_matrix
+#define MATRIXV float_complex_diag_matrix
+
+#define SSHORT fcs
+#define MSHORT fdm
+
+#include "op-dms-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fdm-fdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,102 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gripes.h"
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-flt-re-mat.h"
+#include "ov-flt-re-diag.h"
+#include "ov-re-diag.h"
+#include "ov-typeinfo.h"
+#include "ops.h"
+#include "xdiv.h"
+#include "xpow.h"
+
+// matrix unary ops.
+
+DEFUNOP_OP (uplus, float_diag_matrix, /* no-op */)
+DEFUNOP_OP (uminus, float_diag_matrix, -)
+
+DEFUNOP (transpose, float_diag_matrix)
+{
+  CAST_UNOP_ARG (const octave_float_diag_matrix&);
+  return octave_value (v.float_diag_matrix_value().transpose ());
+}
+
+// matrix by matrix ops.
+
+DEFBINOP_OP (add, float_diag_matrix, float_diag_matrix, +)
+DEFBINOP_OP (sub, float_diag_matrix, float_diag_matrix, -)
+DEFBINOP_OP (mul, float_diag_matrix, float_diag_matrix, *)
+
+DEFBINOP (div, float_diag_matrix, float_diag_matrix)
+{
+  CAST_BINOP_ARGS (const octave_float_diag_matrix&, const octave_float_diag_matrix&);
+  
+  return xdiv (v1.float_diag_matrix_value (), 
+               v2.float_diag_matrix_value ());
+}
+
+DEFBINOP (ldiv, float_diag_matrix, float_diag_matrix)
+{
+  CAST_BINOP_ARGS (const octave_float_diag_matrix&, const octave_float_diag_matrix&);
+  
+  return xleftdiv (v1.float_diag_matrix_value (),
+                   v2.float_diag_matrix_value ());
+}
+
+CONVDECL (float_diag_matrix_to_diag_matrix)
+{
+  CAST_CONV_ARG (const octave_float_diag_matrix&);
+
+  return new octave_diag_matrix (v.diag_matrix_value ());
+}
+
+CONVDECL (float_diag_matrix_to_float_matrix)
+{
+  CAST_CONV_ARG (const octave_float_diag_matrix&);
+
+  return new octave_float_matrix (v.float_matrix_value ());
+}
+
+void
+install_fdm_fdm_ops (void)
+{
+  INSTALL_UNOP (op_uplus, octave_float_diag_matrix, uplus);
+  INSTALL_UNOP (op_uminus, octave_float_diag_matrix, uminus);
+  INSTALL_UNOP (op_transpose, octave_float_diag_matrix, transpose);
+  INSTALL_UNOP (op_hermitian, octave_float_diag_matrix, transpose);
+
+  INSTALL_BINOP (op_add, octave_float_diag_matrix, octave_float_diag_matrix, add);
+  INSTALL_BINOP (op_sub, octave_float_diag_matrix, octave_float_diag_matrix, sub);
+  INSTALL_BINOP (op_mul, octave_float_diag_matrix, octave_float_diag_matrix, mul);
+  INSTALL_BINOP (op_div, octave_float_diag_matrix, octave_float_diag_matrix, div);
+  INSTALL_BINOP (op_ldiv, octave_float_diag_matrix, octave_float_diag_matrix, ldiv);
+
+  INSTALL_CONVOP (octave_float_diag_matrix, octave_float_matrix, float_diag_matrix_to_float_matrix);
+  INSTALL_CONVOP (octave_float_diag_matrix, octave_diag_matrix, float_diag_matrix_to_diag_matrix);
+  INSTALL_ASSIGNCONV (octave_float_diag_matrix, octave_float_matrix, octave_float_matrix);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fdm-fm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-flt-re-diag.h"
+#define RINCLUDE "ov-flt-re-mat.h"
+
+#define LMATRIX float_diag_matrix
+#define RMATRIX float_matrix
+
+#define LSHORT fdm
+#define RSHORT fm
+
+#define DEFINELDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fdm-fs.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,33 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define SINCLUDE "ov-float.h"
+#define MINCLUDE "ov-flt-re-diag.h"
+
+#define SCALAR float_scalar
+#define MATRIX float_diag_matrix
+
+#define SSHORT fs
+#define MSHORT fdm
+
+#include "op-dms-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fm-fcdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,36 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-flt-re-mat.h"
+#define RINCLUDE "ov-flt-cx-diag.h"
+
+#define LMATRIX float_matrix
+#define RMATRIX float_complex_diag_matrix
+#define LDMATRIX float_complex_matrix
+
+#define LSHORT fm
+#define RSHORT fcdm
+
+#define DEFINEDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-fm-fdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-flt-re-mat.h"
+#define RINCLUDE "ov-flt-re-diag.h"
+
+#define LMATRIX float_matrix
+#define RMATRIX float_diag_matrix
+
+#define LSHORT fm
+#define RSHORT fdm
+
+#define DEFINEDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-m-cdm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,36 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-re-mat.h"
+#define RINCLUDE "ov-cx-diag.h"
+
+#define LMATRIX matrix
+#define RMATRIX complex_diag_matrix
+#define LDMATRIX complex_matrix
+
+#define LSHORT m
+#define RSHORT cdm
+
+#define DEFINEDIV
+
+#include "op-dm-template.cc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/OPERATORS/op-m-dm.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,35 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#define LINCLUDE "ov-re-mat.h"
+#define RINCLUDE "ov-re-diag.h"
+
+#define LMATRIX matrix
+#define RMATRIX diag_matrix
+
+#define LSHORT m
+#define RSHORT dm
+
+#define DEFINEDIV
+
+#include "op-dm-template.cc"
+
--- a/src/data.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/data.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -1617,6 +1617,20 @@
       else
 	retval = args(0).diag(k);
     }
+  else if (nargin == 3)
+    {
+      octave_value arg0 = args(0);
+      if (arg0.ndims () == 2 && (args(0).rows () == 1 || args(0).columns () == 1))
+        {
+          octave_idx_type m = args(1).int_value (), n = args(2).int_value ();
+          if (! error_state)
+            retval = arg0.diag ().resize (dim_vector (m, n));
+          else
+            error ("diag: invalid dimensions");
+        }
+      else
+        error ("diag: first argument must be a vector");
+    }
   else
     print_usage ();
 
@@ -1625,7 +1639,7 @@
 
 /*
 
-%!assert(diag ([1; 2; 3]), [1, 0, 0; 0, 2, 0; 0, 0, 3]);
+%!assert(diag ([1; 2; 3])(:,:), [1, 0, 0; 0, 2, 0; 0, 0, 3]);
 %!assert(diag ([1; 2; 3], 1), [0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]);
 %!assert(diag ([1; 2; 3], 2), [0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]);
 %!assert(diag ([1; 2; 3],-1), [0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]);
@@ -1635,7 +1649,7 @@
 %!assert(diag ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0], 1), [1; 2; 3]);
 %!assert(diag ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0], -1), [1; 2; 3]);
 
-%!assert(diag (single([1; 2; 3])), single([1, 0, 0; 0, 2, 0; 0, 0, 3]));
+%!assert(diag (single([1; 2; 3]))(:,:), single([1, 0, 0; 0, 2, 0; 0, 0, 3]));
 %!assert(diag (single([1; 2; 3]), 1), single([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]));
 %!assert(diag (single([1; 2; 3]), 2), single([0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]));
 %!assert(diag (single([1; 2; 3]),-1), single([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]));
@@ -1656,7 +1670,6 @@
 %!assert(diag (int8([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), int8([1; 2; 3]));
 
 %!error <Invalid call to diag.*> diag ();
-%!error <Invalid call to diag.*> diag (1, 2, 3);
 
  */
 
@@ -4081,11 +4094,11 @@
 	  break;
 
 	case oct_data_conv::dt_single:
-	  retval = identity_matrix<FloatNDArray> (nr, nc);
+	  retval = FloatDiagMatrix (nr, nc, 1.0f);
 	  break;
 
 	case oct_data_conv::dt_double:
-	  retval = identity_matrix<NDArray> (nr, nc);
+	  retval = DiagMatrix (nr, nc, 1.0);
 	  break;
 
 	case oct_data_conv::dt_logical:
@@ -4204,11 +4217,11 @@
 
 /*
 
-%!assert (eye(3), [1, 0, 0; 0, 1, 0; 0, 0, 1]);
-%!assert (eye(2, 3), [1, 0, 0; 0, 1, 0]);
-
-%!assert (eye(3,'single'), single([1, 0, 0; 0, 1, 0; 0, 0, 1]));
-%!assert (eye(2, 3,'single'), single([1, 0, 0; 0, 1, 0]));
+%!assert (eye(3)(:,:), [1, 0, 0; 0, 1, 0; 0, 0, 1]);
+%!assert (eye(2, 3)(:,:), [1, 0, 0; 0, 1, 0]);
+
+%!assert (eye(3,'single')(:,:), single([1, 0, 0; 0, 1, 0; 0, 0, 1]));
+%!assert (eye(2, 3,'single')(:,:), single([1, 0, 0; 0, 1, 0]));
 
 %!assert (eye(3,'int8'), int8([1, 0, 0; 0, 1, 0; 0, 0, 1]));
 %!assert (eye(2, 3,'int8'), int8([1, 0, 0; 0, 1, 0]));
--- a/src/mappers.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/mappers.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -807,12 +807,12 @@
 %!assert(imag (1), 0);
 %!assert(imag (i), 1);
 %!assert(imag (1+i), 1);
-%!assert(imag ([i, 1; 1, i]), eye (2));
+%!assert(imag ([i, 1; 1, i]), eye (2)(:,:));
 
 %!assert(imag (single(1)), single(0));
 %!assert(imag (single(i)), single(1));
 %!assert(imag (single(1+i)), single(1));
-%!assert(imag (single([i, 1; 1, i])), eye (2,'single'));
+%!assert(imag (single([i, 1; 1, i])), eye (2,'single')(:,:));
 
 %!error imag ();
 %!error imag (1, 2);
@@ -1254,12 +1254,12 @@
 %!assert(real (1), 1);
 %!assert(real (i), 0);
 %!assert(real (1+i), 1);
-%!assert(real ([1, i; i, 1]), eye (2));
+%!assert(real ([1, i; i, 1]), eye (2)(:,:));
 
 %!assert(real (single(1)), single(1));
 %!assert(real (single(i)), single(0));
 %!assert(real (single(1+i)), single(1));
-%!assert(real (single([1, i; i, 1])), eye (2,'single'));
+%!assert(real (single([1, i; i, 1])), eye (2,'single')(:,:));
 
 %!error real ();
 %!error real (1, 2);
--- a/src/ops.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ops.h	Wed Dec 03 13:32:57 2008 +0100
@@ -26,33 +26,40 @@
 
 #include "Array-util.h"
 
+// Concatenation macros that enforce argument prescan
+#define CONCAT2X(x,y) x ## y
+#define CONCAT2(x,y) CONCAT2X(x,y)
+
+#define CONCAT3X(x,y,z) x ## y ## z
+#define CONCAT3(x,y,z) CONCAT3X(x,y,z)
+
 extern void install_ops (void);
 
 #define INSTALL_UNOP(op, t, f) \
   octave_value_typeinfo::register_unary_op \
-    (octave_value::op, t::static_type_id (), oct_unop_ ## f);
+    (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
 
 #define INSTALL_NCUNOP(op, t, f) \
   octave_value_typeinfo::register_non_const_unary_op \
-    (octave_value::op, t::static_type_id (), oct_unop_ ## f);
+    (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
 
 #define INSTALL_BINOP(op, t1, t2, f) \
   octave_value_typeinfo::register_binary_op \
     (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
-     oct_binop_ ## f);
+     CONCAT2(oct_binop_, f));
 
 #define INSTALL_CATOP(t1, t2, f) \
   octave_value_typeinfo::register_cat_op \
-    (t1::static_type_id (), t2::static_type_id (), oct_catop_ ## f);
+    (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_catop_, f));
 
 #define INSTALL_ASSIGNOP(op, t1, t2, f) \
   octave_value_typeinfo::register_assign_op \
     (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
-     oct_assignop_ ## f);
+     CONCAT2(oct_assignop_, f));
 
 #define INSTALL_ASSIGNANYOP(op, t1, f) \
   octave_value_typeinfo::register_assignany_op \
-    (octave_value::op, t1::static_type_id (), oct_assignop_ ## f);
+    (octave_value::op, t1::static_type_id (), CONCAT2(oct_assignop_, f));
 
 #define INSTALL_ASSIGNCONV(t1, t2, tr) \
   octave_value_typeinfo::register_pref_assign_conv \
@@ -60,11 +67,11 @@
 
 #define INSTALL_CONVOP(t1, t2, f) \
   octave_value_typeinfo::register_type_conv_op \
-    (t1::static_type_id (), t2::static_type_id (), oct_conv_ ## f);
+    (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
 
 #define INSTALL_WIDENOP(t1, t2, f) \
   octave_value_typeinfo::register_widening_op \
-    (t1::static_type_id (), t2::static_type_id (), oct_conv_ ## f);
+    (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
 
 #define BOOL_OP1(xt, xn, get_x, yt, yn, get_y) \
   xt xn = get_x; \
@@ -148,19 +155,19 @@
 
 #define ASSIGNOPDECL(name) \
   static octave_value \
-  oct_assignop_ ## name (octave_base_value& a1, \
+  CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
 			 const octave_value_list& idx, \
 			 const octave_base_value& a2)
 
 #define NULLASSIGNOPDECL(name) \
   static octave_value \
-  oct_assignop_ ## name (octave_base_value& a, \
+  CONCAT2(oct_assignop_, name) (octave_base_value& a, \
 			 const octave_value_list& idx, \
 			 const octave_base_value&)
 
 #define ASSIGNANYOPDECL(name) \
   static octave_value \
-  oct_assignop_ ## name (octave_base_value& a1, \
+  CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
 			 const octave_value_list& idx, \
 			 const octave_value& a2)
 
@@ -170,16 +177,16 @@
 #define DEFASSIGNOP_FN(name, t1, t2, f) \
   ASSIGNOPDECL (name) \
   { \
-    CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
  \
-    v1.f (idx, v2.t1 ## _value ()); \
+    v1.f (idx, v2.CONCAT2(t1, _value) ()); \
     return octave_value (); \
   }
 
 #define DEFNULLASSIGNOP_FN(name, t, f) \
   NULLASSIGNOPDECL (name) \
   { \
-    CAST_UNOP_ARG (octave_ ## t&); \
+    CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
  \
     v.f (idx); \
     return octave_value (); \
@@ -188,16 +195,16 @@
 #define DEFNDASSIGNOP_FN(name, t1, t2, e, f) \
   ASSIGNOPDECL (name) \
   { \
-    CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
  \
-    v1.f (idx, v2.e ## _value ()); \
+    v1.f (idx, v2.CONCAT2(e, _value) ()); \
     return octave_value (); \
   }
 
 #define DEFASSIGNANYOP_FN(name, t1, f) \
   ASSIGNANYOPDECL (name) \
   { \
-    octave_ ## t1& v1 = dynamic_cast<octave_ ## t1&> (a1); \
+    CONCAT2(octave_, t1)& v1 = dynamic_cast<CONCAT2(octave_, t1)&> (a1); \
  \
     v1.f (idx, a2); \
     return octave_value (); \
@@ -205,11 +212,11 @@
 
 #define CONVDECL(name) \
   static octave_base_value * \
-  oct_conv_ ## name (const octave_base_value& a)
+  CONCAT2(oct_conv_, name) (const octave_base_value& a)
 
 #define CONVDECLX(name) \
   static octave_base_value * \
-  oct_conv_ ## name (const octave_base_value&)
+  CONCAT2(oct_conv_, name) (const octave_base_value&)
 
 #define DEFCONV(name, a_dummy, b_dummy) \
   CONVDECL (name)
@@ -217,42 +224,42 @@
 #define DEFCONVFNX(name, tfrom, ovtto, tto, e) \
   CONVDECL (name) \
   { \
-    CAST_CONV_ARG (const octave_ ## tfrom&); \
+    CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
  \
-    return new octave_ ## ovtto (tto ## NDArray (v.e ## array_value ())); \
+    return new CONCAT2(octave_, ovtto) (CONCAT2(tto, NDArray) (v.CONCAT2(e, array_value) ())); \
   }
 
 #define DEFCONVFNX2(name, tfrom, ovtto, e) \
   CONVDECL (name) \
   { \
-    CAST_CONV_ARG (const octave_ ## tfrom&); \
+    CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
  \
-    return new octave_ ## ovtto (v.e ## array_value ()); \
+    return new CONCAT2(octave_, ovtto) (v.CONCAT2(e, array_value) ()); \
   }
 
 #define DEFDBLCONVFN(name, ovtfrom, e) \
   CONVDECL (name) \
   { \
-    CAST_CONV_ARG (const octave_ ## ovtfrom&); \
+    CAST_CONV_ARG (const CONCAT2(octave_, ovtfrom)&); \
  \
-    return new octave_matrix (NDArray (v.e ## _value ())); \
+    return new octave_matrix (NDArray (v.CONCAT2(e, _value) ())); \
   }
 
 #define DEFSTRINTCONVFN(name, tto) \
-  DEFCONVFNX(name, char_matrix_str, tto ## _matrix, tto, char_)
+  DEFCONVFNX(name, char_matrix_str, CONCAT2(tto, _matrix), tto, char_)
 
 #define DEFSTRDBLCONVFN(name, tfrom) \
   DEFCONVFNX(name, tfrom, matrix, , char_)
 
 #define DEFCONVFN(name, tfrom, tto) \
-  DEFCONVFNX2 (name, tfrom, tto ## _matrix, tto ## _)
+  DEFCONVFNX2 (name, tfrom, CONCAT2(tto, _matrix), CONCAT2(tto, _))
 
 #define DEFCONVFN2(name, tfrom, sm, tto) \
-  DEFCONVFNX2 (name, tfrom ## _ ## sm, tto ## _matrix, tto ## _)
+  DEFCONVFNX2 (name, CONCAT3(tfrom, _, sm), CONCAT2(tto, _matrix), CONCAT2(tto, _))
 
 #define UNOPDECL(name, a) \
   static octave_value \
-  oct_unop_ ## name (const octave_base_value& a)
+  CONCAT2(oct_unop_, name) (const octave_base_value& a)
 
 #define DEFUNOPX(name, t) \
   UNOPDECL (name, , )
@@ -263,15 +270,15 @@
 #define DEFUNOP_OP(name, t, op) \
   UNOPDECL (name, a) \
   { \
-    CAST_UNOP_ARG (const octave_ ## t&); \
-    return octave_value (op v.t ## _value ()); \
+    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
+    return octave_value (op v.CONCAT2(t, _value) ()); \
   }
 
 #define DEFNDUNOP_OP(name, t, e, op) \
   UNOPDECL (name, a) \
   { \
-    CAST_UNOP_ARG (const octave_ ## t&); \
-    return octave_value (op v.e ## _value ()); \
+    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
+    return octave_value (op v.CONCAT2(e, _value) ()); \
   }
 
 // FIXME -- in some cases, the constructor isn't necessary.
@@ -279,28 +286,28 @@
 #define DEFUNOP_FN(name, t, f) \
   UNOPDECL (name, a) \
   { \
-    CAST_UNOP_ARG (const octave_ ## t&); \
-    return octave_value (f (v.t ## _value ())); \
+    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
+    return octave_value (f (v.CONCAT2(t, _value) ())); \
   }
 
 #define DEFNDUNOP_FN(name, t, e, f) \
   UNOPDECL (name, a) \
   { \
-    CAST_UNOP_ARG (const octave_ ## t&); \
-    return octave_value (f (v.e ## _value ())); \
+    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
+    return octave_value (f (v.CONCAT2(e, _value) ())); \
   }
 
 #define DEFNCUNOP_METHOD(name, t, method) \
   static void \
-  oct_unop_ ## name (octave_base_value& a) \
+  CONCAT2(oct_unop_, name) (octave_base_value& a) \
   { \
-    CAST_UNOP_ARG (octave_ ## t&); \
+    CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
     v.method (); \
   }
 
 #define BINOPDECL(name, a1, a2) \
   static octave_value \
-  oct_binop_ ## name (const octave_base_value& a1, const octave_base_value& a2)
+  CONCAT2(oct_binop_, name) (const octave_base_value& a1, const octave_base_value& a2)
 
 #define DEFBINOPX(name, t1, t2) \
   BINOPDECL (name, , )
@@ -311,31 +318,31 @@
 #define DEFBINOP_OP(name, t1, t2, op) \
   BINOPDECL (name, a1, a2) \
   { \
-    CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
     return octave_value \
-      (v1.t1 ## _value () op v2.t2 ## _value ()); \
+      (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
   }
 
 #define DEFSCALARBOOLOP_OP(name, t1, t2, op) \
   BINOPDECL (name, a1, a2) \
   { \
-    CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
-    if (xisnan (v1.t1 ## _value ()) || xisnan (v2.t2 ## _value ())) \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    if (xisnan (v1.CONCAT2(t1, _value) ()) || xisnan (v2.CONCAT2(t2, _value) ())) \
       { \
         error ("invalid conversion from NaN to logical"); \
         return octave_value (); \
       } \
     else \
       return octave_value \
-        (v1.t1 ## _value () op v2.t2 ## _value ()); \
+        (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
   }
 
 #define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \
   BINOPDECL (name, a1, a2) \
   { \
-    CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
     return octave_value \
-      (v1.e1 ## _value () op v2.e2 ## _value ()); \
+      (v1.CONCAT2(e1, _value) () op v2.CONCAT2(e2, _value) ()); \
   }
 
 // FIXME -- in some cases, the constructor isn't necessary.
@@ -343,15 +350,15 @@
 #define DEFBINOP_FN(name, t1, t2, f) \
   BINOPDECL (name, a1, a2) \
   { \
-    CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
-    return octave_value (f (v1.t1 ## _value (), v2.t2 ## _value ())); \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (f (v1.CONCAT2(t1, _value) (), v2.CONCAT2(t2, _value) ())); \
   }
 
 #define DEFNDBINOP_FN(name, t1, t2, e1, e2, f) \
   BINOPDECL (name, a1, a2) \
   { \
-    CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
-    return octave_value (f (v1.e1 ## _value (), v2.e2 ## _value ())); \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (f (v1.CONCAT2(e1, _value) (), v2.CONCAT2(e2, _value) ())); \
   }
 
 #define BINOP_NONCONFORMANT(msg) \
@@ -362,7 +369,7 @@
 
 #define CATOPDECL(name, a1, a2)	\
   static octave_value \
-  oct_catop_ ## name (octave_base_value& a1, const octave_base_value& a2, \
+  CONCAT2(oct_catop_, name) (octave_base_value& a1, const octave_base_value& a2, \
 		      const Array<octave_idx_type>& ra_idx)
 
 #define DEFCATOPX(name, t1, t2)	\
@@ -376,21 +383,21 @@
 #define DEFCATOP_FN(name, t1, t2, f) \
   CATOPDECL (name, a1, a2) \
   { \
-    CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \
-    return octave_value (v1.t1 ## _value () . f (v2.t2 ## _value (), ra_idx)); \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (v1.CONCAT2(t1, _value) () . f (v2.CONCAT2(t2, _value) (), ra_idx)); \
   }
 
 #define DEFNDCATOP_FN(name, t1, t2, e1, e2, f) \
   CATOPDECL (name, a1, a2) \
   { \
-    CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \
-    return octave_value (v1.e1 ## _value () . f (v2.e2 ## _value (), ra_idx)); \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (v1.CONCAT2(e1, _value) () . f (v2.CONCAT2(e2, _value) (), ra_idx)); \
   }
 
 #define DEFNDCHARCATOP_FN(name, t1, t2, f) \
   CATOPDECL (name, a1, a2) \
   { \
-    CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
  \
     return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \
 			 true, ((a1.is_sq_string () || a2.is_sq_string ()) \
@@ -403,8 +410,8 @@
 #define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f) \
   CATOPDECL (name, a1, a2) \
   { \
-    CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \
-    return octave_value (tc1 (v1.e1 ## _value ()) . f (tc2 (v2.e2 ## _value ()), ra_idx)); \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (tc1 (v1.CONCAT2(e1, _value) ()) . f (tc2 (v2.CONCAT2(e2, _value) ()), ra_idx)); \
   }
 
 #define CATOP_NONCONFORMANT(msg) \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-base-diag.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,440 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+
+#include "mach-info.h"
+
+#include "ov-base.h"
+#include "ov-base-mat.h"
+#include "pr-output.h"
+#include "error.h"
+#include "gripes.h"
+#include "oct-stream.h"
+#include "ops.h"
+
+template <class DMT, class MT>
+octave_value
+octave_base_diag<DMT, MT>::subsref (const std::string& type,
+                                    const std::list<octave_value_list>& idx)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = do_index_op (idx.front ());
+      break;
+
+    case '{':
+    case '.':
+      {
+	std::string nm = type_name ();
+	error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+
+  return retval.next_subsref (type, idx);
+}
+
+template <class DMT, class MT>
+octave_value
+octave_base_diag<DMT, MT>::do_index_op (const octave_value_list& idx,
+                                        bool resize_ok)
+{
+  octave_value retval;
+
+  if (idx.length () == 2 && idx(0).is_scalar_type () 
+      && idx(1).is_scalar_type () && ! resize_ok)
+    {
+      idx_vector i = idx(0).index_vector (), j = idx(1).index_vector ();
+      // FIXME: the proxy mechanism of DiagArray2 causes problems here.
+      typedef typename DMT::element_type el_type;
+      if (! error_state)
+         retval = el_type (matrix.checkelem (i(0), j(0)));
+    }
+  else
+    retval = to_dense ().do_index_op (idx, resize_ok);
+  return retval;
+}
+
+template <class DMT, class MT>
+octave_value
+octave_base_diag<DMT, MT>::resize (const dim_vector& dv, bool fill) const
+{
+  octave_value retval;
+  if (dv.length () == 2)
+    {
+      DMT rm (matrix);
+      rm.resize (dv(0), dv(1));
+      retval = rm;
+    }
+  else
+    retval = to_dense ().resize (dv, fill);
+  return retval;
+}
+
+template <class DMT, class MT>
+bool
+octave_base_diag<DMT, MT>::is_true (void) const
+{
+  return to_dense ().is_true ();
+}
+
+template <class DMT, class MT>
+bool
+octave_base_diag<DMT, MT>::valid_as_scalar_index (void) const
+{
+  // FIXME
+  return false;
+}
+
+// FIXME: this should be achieveable using ::real
+template <class T> inline T helper_getreal (T x) { return x; }
+template <class T> inline T helper_getreal (std::complex<T> x) { return x.real (); }
+// FIXME: we really need some traits so that ad hoc hooks like this are not necessary
+template <class T> inline T helper_iscomplex (T) { return false; }
+template <class T> inline T helper_iscomplex (std::complex<T>) { return true; }
+
+template <class DMT, class MT>
+double
+octave_base_diag<DMT, MT>::double_value (bool force_conversion) const
+{
+  double retval = lo_ieee_nan_value ();
+  typedef typename DMT::element_type el_type;
+
+  if (helper_iscomplex (el_type ()) && ! force_conversion)
+    gripe_implicit_conversion ("Octave:imag-to-real",
+			       "complex matrix", "real scalar");
+
+  if (numel () > 0)
+    {
+      gripe_implicit_conversion ("Octave:array-as-scalar",
+				 type_name (), "real scalar");
+
+      retval = helper_getreal (el_type (matrix (0, 0)));
+    }
+  else
+    gripe_invalid_conversion (type_name (), "real scalar");
+
+  return retval;
+}
+
+template <class DMT, class MT>
+float
+octave_base_diag<DMT, MT>::float_value (bool force_conversion) const
+{
+  float retval = lo_ieee_float_nan_value ();
+  typedef typename DMT::element_type el_type;
+
+  if (helper_iscomplex (el_type ()) && ! force_conversion)
+    gripe_implicit_conversion ("Octave:imag-to-real",
+			       "complex matrix", "real scalar");
+
+  if (numel () > 0)
+    {
+      gripe_implicit_conversion ("Octave:array-as-scalar",
+				 type_name (), "real scalar");
+
+      retval = helper_getreal (el_type (matrix (0, 0)));
+    }
+  else
+    gripe_invalid_conversion (type_name (), "real scalar");
+
+  return retval;
+}
+
+template <class DMT, class MT>
+Complex
+octave_base_diag<DMT, MT>::complex_value (bool) const
+{
+  double tmp = lo_ieee_nan_value ();
+
+  Complex retval (tmp, tmp);
+
+  if (rows () > 0 && columns () > 0)
+    {
+      gripe_implicit_conversion ("Octave:array-as-scalar",
+				 type_name (), "complex scalar");
+
+      retval = matrix (0, 0);
+    }
+  else
+    gripe_invalid_conversion (type_name (), "complex scalar");
+
+  return retval;
+}
+
+template <class DMT, class MT>
+FloatComplex
+octave_base_diag<DMT, MT>::float_complex_value (bool) const
+{
+  float tmp = lo_ieee_float_nan_value ();
+
+  FloatComplex retval (tmp, tmp);
+
+  if (rows () > 0 && columns () > 0)
+    {
+      gripe_implicit_conversion ("Octave:array-as-scalar",
+				 type_name (), "complex scalar");
+
+      retval = matrix (0, 0);
+    }
+  else
+    gripe_invalid_conversion (type_name (), "complex scalar");
+
+  return retval;
+}
+
+template <class DMT, class MT>
+Matrix
+octave_base_diag<DMT, MT>::matrix_value (bool) const
+{
+  return Matrix (diag_matrix_value ());
+}
+
+template <class DMT, class MT>
+FloatMatrix
+octave_base_diag<DMT, MT>::float_matrix_value (bool) const
+{
+  return FloatMatrix (float_diag_matrix_value ());
+}
+
+template <class DMT, class MT>
+ComplexMatrix
+octave_base_diag<DMT, MT>::complex_matrix_value (bool) const
+{
+  return ComplexMatrix (complex_diag_matrix_value ());
+}
+
+template <class DMT, class MT>
+FloatComplexMatrix
+octave_base_diag<DMT, MT>::float_complex_matrix_value (bool) const
+{
+  return FloatComplexMatrix (float_complex_diag_matrix_value ());
+}
+
+template <class DMT, class MT>
+NDArray
+octave_base_diag<DMT, MT>::array_value (bool) const
+{
+  return NDArray (matrix_value ());
+}
+
+template <class DMT, class MT>
+FloatNDArray
+octave_base_diag<DMT, MT>::float_array_value (bool) const
+{
+  return FloatNDArray (float_matrix_value ());
+}
+
+template <class DMT, class MT>
+ComplexNDArray
+octave_base_diag<DMT, MT>::complex_array_value (bool) const
+{
+  return ComplexNDArray (complex_matrix_value ());
+}
+
+template <class DMT, class MT>
+FloatComplexNDArray
+octave_base_diag<DMT, MT>::float_complex_array_value (bool) const
+{
+  return FloatComplexNDArray (float_complex_matrix_value ());
+}
+
+template <class DMT, class MT>
+boolNDArray
+octave_base_diag<DMT, MT>::bool_array_value (bool warn) const
+{
+  return to_dense ().bool_array_value (warn); 
+}
+  
+template <class DMT, class MT>
+charNDArray
+octave_base_diag<DMT, MT>::char_array_value (bool warn) const
+{
+  return to_dense ().char_array_value (warn); 
+}
+  
+template <class DMT, class MT>
+SparseMatrix 
+octave_base_diag<DMT, MT>::sparse_matrix_value (bool) const
+{
+  return SparseMatrix (diag_matrix_value ());
+}
+
+template <class DMT, class MT>
+SparseComplexMatrix 
+octave_base_diag<DMT, MT>::sparse_complex_matrix_value (bool) const
+{
+  return SparseComplexMatrix (complex_diag_matrix_value ());
+}
+
+template <class DMT, class MT>
+idx_vector
+octave_base_diag<DMT, MT>::index_vector (void) const
+{
+  return to_dense ().index_vector ();
+}
+
+template <class DMT, class MT>
+octave_value
+octave_base_diag<DMT, MT>::convert_to_str_internal (bool pad, bool force, char type) const
+{
+  return to_dense ().convert_to_str_internal (pad, force, type);
+}
+
+template <class DMT, class MT>
+bool 
+octave_base_diag<DMT, MT>::save_ascii (std::ostream& os)
+{
+  // FIXME: this should probably save the matrix as diagonal.
+  return to_dense ().save_ascii (os);
+}
+
+template <class DMT, class MT>
+bool 
+octave_base_diag<DMT, MT>::save_binary (std::ostream& os, bool& save_as_floats)
+{
+  return to_dense ().save_binary (os, save_as_floats);
+}
+
+#if defined (HAVE_HDF5)
+
+template <class DMT, class MT>
+bool
+octave_base_diag<DMT, MT>::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
+{
+  return to_dense ().save_hdf5 (loc_id, name, save_as_floats);
+}
+
+#endif
+
+template <class DMT, class MT>
+void
+octave_base_diag<DMT, MT>::print_raw (std::ostream& os,
+			  bool pr_as_read_syntax) const
+{
+  return to_dense ().print_raw (os, pr_as_read_syntax);
+}
+
+template <class DMT, class MT>
+mxArray *
+octave_base_diag<DMT, MT>::as_mxArray (void) const
+{
+  return to_dense ().as_mxArray ();
+}
+
+template <class DMT, class MT>
+bool
+octave_base_diag<DMT, MT>::print_as_scalar (void) const
+{
+  dim_vector dv = dims ();
+
+  return (dv.all_ones () || dv.any_zero ());
+}
+
+template <class DMT, class MT>
+void
+octave_base_diag<DMT, MT>::print (std::ostream& os, bool pr_as_read_syntax) const
+{
+  to_dense ().print (os, pr_as_read_syntax);
+}
+template <class DMT, class MT>
+int
+octave_base_diag<DMT, MT>::write (octave_stream& os, int block_size,
+                                  oct_data_conv::data_type output_type, int skip,
+                                  oct_mach_info::float_format flt_fmt) const
+{ 
+  return to_dense ().write (os, block_size, output_type, skip, flt_fmt); 
+}
+
+template <class DMT, class MT>
+void
+octave_base_diag<DMT, MT>::print_info (std::ostream& os,
+				    const std::string& prefix) const
+{
+  matrix.print_info (os, prefix);
+}
+
+template <class DMT, class MT>
+octave_value
+octave_base_diag<DMT, MT>::to_dense (void) const
+{
+  if (! dense_cache.is_defined ())
+      dense_cache = MT (matrix);
+
+  return dense_cache;
+}
+
+#define FORWARD_MAPPER(MAP) \
+  template <class DMT, class MT> \
+  octave_value \
+  octave_base_diag<DMT, MT>::MAP (void) const \
+  { \
+    return to_dense ().MAP (); \
+  }
+
+FORWARD_MAPPER (erf)
+FORWARD_MAPPER (erfc)
+FORWARD_MAPPER (gamma)
+FORWARD_MAPPER (lgamma)
+FORWARD_MAPPER (acos)
+FORWARD_MAPPER (acosh)
+FORWARD_MAPPER (angle)
+FORWARD_MAPPER (arg)
+FORWARD_MAPPER (asin)
+FORWARD_MAPPER (asinh)
+FORWARD_MAPPER (atan)
+FORWARD_MAPPER (atanh)
+FORWARD_MAPPER (ceil)
+FORWARD_MAPPER (cos)
+FORWARD_MAPPER (cosh)
+FORWARD_MAPPER (exp)
+FORWARD_MAPPER (expm1)
+FORWARD_MAPPER (fix)
+FORWARD_MAPPER (floor)
+FORWARD_MAPPER (log)
+FORWARD_MAPPER (log2)
+FORWARD_MAPPER (log10)
+FORWARD_MAPPER (log1p)
+FORWARD_MAPPER (round)
+FORWARD_MAPPER (roundb)
+FORWARD_MAPPER (signum)
+FORWARD_MAPPER (sin)
+FORWARD_MAPPER (sinh)
+FORWARD_MAPPER (sqrt)
+FORWARD_MAPPER (tan)
+FORWARD_MAPPER (tanh)
+FORWARD_MAPPER (finite)
+FORWARD_MAPPER (isinf)
+FORWARD_MAPPER (isna)
+FORWARD_MAPPER (isnan)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-base-diag.h	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,259 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_base_diag_h)
+#define octave_base_diag_h 1
+
+#include <cstdlib>
+
+#include <iostream>
+#include <string>
+
+#include "mx-base.h"
+#include "str-vec.h"
+
+#include "oct-obj.h"
+#include "ov-base.h"
+#include "ov-typeinfo.h"
+
+class tree_walker;
+
+// Real matrix values.
+
+template <class DMT, class MT>
+class
+octave_base_diag : public octave_base_value
+{
+
+public:
+
+  octave_base_diag (void)
+    : octave_base_value () { }
+
+  octave_base_diag (const DMT& m)
+    : octave_base_value (), matrix (m)
+  { }
+
+  octave_base_diag (const octave_base_diag& m)
+    : octave_base_value (), matrix (m.matrix) { }
+
+  ~octave_base_diag (void) { }
+
+  size_t byte_size (void) const { return matrix.byte_size (); }
+
+  octave_value squeeze (void) const { return matrix; }
+
+  octave_value subsref (const std::string& type,
+			const std::list<octave_value_list>& idx);
+
+  octave_value_list subsref (const std::string& type,
+			     const std::list<octave_value_list>& idx, int)
+    { return subsref (type, idx); }
+
+  octave_value do_index_op (const octave_value_list& idx,
+			    bool resize_ok = false);
+
+  dim_vector dims (void) const { return matrix.dims (); }
+
+  octave_idx_type nnz (void) const { return to_dense ().nnz (); }
+
+  octave_value reshape (const dim_vector& new_dims) const
+    { return to_dense ().reshape (new_dims); }
+
+  octave_value permute (const Array<int>& vec, bool inv = false) const
+    { return to_dense ().permute (vec, inv); }
+
+  octave_value resize (const dim_vector& dv, bool fill = false) const;
+
+  octave_value all (int dim = 0) const { return MT (matrix).all (dim); }
+  octave_value any (int dim = 0) const { return MT (matrix).any (dim); }
+
+  MatrixType matrix_type (void) const { return MatrixType::Diagonal; }
+  MatrixType matrix_type (const MatrixType&) const
+    { return matrix_type (); }
+
+  octave_value diag (octave_idx_type k = 0) const
+    { return octave_value (matrix.diag (k)); }
+
+  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
+    { return to_dense ().sort (dim, mode); }
+  octave_value sort (Array<octave_idx_type> &sidx, octave_idx_type dim = 0,
+		     sortmode mode = ASCENDING) const
+    { return to_dense ().sort (sidx, dim, mode); }
+
+  bool is_matrix_type (void) const { return true; }
+
+  bool is_numeric_type (void) const { return true; }
+
+  bool is_defined (void) const { return true; }
+
+  bool is_constant (void) const { return true; }
+
+  bool is_true (void) const;
+
+  bool is_diag_matrix (void) const { return true; }
+
+  bool valid_as_scalar_index (void) const;
+
+  double double_value (bool = false) const;
+
+  float float_value (bool = false) const;
+
+  double scalar_value (bool frc_str_conv = false) const
+    { return double_value (frc_str_conv); }
+
+  idx_vector index_vector (void) const;
+
+  virtual DiagMatrix diag_matrix_value (bool = false) const = 0;
+
+  virtual FloatDiagMatrix float_diag_matrix_value (bool = false) const = 0;
+
+  virtual ComplexDiagMatrix complex_diag_matrix_value (bool = false) const = 0;
+
+  virtual FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const = 0;
+
+  Matrix matrix_value (bool = false) const;
+
+  FloatMatrix float_matrix_value (bool = false) const;
+
+  Complex complex_value (bool = false) const;
+
+  FloatComplex float_complex_value (bool = false) const;
+
+  ComplexMatrix complex_matrix_value (bool = false) const;
+
+  FloatComplexMatrix float_complex_matrix_value (bool = false) const;
+
+  ComplexNDArray complex_array_value (bool = false) const;
+   
+  FloatComplexNDArray float_complex_array_value (bool = false) const;
+   
+  boolNDArray bool_array_value (bool warn = false) const;
+
+  charNDArray char_array_value (bool = false) const;
+  
+  NDArray array_value (bool = false) const; 
+
+  FloatNDArray float_array_value (bool = false) const;
+
+  SparseMatrix sparse_matrix_value (bool = false) const;
+
+  SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
+
+  int8NDArray
+  int8_array_value (void) const { return to_dense ().int8_array_value (); }
+
+  int16NDArray
+  int16_array_value (void) const { return to_dense ().int16_array_value (); }
+
+  int32NDArray
+  int32_array_value (void) const { return to_dense ().int32_array_value (); }
+
+  int64NDArray
+  int64_array_value (void) const { return to_dense ().int64_array_value (); }
+
+  uint8NDArray
+  uint8_array_value (void) const { return to_dense ().uint8_array_value (); }
+
+  uint16NDArray
+  uint16_array_value (void) const { return to_dense ().uint16_array_value (); }
+
+  uint32NDArray
+  uint32_array_value (void) const { return to_dense ().uint32_array_value (); }
+
+  uint64NDArray
+  uint64_array_value (void) const { return to_dense ().uint64_array_value (); }
+
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const;
+
+  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
+
+  bool save_ascii (std::ostream& os);
+
+  bool save_binary (std::ostream& os, bool& save_as_floats);
+
+#if defined (HAVE_HDF5)
+  bool save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats);
+#endif
+
+  int write (octave_stream& os, int block_size,
+	     oct_data_conv::data_type output_type, int skip,
+	     oct_mach_info::float_format flt_fmt) const;
+
+  mxArray *as_mxArray (void) const;
+
+  bool print_as_scalar (void) const;
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+
+  void print_info (std::ostream& os, const std::string& prefix) const;
+
+  // We forward everything except abs, real, imag, conj.
+  octave_value erf (void) const;
+  octave_value erfc (void) const;
+  octave_value gamma (void) const;
+  octave_value lgamma (void) const;
+  octave_value acos (void) const;
+  octave_value acosh (void) const;
+  octave_value angle (void) const;
+  octave_value arg (void) const;
+  octave_value asin (void) const;
+  octave_value asinh (void) const;
+  octave_value atan (void) const;
+  octave_value atanh (void) const;
+  octave_value ceil (void) const;
+  octave_value cos (void) const;
+  octave_value cosh (void) const;
+  octave_value exp (void) const;
+  octave_value expm1 (void) const;
+  octave_value fix (void) const;
+  octave_value floor (void) const;
+  octave_value log (void) const;
+  octave_value log2 (void) const;
+  octave_value log10 (void) const;
+  octave_value log1p (void) const;
+  octave_value round (void) const;
+  octave_value roundb (void) const;
+  octave_value signum (void) const;
+  octave_value sin (void) const;
+  octave_value sinh (void) const;
+  octave_value sqrt (void) const;
+  octave_value tan (void) const;
+  octave_value tanh (void) const;
+  octave_value finite (void) const;
+  octave_value isinf (void) const;
+  octave_value isna (void) const;
+  octave_value isnan (void) const;
+
+protected:
+
+  DMT matrix;
+
+  octave_value to_dense () const;
+
+private:
+
+  mutable octave_value dense_cache;
+
+};
+
+#endif
--- a/src/ov-base.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-base.h	Wed Dec 03 13:32:57 2008 +0100
@@ -236,6 +236,8 @@
 
   virtual bool is_char_matrix (void) const { return false; }
 
+  virtual bool is_diag_matrix (void) const { return false; }
+
   virtual bool is_string (void) const { return false; }
 
   virtual bool is_sq_string (void) const { return false; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-cx-diag.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,158 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-cx-diag.h"
+#include "ov-flt-cx-diag.h"
+#include "ov-re-diag.h"
+#include "ov-base-diag.cc"
+#include "ov-complex.h"
+#include "ov-cx-mat.h"
+
+template class octave_base_diag<ComplexDiagMatrix, ComplexMatrix>;
+
+DEFINE_OCTAVE_ALLOCATOR (octave_complex_diag_matrix);
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_complex_diag_matrix, 
+                                     "complex diagonal matrix", "double");
+
+static octave_base_value *
+default_numeric_conversion_function (const octave_base_value& a)
+{
+  CAST_CONV_ARG (const octave_complex_diag_matrix&);
+
+  return new octave_complex_matrix (v.complex_matrix_value ());
+}
+
+octave_base_value::type_conv_info
+octave_complex_diag_matrix::numeric_conversion_function (void) const
+{
+  return octave_base_value::type_conv_info (default_numeric_conversion_function,
+                                            octave_complex_matrix::static_type_id ());
+}
+
+static octave_base_value *
+default_numeric_demotion_function (const octave_base_value& a)
+{
+  CAST_CONV_ARG (const octave_complex_diag_matrix&);
+
+  return new octave_float_complex_diag_matrix (v.float_complex_diag_matrix_value ());
+}
+
+octave_base_value::type_conv_info
+octave_complex_diag_matrix::numeric_demotion_function (void) const
+{
+  return octave_base_value::type_conv_info (default_numeric_demotion_function,
+                                            octave_float_complex_diag_matrix::static_type_id ());
+}
+
+octave_base_value *
+octave_complex_diag_matrix::try_narrowing_conversion (void)
+{
+  octave_base_value *retval = 0;
+
+  if (matrix.nelem () == 1)
+    {
+      // FIXME: the proxy mechanism of DiagArray2 causes problems here.
+      retval = new octave_complex (Complex (matrix (0, 0)));
+      octave_base_value *rv2 = retval->try_narrowing_conversion ();
+      if (rv2)
+        {
+          delete retval;
+          retval = rv2;
+        }
+    }
+  else if (matrix.all_elements_are_real ())
+    {
+      return new octave_diag_matrix (::real (matrix));
+    }
+
+  return retval;
+}
+
+DiagMatrix
+octave_complex_diag_matrix::diag_matrix_value (bool force_conversion) const
+{
+  DiagMatrix retval;
+
+  if (! force_conversion)
+    gripe_implicit_conversion ("Octave:imag-to-real",
+			       type_name (), "real matrix");
+
+  retval = ::real (matrix);
+
+  return retval;
+}
+
+FloatDiagMatrix
+octave_complex_diag_matrix::float_diag_matrix_value (bool force_conversion) const
+{
+  DiagMatrix retval;
+
+  if (! force_conversion)
+    gripe_implicit_conversion ("Octave:imag-to-real",
+			       type_name (), "real matrix");
+
+  retval = ::real (matrix);
+
+  return retval;
+}
+
+ComplexDiagMatrix
+octave_complex_diag_matrix::complex_diag_matrix_value (bool) const
+{
+  return matrix;
+}
+
+FloatComplexDiagMatrix
+octave_complex_diag_matrix::float_complex_diag_matrix_value (bool) const
+{
+  return FloatComplexDiagMatrix (matrix);
+}
+
+octave_value
+octave_complex_diag_matrix::abs (void) const
+{
+  return matrix.abs ();
+}
+
+octave_value
+octave_complex_diag_matrix::real (void) const
+{
+  return ::real (matrix);
+}
+
+octave_value
+octave_complex_diag_matrix::conj (void) const
+{
+  return ::conj (matrix);
+}
+
+octave_value
+octave_complex_diag_matrix::imag (void) const
+{
+  return ::imag (matrix);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-cx-diag.h	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,87 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_complex_diag_matrix_h)
+#define octave_complex_diag_matrix_h 1
+
+#include "ov-base.h"
+#include "ov-base-diag.h"
+#include "ov-cx-mat.h"
+#include "ov-typeinfo.h"
+
+// Real diagonal matrix values.
+
+class
+OCTINTERP_API
+octave_complex_diag_matrix 
+  : public octave_base_diag<ComplexDiagMatrix, ComplexMatrix>
+{
+public:
+
+  octave_complex_diag_matrix (void)
+    : octave_base_diag<ComplexDiagMatrix, ComplexMatrix> () { }
+
+  octave_complex_diag_matrix (const ComplexDiagMatrix& m)
+    : octave_base_diag<ComplexDiagMatrix, ComplexMatrix> (m) { }
+
+  octave_complex_diag_matrix (const octave_complex_diag_matrix& m)
+    : octave_base_diag<ComplexDiagMatrix, ComplexMatrix> (m) { }
+
+  ~octave_complex_diag_matrix (void) { }
+
+  octave_base_value *clone (void) const { return new octave_complex_diag_matrix (*this); }
+  octave_base_value *empty_clone (void) const { return new octave_complex_diag_matrix (); }
+
+  type_conv_info numeric_conversion_function (void) const;
+
+  type_conv_info numeric_demotion_function (void) const;
+
+  octave_base_value *try_narrowing_conversion (void);
+
+  bool is_complex_matrix (void) const { return true; }
+
+  bool is_complex_type (void) const { return true; }
+
+  bool is_double_type (void) const { return true; }
+
+  bool is_float_type (void) const { return true; }
+
+  DiagMatrix diag_matrix_value (bool = false) const;
+
+  FloatDiagMatrix float_diag_matrix_value (bool = false) const;
+
+  ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;
+
+  FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;
+
+  octave_value abs (void) const;
+  octave_value conj (void) const;
+  octave_value imag (void) const;
+  octave_value real (void) const;
+
+private:
+  DECLARE_OCTAVE_ALLOCATOR
+
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+#endif
--- a/src/ov-cx-mat.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-cx-mat.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -308,6 +308,19 @@
   return SparseComplexMatrix (matrix.matrix_value ());
 }
 
+octave_value
+octave_complex_matrix::diag (octave_idx_type k) const
+{
+  octave_value retval;
+  if (k == 0 && matrix.ndims () == 2 
+      && (matrix.rows () == 1 || matrix.columns () == 1))
+    retval = ComplexDiagMatrix (DiagArray2<Complex> (matrix));
+  else
+    retval = octave_base_matrix<ComplexNDArray>::diag (k);
+
+  return retval;
+}
+
 bool 
 octave_complex_matrix::save_ascii (std::ostream& os)
 {
--- a/src/ov-cx-mat.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-cx-mat.h	Wed Dec 03 13:32:57 2008 +0100
@@ -136,6 +136,8 @@
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
+  octave_value diag (octave_idx_type k = 0) const;
+
   void increment (void) { matrix += Complex (1.0); }
 
   void decrement (void) { matrix -= Complex (1.0); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-flt-cx-diag.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,141 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-flt-cx-diag.h"
+#include "ov-base-diag.cc"
+#include "ov-flt-re-diag.h"
+#include "ov-flt-complex.h"
+#include "ov-flt-cx-mat.h"
+
+template class octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix>;
+
+DEFINE_OCTAVE_ALLOCATOR (octave_float_complex_diag_matrix);
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_complex_diag_matrix, 
+                                     "float complex diagonal matrix", "single");
+
+static octave_base_value *
+default_numeric_conversion_function (const octave_base_value& a)
+{
+  CAST_CONV_ARG (const octave_float_complex_diag_matrix&);
+
+  return new octave_float_complex_matrix (v.float_complex_matrix_value ());
+}
+
+octave_base_value::type_conv_info
+octave_float_complex_diag_matrix::numeric_conversion_function (void) const
+{
+  return octave_base_value::type_conv_info (default_numeric_conversion_function,
+                                            octave_float_complex_matrix::static_type_id ());
+}
+
+octave_base_value *
+octave_float_complex_diag_matrix::try_narrowing_conversion (void)
+{
+  octave_base_value *retval = 0;
+
+  if (matrix.nelem () == 1)
+    {
+      // FIXME: the proxy mechanism of DiagArray2 causes problems here.
+      retval = new octave_float_complex (FloatComplex (matrix (0, 0)));
+      octave_base_value *rv2 = retval->try_narrowing_conversion ();
+      if (rv2)
+        {
+          delete retval;
+          retval = rv2;
+        }
+    }
+  else if (matrix.all_elements_are_real ())
+    {
+      return new octave_float_diag_matrix (::real (matrix));
+    }
+
+  return retval;
+}
+
+DiagMatrix
+octave_float_complex_diag_matrix::diag_matrix_value (bool force_conversion) const
+{
+  DiagMatrix retval;
+
+  if (! force_conversion)
+    gripe_implicit_conversion ("Octave:imag-to-real",
+			       type_name (), "real matrix");
+
+  retval = ::real (matrix);
+
+  return retval;
+}
+
+FloatDiagMatrix
+octave_float_complex_diag_matrix::float_diag_matrix_value (bool force_conversion) const
+{
+  DiagMatrix retval;
+
+  if (! force_conversion)
+    gripe_implicit_conversion ("Octave:imag-to-real",
+			       type_name (), "real matrix");
+
+  retval = ::real (matrix);
+
+  return retval;
+}
+
+ComplexDiagMatrix
+octave_float_complex_diag_matrix::complex_diag_matrix_value (bool) const
+{
+  return ComplexDiagMatrix (matrix);
+}
+
+FloatComplexDiagMatrix
+octave_float_complex_diag_matrix::float_complex_diag_matrix_value (bool) const
+{
+  return matrix;
+}
+
+octave_value
+octave_float_complex_diag_matrix::abs (void) const
+{
+  return matrix.abs ();
+}
+
+octave_value
+octave_float_complex_diag_matrix::real (void) const
+{
+  return ::real (matrix);
+}
+
+octave_value
+octave_float_complex_diag_matrix::conj (void) const
+{
+  return ::conj (matrix);
+}
+
+octave_value
+octave_float_complex_diag_matrix::imag (void) const
+{
+  return ::imag (matrix);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-flt-cx-diag.h	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,91 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_float_complex_diag_matrix_h)
+#define octave_float_complex_diag_matrix_h 1
+
+#include "ov-base.h"
+#include "ov-base-diag.h"
+#include "ov-flt-cx-mat.h"
+#include "ov-typeinfo.h"
+
+// Real diagonal matrix values.
+
+class
+OCTINTERP_API
+octave_float_complex_diag_matrix 
+  : public octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix>
+{
+public:
+
+  octave_float_complex_diag_matrix (void)
+    : octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix> () { }
+
+  octave_float_complex_diag_matrix (const FloatComplexDiagMatrix& m)
+    : octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix> (m) { }
+
+  octave_float_complex_diag_matrix (const octave_float_complex_diag_matrix& m)
+    : octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix> (m) { }
+
+  ~octave_float_complex_diag_matrix (void) { }
+
+  octave_base_value *clone (void) const { return new octave_float_complex_diag_matrix (*this); }
+  octave_base_value *empty_clone (void) const { return new octave_float_complex_diag_matrix (); }
+
+  type_conv_info numeric_conversion_function (void) const;
+
+  octave_base_value *try_narrowing_conversion (void);
+
+  bool is_complex_matrix (void) const { return true; }
+
+  bool is_complex_type (void) const { return true; }
+
+  bool is_double_type (void) const { return true; }
+
+  bool is_float_type (void) const { return true; }
+
+  DiagMatrix diag_matrix_value (bool = false) const;
+
+  FloatDiagMatrix float_diag_matrix_value (bool = false) const;
+
+  ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;
+
+  FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;
+
+  octave_value abs (void) const;
+  octave_value conj (void) const;
+  octave_value imag (void) const;
+  octave_value real (void) const;
+
+private:
+  DECLARE_OCTAVE_ALLOCATOR
+
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/src/ov-flt-cx-mat.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-flt-cx-mat.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -297,6 +297,19 @@
   return SparseComplexMatrix (matrix.matrix_value ());
 }
 
+octave_value
+octave_float_complex_matrix::diag (octave_idx_type k) const
+{
+  octave_value retval;
+  if (k == 0 && matrix.ndims () == 2 
+      && (matrix.rows () == 1 || matrix.columns () == 1))
+    retval = FloatComplexDiagMatrix (DiagArray2<FloatComplex> (matrix));
+  else
+    retval = octave_base_matrix<FloatComplexNDArray>::diag (k);
+
+  return retval;
+}
+
 bool 
 octave_float_complex_matrix::save_ascii (std::ostream& os)
 {
--- a/src/ov-flt-cx-mat.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-flt-cx-mat.h	Wed Dec 03 13:32:57 2008 +0100
@@ -134,6 +134,8 @@
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
+  octave_value diag (octave_idx_type k = 0) const;
+
   void increment (void) { matrix += FloatComplex (1.0); }
 
   void decrement (void) { matrix -= FloatComplex (1.0); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-flt-re-diag.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,112 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-flt-re-diag.h"
+#include "ov-base-diag.cc"
+#include "ov-float.h"
+#include "ov-flt-re-mat.h"
+
+template class octave_base_diag<FloatDiagMatrix, FloatMatrix>;
+
+DEFINE_OCTAVE_ALLOCATOR (octave_float_diag_matrix);
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_diag_matrix, 
+                                     "float diagonal matrix", "single");
+
+static octave_base_value *
+default_numeric_conversion_function (const octave_base_value& a)
+{
+  CAST_CONV_ARG (const octave_float_diag_matrix&);
+
+  return new octave_float_matrix (v.float_matrix_value ());
+}
+
+octave_base_value::type_conv_info
+octave_float_diag_matrix::numeric_conversion_function (void) const
+{
+  return octave_base_value::type_conv_info (default_numeric_conversion_function,
+                                            octave_float_matrix::static_type_id ());
+}
+
+octave_base_value *
+octave_float_diag_matrix::try_narrowing_conversion (void)
+{
+  octave_base_value *retval = 0;
+
+  // FIXME: the proxy mechanism of DiagArray2 causes problems here.
+  if (matrix.nelem () == 1)
+    retval = new octave_float_scalar (float (matrix (0, 0)));
+
+  return retval;
+}
+
+DiagMatrix
+octave_float_diag_matrix::diag_matrix_value (bool) const
+{
+  return DiagMatrix (matrix);
+}
+
+FloatDiagMatrix
+octave_float_diag_matrix::float_diag_matrix_value (bool) const
+{
+  return matrix;
+}
+
+ComplexDiagMatrix
+octave_float_diag_matrix::complex_diag_matrix_value (bool) const
+{
+  return ComplexDiagMatrix (matrix);
+}
+
+FloatComplexDiagMatrix
+octave_float_diag_matrix::float_complex_diag_matrix_value (bool) const
+{
+  return FloatComplexDiagMatrix (matrix);
+}
+
+octave_value
+octave_float_diag_matrix::abs (void) const
+{
+  return matrix.abs ();
+}
+
+octave_value
+octave_float_diag_matrix::real (void) const
+{
+  return matrix;
+}
+
+octave_value
+octave_float_diag_matrix::conj (void) const
+{
+  return matrix;
+}
+
+octave_value
+octave_float_diag_matrix::imag (void) const
+{
+  return DiagMatrix (matrix.rows (), matrix.cols ());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-flt-re-diag.h	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,85 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_float_diag_matrix_h)
+#define octave_float_diag_matrix_h 1
+
+#include "ov-base.h"
+#include "ov-base-diag.h"
+#include "ov-flt-re-mat.h"
+#include "ov-typeinfo.h"
+
+// Real diagonal matrix values.
+
+class
+OCTINTERP_API
+octave_float_diag_matrix 
+  : public octave_base_diag<FloatDiagMatrix, FloatMatrix>
+{
+public:
+
+  octave_float_diag_matrix (void)
+    : octave_base_diag<FloatDiagMatrix, FloatMatrix> () { }
+
+  octave_float_diag_matrix (const FloatDiagMatrix& m)
+    : octave_base_diag<FloatDiagMatrix, FloatMatrix> (m) { }
+
+  octave_float_diag_matrix (const octave_float_diag_matrix& m)
+    : octave_base_diag<FloatDiagMatrix, FloatMatrix> (m) { }
+
+  ~octave_float_diag_matrix (void) { }
+
+  octave_base_value *clone (void) const { return new octave_float_diag_matrix (*this); }
+  octave_base_value *empty_clone (void) const { return new octave_float_diag_matrix (); }
+
+  type_conv_info numeric_conversion_function (void) const;
+
+  octave_base_value *try_narrowing_conversion (void);
+
+  bool is_real_matrix (void) const { return true; }
+
+  bool is_real_type (void) const { return true; }
+
+  bool is_single_type (void) const { return true; }
+
+  bool is_float_type (void) const { return true; }
+
+  DiagMatrix diag_matrix_value (bool = false) const;
+
+  FloatDiagMatrix float_diag_matrix_value (bool = false) const;
+
+  ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;
+
+  FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;
+
+  octave_value abs (void) const;
+  octave_value conj (void) const;
+  octave_value imag (void) const;
+  octave_value real (void) const;
+
+private:
+  DECLARE_OCTAVE_ALLOCATOR
+
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+#endif
--- a/src/ov-flt-re-mat.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-flt-re-mat.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -255,6 +255,19 @@
 }
 
 octave_value
+octave_float_matrix::diag (octave_idx_type k) const
+{
+  octave_value retval;
+  if (k == 0 && matrix.ndims () == 2 
+      && (matrix.rows () == 1 || matrix.columns () == 1))
+    retval = FloatDiagMatrix (DiagArray2<float> (matrix));
+  else
+    retval = octave_base_matrix<FloatNDArray>::diag (k);
+
+  return retval;
+}
+
+octave_value
 octave_float_matrix::convert_to_str_internal (bool, bool, char type) const
 {
   octave_value retval;
--- a/src/ov-flt-re-mat.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-flt-re-mat.h	Wed Dec 03 13:32:57 2008 +0100
@@ -162,6 +162,8 @@
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
+  octave_value diag (octave_idx_type k = 0) const;
+
   void increment (void) { matrix += 1.0; }
 
   void decrement (void) { matrix -= 1.0; }
--- a/src/ov-range.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-range.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -188,6 +188,15 @@
   return m.any (dim);
 }
 
+octave_value 
+octave_range::diag (octave_idx_type k) const
+{ 
+  return (k == 0
+          ? octave_value (DiagMatrix (DiagArray2<double> (range.matrix_value ())))
+          : octave_value (range.diag (k))); 
+}
+
+
 bool
 octave_range::is_true (void) const
 {
--- a/src/ov-range.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-range.h	Wed Dec 03 13:32:57 2008 +0100
@@ -129,8 +129,7 @@
 
   octave_value any (int dim = 0) const;
 
-  octave_value diag (octave_idx_type k = 0) const
-    { return octave_value (range.diag (k)); }
+  octave_value diag (octave_idx_type k = 0) const;
 
   octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
     { return range.sort (dim, mode); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-re-diag.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,127 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-re-diag.h"
+#include "ov-flt-re-diag.h"
+#include "ov-base-diag.cc"
+#include "ov-scalar.h"
+#include "ov-re-mat.h"
+
+template class octave_base_diag<DiagMatrix, Matrix>;
+
+DEFINE_OCTAVE_ALLOCATOR (octave_diag_matrix);
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_diag_matrix, "diagonal matrix", "double");
+
+static octave_base_value *
+default_numeric_conversion_function (const octave_base_value& a)
+{
+  CAST_CONV_ARG (const octave_diag_matrix&);
+
+  return new octave_matrix (v.matrix_value ());
+}
+
+octave_base_value::type_conv_info
+octave_diag_matrix::numeric_conversion_function (void) const
+{
+  return octave_base_value::type_conv_info (default_numeric_conversion_function,
+                                            octave_matrix::static_type_id ());
+}
+
+static octave_base_value *
+default_numeric_demotion_function (const octave_base_value& a)
+{
+  CAST_CONV_ARG (const octave_diag_matrix&);
+
+  return new octave_float_diag_matrix (v.float_diag_matrix_value ());
+}
+
+octave_base_value::type_conv_info
+octave_diag_matrix::numeric_demotion_function (void) const
+{
+  return octave_base_value::type_conv_info (default_numeric_demotion_function,
+                                            octave_float_diag_matrix::static_type_id ());
+}
+
+octave_base_value *
+octave_diag_matrix::try_narrowing_conversion (void)
+{
+  octave_base_value *retval = 0;
+
+  // FIXME: the proxy mechanism of DiagArray2 causes problems here.
+  if (matrix.nelem () == 1)
+    retval = new octave_scalar (double (matrix (0, 0)));
+
+  return retval;
+}
+
+DiagMatrix
+octave_diag_matrix::diag_matrix_value (bool) const
+{
+  return matrix;
+}
+
+FloatDiagMatrix
+octave_diag_matrix::float_diag_matrix_value (bool) const
+{
+  return FloatDiagMatrix (matrix);
+}
+
+ComplexDiagMatrix
+octave_diag_matrix::complex_diag_matrix_value (bool) const
+{
+  return ComplexDiagMatrix (matrix);
+}
+
+FloatComplexDiagMatrix
+octave_diag_matrix::float_complex_diag_matrix_value (bool) const
+{
+  return FloatComplexDiagMatrix (matrix);
+}
+
+octave_value
+octave_diag_matrix::abs (void) const
+{
+  return matrix.abs ();
+}
+
+octave_value
+octave_diag_matrix::real (void) const
+{
+  return matrix;
+}
+
+octave_value
+octave_diag_matrix::conj (void) const
+{
+  return matrix;
+}
+
+octave_value
+octave_diag_matrix::imag (void) const
+{
+  return DiagMatrix (matrix.rows (), matrix.cols ());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-re-diag.h	Wed Dec 03 13:32:57 2008 +0100
@@ -0,0 +1,87 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_diag_matrix_h)
+#define octave_diag_matrix_h 1
+
+#include "ov-base.h"
+#include "ov-base-diag.h"
+#include "ov-re-mat.h"
+#include "ov-typeinfo.h"
+
+// Real diagonal matrix values.
+
+class
+OCTINTERP_API
+octave_diag_matrix 
+  : public octave_base_diag<DiagMatrix, Matrix>
+{
+public:
+
+  octave_diag_matrix (void)
+    : octave_base_diag<DiagMatrix, Matrix> () { }
+
+  octave_diag_matrix (const DiagMatrix& m)
+    : octave_base_diag<DiagMatrix, Matrix> (m) { }
+
+  octave_diag_matrix (const octave_diag_matrix& m)
+    : octave_base_diag<DiagMatrix, Matrix> (m) { }
+
+  ~octave_diag_matrix (void) { }
+
+  octave_base_value *clone (void) const { return new octave_diag_matrix (*this); }
+  octave_base_value *empty_clone (void) const { return new octave_diag_matrix (); }
+
+  type_conv_info numeric_conversion_function (void) const;
+
+  type_conv_info numeric_demotion_function (void) const;
+
+  octave_base_value *try_narrowing_conversion (void);
+
+  bool is_real_matrix (void) const { return true; }
+
+  bool is_real_type (void) const { return true; }
+
+  bool is_double_type (void) const { return true; }
+
+  bool is_float_type (void) const { return true; }
+
+  DiagMatrix diag_matrix_value (bool = false) const;
+
+  FloatDiagMatrix float_diag_matrix_value (bool = false) const;
+
+  ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;
+
+  FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;
+
+  octave_value abs (void) const;
+  octave_value conj (void) const;
+  octave_value imag (void) const;
+  octave_value real (void) const;
+
+private:
+  DECLARE_OCTAVE_ALLOCATOR
+
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+#endif
--- a/src/ov-re-mat.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-re-mat.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -262,6 +262,19 @@
 }
 
 octave_value
+octave_matrix::diag (octave_idx_type k) const
+{
+  octave_value retval;
+  if (k == 0 && matrix.ndims () == 2 
+      && (matrix.rows () == 1 || matrix.columns () == 1))
+    retval = DiagMatrix (DiagArray2<double> (matrix));
+  else
+    retval = octave_base_matrix<NDArray>::diag (k);
+
+  return retval;
+}
+
+octave_value
 octave_matrix::convert_to_str_internal (bool, bool, char type) const
 {
   octave_value retval;
--- a/src/ov-re-mat.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov-re-mat.h	Wed Dec 03 13:32:57 2008 +0100
@@ -161,6 +161,8 @@
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
+  octave_value diag (octave_idx_type k = 0) const;
+
   void increment (void) { matrix += 1.0; }
 
   void decrement (void) { matrix -= 1.0; }
--- a/src/ov.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -40,6 +40,8 @@
 #include "ov-float.h"
 #include "ov-re-mat.h"
 #include "ov-flt-re-mat.h"
+#include "ov-re-diag.h"
+#include "ov-flt-re-diag.h"
 #include "ov-bool-sparse.h"
 #include "ov-cx-sparse.h"
 #include "ov-re-sparse.h"
@@ -55,6 +57,8 @@
 #include "ov-flt-complex.h"
 #include "ov-cx-mat.h"
 #include "ov-flt-cx-mat.h"
+#include "ov-cx-diag.h"
+#include "ov-flt-cx-diag.h"
 #include "ov-ch-mat.h"
 #include "ov-str-mat.h"
 #include "ov-range.h"
@@ -568,13 +572,13 @@
 }
 
 octave_value::octave_value (const DiagMatrix& d)
-  : rep (new octave_matrix (d))
+  : rep (new octave_diag_matrix (d))
 {
   maybe_mutate ();
 }
 
 octave_value::octave_value (const FloatDiagMatrix& d)
-  : rep (new octave_float_matrix (d))
+  : rep (new octave_float_diag_matrix (d))
 {
   maybe_mutate ();
 }
@@ -652,13 +656,13 @@
 }
 
 octave_value::octave_value (const ComplexDiagMatrix& d)
-  : rep (new octave_complex_matrix (d))
+  : rep (new octave_complex_diag_matrix (d))
 {
   maybe_mutate ();
 }
 
 octave_value::octave_value (const FloatComplexDiagMatrix& d)
-  : rep (new octave_float_complex_matrix (d))
+  : rep (new octave_float_complex_diag_matrix (d))
 {
   maybe_mutate ();
 }
@@ -2319,7 +2323,9 @@
   octave_scalar::register_type ();
   octave_complex::register_type ();
   octave_matrix::register_type ();
+  octave_diag_matrix::register_type ();
   octave_complex_matrix::register_type ();
+  octave_complex_diag_matrix::register_type ();
   octave_range::register_type ();
   octave_bool::register_type ();
   octave_bool_matrix::register_type ();
@@ -2358,7 +2364,9 @@
   octave_float_scalar::register_type ();
   octave_float_complex::register_type ();
   octave_float_matrix::register_type ();
+  octave_float_diag_matrix::register_type ();
   octave_float_complex_matrix::register_type ();
+  octave_float_complex_diag_matrix::register_type ();
   octave_null_matrix::register_type ();
   octave_null_str::register_type ();
   octave_null_sq_str::register_type ();
--- a/src/ov.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/ov.h	Wed Dec 03 13:32:57 2008 +0100
@@ -462,6 +462,9 @@
   bool is_char_matrix (void) const
     { return rep->is_char_matrix (); }
 
+  bool is_diag_matrix (void) const
+    { return rep->is_diag_matrix (); }
+
   bool is_string (void) const
     { return rep->is_string (); }
 
--- a/src/xdiv.cc	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/xdiv.cc	Wed Dec 03 13:32:57 2008 +0100
@@ -2,6 +2,7 @@
 
 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2003,
               2005, 2006, 2007 John W. Eaton
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
 
 This file is part of Octave.
 
@@ -37,6 +38,10 @@
 #include "fCNDArray.h"
 #include "fNDArray.h"
 #include "oct-cmplx.h"
+#include "dDiagMatrix.h"
+#include "fDiagMatrix.h"
+#include "CDiagMatrix.h"
+#include "fCDiagMatrix.h"
 #include "quit.h"
 
 #include "error.h"
@@ -722,6 +727,299 @@
   return a.solve (typ, b, info, rcond, solve_singularity_warning);
 }
 
+// Diagonal matrix division.
+
+template <class MT, class DMT>
+MT
+mdm_div_impl (const MT& a, const DMT& d)
+{
+  if (! mx_div_conform (a, d))
+    return MT ();
+
+  octave_idx_type m = a.rows (), n = d.rows (), k = d.cols ();
+  MT x (m, n);
+  const typename DMT::element_type zero = typename DMT::element_type ();
+
+  for (octave_idx_type j = 0; j < n; j++)
+    {
+      if (j < k && d(j, j) != zero)
+        {
+          for (octave_idx_type i = 0; i < m; i++)
+            x(i, j) = a(i, j) / d(j, j);
+        }
+      else
+        {
+          for (octave_idx_type i = 0; i < m; i++)
+            x(i, j) = zero;
+        }
+    }
+
+  return x;
+}
+
+// Right division functions.
+//
+//       op2 / op1:   dm  cdm
+//            +--   +---+----+
+//   matrix         | 1 |    |
+//                  +---+----+
+//   complex_matrix | 2 |  3 |
+//                  +---+----+
+
+// -*- 1 -*-
+Matrix
+xdiv (const Matrix& a, const DiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// -*- 2 -*-
+ComplexMatrix
+xdiv (const ComplexMatrix& a, const DiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// -*- 3 -*-
+ComplexMatrix
+xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// Right division functions, float type.
+//
+//       op2 / op1:   dm  cdm
+//            +--   +---+----+
+//   matrix         | 1 |    |
+//                  +---+----+
+//   complex_matrix | 2 |  3 |
+//                  +---+----+
+
+// -*- 1 -*-
+FloatMatrix
+xdiv (const FloatMatrix& a, const FloatDiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// -*- 2 -*-
+FloatComplexMatrix
+xdiv (const FloatComplexMatrix& a, const FloatDiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// -*- 3 -*-
+FloatComplexMatrix
+xdiv (const FloatComplexMatrix& a, const FloatComplexDiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+template <class MT, class DMT>
+MT
+dmm_leftdiv_impl (const DMT& d, const MT& a)
+{
+  if (! mx_leftdiv_conform (d, a))
+    return MT ();
+
+  octave_idx_type m = d.cols (), n = a.cols (), k = d.rows ();
+  octave_idx_type mk = m < k ? m : k;
+  MT x (m, n);
+  const typename DMT::element_type zero = typename DMT::element_type ();
+
+  for (octave_idx_type j = 0; j < n; j++)
+    {
+      for (octave_idx_type i = 0; i < mk; i++)
+        x(i, j) = d(i, i) != zero ? a(i, j) / d(i, i) : 0;
+      for (octave_idx_type i = mk; i < m; i++)
+        x(i, j) = zero;
+    }
+
+  return x;
+}
+
+// Left division functions.
+//
+//       op2 \ op1:         m   cm
+//                        +---+----+
+//   diag_matrix          | 1 |  2 |
+//                        +---+----+
+//   complex_diag_matrix  |   |  3 |
+//                        +---+----+
+
+// -*- 1 -*-
+Matrix
+xleftdiv (const DiagMatrix& a, const Matrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// -*- 2 -*-
+ComplexMatrix
+xleftdiv (const DiagMatrix& a, const ComplexMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// -*- 3 -*-
+ComplexMatrix
+xleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// Left division functions, float type.
+//
+//       op2 \ op1:         m   cm
+//                        +---+----+
+//   diag_matrix          | 1 |  2 |
+//                        +---+----+
+//   complex_diag_matrix  |   |  3 |
+//                        +---+----+
+
+// -*- 1 -*-
+FloatMatrix
+xleftdiv (const FloatDiagMatrix& a, const FloatMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// -*- 2 -*-
+FloatComplexMatrix
+xleftdiv (const FloatDiagMatrix& a, const FloatComplexMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// -*- 3 -*-
+FloatComplexMatrix
+xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// Diagonal by diagonal matrix division.
+
+template <class MT, class DMT>
+MT
+dmdm_div_impl (const MT& a, const DMT& d)
+{
+  if (! mx_div_conform (a, d))
+    return MT ();
+
+  octave_idx_type m = a.rows (), n = d.rows (), k = d.cols ();
+  octave_idx_type mn = m < n ? m : n;
+  MT x (m, n);
+  const typename DMT::element_type zero = typename DMT::element_type ();
+
+  for (octave_idx_type j = 0; j < mn; j++)
+    {
+      if (j < k && d(j, j) != zero)
+        x(j, j) = a(j, j) / d(j, j);
+      else
+        x(j, j) = zero;
+    }
+
+  return x;
+}
+
+// Right division functions.
+//
+//       op2 / op1:        dm  cdm
+//            +--        +---+----+
+//   diag_matrix         | 1 |    |
+//                       +---+----+
+//   complex_diag_matrix | 2 |  3 |
+//                       +---+----+
+
+// -*- 1 -*-
+DiagMatrix
+xdiv (const DiagMatrix& a, const DiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// -*- 2 -*-
+ComplexDiagMatrix
+xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// -*- 3 -*-
+ComplexDiagMatrix
+xdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// Right division functions, float type.
+//
+//       op2 / op1:        dm  cdm
+//            +--        +---+----+
+//   diag_matrix         | 1 |    |
+//                       +---+----+
+//   complex_diag_matrix | 2 |  3 |
+//                       +---+----+
+
+// -*- 1 -*-
+FloatDiagMatrix
+xdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// -*- 2 -*-
+FloatComplexDiagMatrix
+xdiv (const FloatComplexDiagMatrix& a, const FloatDiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// -*- 3 -*-
+FloatComplexDiagMatrix
+xdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+template <class MT, class DMT>
+MT
+dmdm_leftdiv_impl (const DMT& d, const MT& a)
+{
+  if (! mx_leftdiv_conform (d, a))
+    return MT ();
+
+  octave_idx_type m = d.cols (), n = a.cols (), k = d.rows ();
+  octave_idx_type mn = m < n ? m : n;
+  MT x (m, n);
+  const typename DMT::element_type zero = typename DMT::element_type ();
+
+  for (octave_idx_type j = 0; j < mn; j++)
+    {
+      if (j < k && d(j, j) != zero)
+        x(j, j) = a(j, j) / d(j, j);
+      else
+        x(j, j) = zero;
+    }
+
+  return x;
+}
+
+// Left division functions.
+//
+//       op2 \ op1:         dm  cdm
+//                        +---+----+
+//   diag_matrix          | 1 |  2 |
+//                        +---+----+
+//   complex_diag_matrix  |   |  3 |
+//                        +---+----+
+
+// -*- 1 -*-
+DiagMatrix
+xleftdiv (const DiagMatrix& a, const DiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// -*- 2 -*-
+ComplexDiagMatrix
+xleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// -*- 3 -*-
+ComplexDiagMatrix
+xleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// Left division functions, float type.
+//
+//       op2 \ op1:         dm  cdm
+//                        +---+----+
+//   diag_matrix          | 1 |  2 |
+//                        +---+----+
+//   complex_diag_matrix  |   |  3 |
+//                        +---+----+
+
+// -*- 1 -*-
+FloatDiagMatrix
+xleftdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// -*- 2 -*-
+FloatComplexDiagMatrix
+xleftdiv (const FloatDiagMatrix& a, const FloatComplexDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// -*- 3 -*-
+FloatComplexDiagMatrix
+xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/xdiv.h	Wed Dec 03 20:57:27 2008 -0500
+++ b/src/xdiv.h	Wed Dec 03 13:32:57 2008 +0100
@@ -2,6 +2,7 @@
 
 Copyright (C) 1993, 1994, 1995, 1996, 1997, 2003, 2005, 2006, 2007
               John W. Eaton
+Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
 
 This file is part of Octave.
 
@@ -92,6 +93,55 @@
 			       MatrixType &typ);
 
 
+class DiagMatrix;
+class FloatDiagMatrix;
+class ComplexDiagMatrix;
+class FloatComplexDiagMatrix;
+
+extern Matrix xdiv (const Matrix& a, const DiagMatrix& b);
+extern ComplexMatrix xdiv (const ComplexMatrix& a, const DiagMatrix& b);
+extern ComplexMatrix xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b);
+
+extern DiagMatrix xdiv (const DiagMatrix& a, const DiagMatrix& b);
+extern ComplexDiagMatrix xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b);
+extern ComplexDiagMatrix xdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b);
+
+extern FloatMatrix xdiv (const FloatMatrix& a, const FloatDiagMatrix& b);
+extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a, 
+                                const FloatDiagMatrix& b); 
+extern FloatComplexMatrix xdiv (const FloatMatrix& a, 
+                                const FloatComplexDiagMatrix& b); 
+extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a, 
+                                const FloatComplexDiagMatrix& b);
+
+extern FloatDiagMatrix xdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b);
+extern FloatComplexDiagMatrix xdiv (const FloatComplexDiagMatrix& a, 
+                                    const FloatDiagMatrix& b);
+extern FloatComplexDiagMatrix xdiv (const FloatComplexDiagMatrix& a, 
+                                    const FloatComplexDiagMatrix& b);
+
+extern Matrix xleftdiv (const DiagMatrix& a, const Matrix& b);
+extern ComplexMatrix xleftdiv (const DiagMatrix& a, const ComplexMatrix& b);
+extern ComplexMatrix xleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b);
+
+extern DiagMatrix xleftdiv (const DiagMatrix& a, const DiagMatrix& b);
+extern ComplexDiagMatrix xleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b);
+extern ComplexDiagMatrix xleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b);
+
+extern FloatMatrix xleftdiv (const FloatDiagMatrix& a, 
+                             const FloatMatrix& b);
+extern FloatComplexMatrix xleftdiv (const FloatDiagMatrix& a, 
+                                    const FloatComplexMatrix& b);
+extern FloatComplexMatrix xleftdiv (const FloatComplexDiagMatrix& a, 
+                                    const FloatComplexMatrix& b);
+
+extern FloatDiagMatrix xleftdiv (const FloatDiagMatrix& a, 
+                                 const FloatDiagMatrix& b);
+extern FloatComplexDiagMatrix xleftdiv (const FloatDiagMatrix& a, 
+                                        const FloatComplexDiagMatrix& b);
+extern FloatComplexDiagMatrix xleftdiv (const FloatComplexDiagMatrix& a, 
+                                        const FloatComplexDiagMatrix& b);
+
 #endif
 
 /*
--- a/test/ChangeLog	Wed Dec 03 20:57:27 2008 -0500
+++ b/test/ChangeLog	Wed Dec 03 13:32:57 2008 +0100
@@ -1,3 +1,7 @@
+2008-12-02  Jaroslav Hajek  <highegg@gmail.com>
+
+	* build_sparse_tests.sh: Fix test.
+
 2008-10-28  Jaroslav Hajek <highegg@gmail.com>
 
 	* test_logical-wfi-f.m: Fix error messages.
--- a/test/build_sparse_tests.sh	Wed Dec 03 20:57:27 2008 -0500
+++ b/test/build_sparse_tests.sh	Wed Dec 03 13:32:57 2008 +0100
@@ -216,7 +216,7 @@
 %!test
 %! wdbz = warning ("query", "Octave:divide-by-zero");
 %! warning ("off", "Octave:divide-by-zero");
-%! assert(full(sparse(eye(3))/0),eye(3)/0);
+%! assert(full(sparse(eye(3))/0),full(eye(3))/0);
 %! warning (wdbz.state, "Octave:divide-by-zero");
 
 EOF