changeset 9713:7918eb15040c

refactor the QR classes onto a templated base
author Jaroslav Hajek <highegg@gmail.com>
date Mon, 12 Oct 2009 10:42:49 +0200
parents 25e1e368618c
children 0407883e1a33
files liboctave/ChangeLog liboctave/CmplxQR.cc liboctave/CmplxQR.h liboctave/CmplxQRP.cc liboctave/CmplxQRP.h liboctave/base-qr.cc liboctave/base-qr.h liboctave/dbleQR.cc liboctave/dbleQR.h liboctave/dbleQRP.cc liboctave/dbleQRP.h liboctave/fCmplxQR.cc liboctave/fCmplxQR.h liboctave/fCmplxQRP.cc liboctave/fCmplxQRP.h liboctave/floatQR.cc liboctave/floatQR.h liboctave/floatQRP.cc liboctave/floatQRP.h
diffstat 19 files changed, 259 insertions(+), 288 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/ChangeLog	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/ChangeLog	Mon Oct 12 10:42:49 2009 +0200
@@ -1,3 +1,24 @@
+2009-10-12  Jaroslav Hajek  <highegg@gmail.com>
+
+	* base-qr.h: New source.
+	* base-qr.cc: New source.
+	* dbleQR.h (QR): Rebase on base_qr<Matrix>.
+	* dbleQR.cc: Ditto.
+	* floatQR.h (QR): Rebase on base_qr<FloatMatrix>.
+	* floatQR.cc: Ditto.
+	* CmplxQR.h (QR): Rebase on base_qr<ComplexMatrix>.
+	* CmplxQR.cc: Ditto.
+	* fCmplxQR.h (QR): Rebase on base_qr<FloatComplexMatrix>.
+	* fCmplxQR.cc: Ditto.
+	* dbleQRP.h (QR): Update.
+	* dbleQRP.cc: Ditto.
+	* floatQRP.h (QR): Update.
+	* floatQRP.cc: Ditto.
+	* CmplxQRP.h (QR): Update.
+	* CmplxQRP.cc: Ditto.
+	* fCmplxQRP.h (QR): Update.
+	* fCmplxQRP.cc: Ditto.
+
 2009-10-08  Jaroslav Hajek  <highegg@gmail.com>
 
 	* PermMatrix.cc (PermMatrix::eye): New method.
--- a/liboctave/CmplxQR.cc	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/CmplxQR.cc	Mon Oct 12 10:42:49 2009 +0200
@@ -34,6 +34,10 @@
 #include "idx-vector.h"
 #include "oct-locbuf.h"
 
+#include "base-qr.cc"
+
+template class base_qr<ComplexMatrix>;
+
 extern "C"
 {
   F77_RET_T
@@ -82,14 +86,13 @@
 #endif
 }
 
-ComplexQR::ComplexQR (const ComplexMatrix& a, QR::type qr_type)
-  : q (), r ()
+ComplexQR::ComplexQR (const ComplexMatrix& a, qr_type_t qr_type)
 {
   init (a, qr_type);
 }
 
 void
-ComplexQR::init (const ComplexMatrix& a, QR::type qr_type)
+ComplexQR::init (const ComplexMatrix& a, qr_type_t qr_type)
 {
   octave_idx_type m = a.rows ();
   octave_idx_type n = a.cols ();
@@ -100,7 +103,7 @@
   octave_idx_type info = 0;
 
   ComplexMatrix afact = a;
-  if (m > n && qr_type == QR::std)
+  if (m > n && qr_type == qr_type_std)
     afact.resize (m, m);
 
   if (m > 0)
@@ -120,12 +123,12 @@
 }
 
 void ComplexQR::form (octave_idx_type n, ComplexMatrix& afact, 
-                      Complex *tau, QR::type qr_type)
+                      Complex *tau, qr_type_t qr_type)
 {
   octave_idx_type m = afact.rows (), min_mn = std::min (m, n);
   octave_idx_type info;
 
-  if (qr_type == QR::raw)
+  if (qr_type == qr_type_raw)
     {
       for (octave_idx_type j = 0; j < min_mn; j++)
 	{
@@ -143,7 +146,7 @@
         {
           // afact will become q.
           q = afact;
-          octave_idx_type k = qr_type == QR::economy ? n : m;
+          octave_idx_type k = qr_type == qr_type_economy ? n : m;
           r = ComplexMatrix (k, n);
           for (octave_idx_type j = 0; j < n; j++)
             {
@@ -187,32 +190,6 @@
     }
 }
 
-ComplexQR::ComplexQR (const ComplexMatrix& q_arg, const ComplexMatrix& r_arg)
-{
-  octave_idx_type qr = q_arg.rows (), qc = q_arg.columns ();
-  octave_idx_type rr = r_arg.rows (), rc = r_arg.columns ();
-  if (qc == rr && (qr == qc || (qr > qc && rr == rc)))
-    {
-      q = q_arg;
-      r = r_arg;
-    }
-  else
-    (*current_liboctave_error_handler) ("QR dimensions mismatch");
-}
-
-QR::type
-ComplexQR::get_type (void) const
-{
-  QR::type retval;
-  if (!q.is_empty () && q.is_square ())
-    retval = QR::std;
-  else if (q.rows () > q.columns () && r.is_square ())
-    retval = QR::economy;
-  else
-    retval = QR::raw;
-  return retval;
-}
-
 #ifdef HAVE_QRUPDATE
 
 void
--- a/liboctave/CmplxQR.h	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/CmplxQR.h	Mon Oct 12 10:42:49 2009 +0200
@@ -30,42 +30,25 @@
 #include "CMatrix.h"
 #include "CColVector.h"
 #include "CRowVector.h"
-#include "dbleQR.h"
+#include "base-qr.h"
 
 
 class
 OCTAVE_API
-ComplexQR
+ComplexQR : public base_qr<ComplexMatrix>
 {
 public:
 
-  ComplexQR (void) : q (), r () { }
-
-  ComplexQR (const ComplexMatrix&, QR::type = QR::std);
+  ComplexQR (void) : base_qr<ComplexMatrix> () { }
 
-  ComplexQR (const ComplexMatrix& q, const ComplexMatrix& r);
-
-  ComplexQR (const ComplexQR& a) : q (a.q), r (a.r) { }
+  ComplexQR (const ComplexMatrix&, qr_type_t = qr_type_std);
 
-  ComplexQR& operator = (const ComplexQR& a)
-    {
-      if (this != &a)
-	{
-	  q = a.q;
-	  r = a.r;
-	}
-      return *this;
-    }
+  ComplexQR (const ComplexMatrix& qx, const ComplexMatrix& rx) 
+    : base_qr<ComplexMatrix> (qx, rx) { }
 
-  ~ComplexQR (void) { }
-
-  void init (const ComplexMatrix&, QR::type = QR::std);
+  ComplexQR (const ComplexQR& a) : base_qr<ComplexMatrix> (a) { }
 
-  ComplexMatrix Q (void) const { return q; }
-
-  ComplexMatrix R (void) const { return r; }
-
-  QR::type get_type (void) const;
+  void init (const ComplexMatrix&, qr_type_t = qr_type_std);
 
   void update (const ComplexColumnVector& u, const ComplexColumnVector& v);
 
@@ -85,15 +68,10 @@
 
   void shift_cols (octave_idx_type i, octave_idx_type j);
 
-  friend std::ostream&  operator << (std::ostream&, const ComplexQR&);
-
 protected:
 
   void form (octave_idx_type n, ComplexMatrix& afact, 
-             Complex *tau, QR::type qr_type);
-
-  ComplexMatrix q;
-  ComplexMatrix r;
+             Complex *tau, qr_type_t qr_type);
 };
 
 #endif
--- a/liboctave/CmplxQRP.cc	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/CmplxQRP.cc	Mon Oct 12 10:42:49 2009 +0200
@@ -42,16 +42,16 @@
 
 // It would be best to share some of this code with ComplexQR class...
 
-ComplexQRP::ComplexQRP (const ComplexMatrix& a, QR::type qr_type)
+ComplexQRP::ComplexQRP (const ComplexMatrix& a, qr_type_t qr_type)
   : ComplexQR (), p ()
 {
   init (a, qr_type);
 }
 
 void
-ComplexQRP::init (const ComplexMatrix& a, QR::type qr_type)
+ComplexQRP::init (const ComplexMatrix& a, qr_type_t qr_type)
 {
-  assert (qr_type != QR::raw);
+  assert (qr_type != qr_type_raw);
 
   octave_idx_type m = a.rows ();
   octave_idx_type n = a.cols ();
@@ -62,7 +62,7 @@
   octave_idx_type info = 0;
 
   ComplexMatrix afact = a;
-  if (m > n && qr_type == QR::std)
+  if (m > n && qr_type == qr_type_std)
     afact.resize (m, m);
 
   MArray<octave_idx_type> jpvt (n, 0);
--- a/liboctave/CmplxQRP.h	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/CmplxQRP.h	Mon Oct 12 10:42:49 2009 +0200
@@ -38,7 +38,7 @@
 
   ComplexQRP (void) : ComplexQR (), p () { }
 
-  ComplexQRP (const ComplexMatrix&, QR::type = QR::std);
+  ComplexQRP (const ComplexMatrix&, qr_type_t = qr_type_std);
 
   ComplexQRP (const ComplexQRP& a) : ComplexQR (a), p (a.p) { }
 
@@ -54,7 +54,7 @@
 
   ~ComplexQRP (void) { }
 
-  void init (const ComplexMatrix&, QR::type = QR::std);
+  void init (const ComplexMatrix&, qr_type_t = qr_type_std);
 
   PermMatrix P (void) const { return p; }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/base-qr.cc	Mon Oct 12 10:42:49 2009 +0200
@@ -0,0 +1,56 @@
+/*
+
+Copyright (C) 2009 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 "base-qr.h"
+
+template <class qr_type>
+base_qr<qr_type>::base_qr (const qr_type& q_arg, const qr_type& r_arg)
+{
+  octave_idx_type qr = q_arg.rows (), qc = q_arg.columns ();
+  octave_idx_type rr = r_arg.rows (), rc = r_arg.columns ();
+  if (qc == rr && (qr == qc || (qr > qc && rr == rc)))
+    {
+      q = q_arg;
+      r = r_arg;
+    }
+  else
+    (*current_liboctave_error_handler) ("QR dimensions mismatch");
+}
+
+template <class qr_type>
+qr_type_t
+base_qr<qr_type>::get_type (void) const
+{
+  qr_type_t retval;
+  if (!q.is_empty () && q.is_square ())
+    retval = qr_type_std;
+  else if (q.rows () > q.columns () && r.is_square ())
+    retval = qr_type_economy;
+  else
+    retval = qr_type_raw;
+  return retval;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/base-qr.h	Mon Oct 12 10:42:49 2009 +0200
@@ -0,0 +1,77 @@
+/*
+
+Copyright (C) 2009 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_base_qr_h)
+#define octave_base_qr_h 1
+
+#include "MArray.h"
+#include "dColVector.h"
+#include "PermMatrix.h"
+
+enum qr_type_t
+{
+  qr_type_std,
+  qr_type_raw,
+  qr_type_economy
+};
+
+template <class qr_type>
+class
+base_qr
+{
+public:
+
+  typedef typename qr_type::element_type qr_elt_type;
+
+  base_qr (void) { }
+
+  base_qr (const qr_type& q, const qr_type& r);
+
+  base_qr (const base_qr& a) : 
+    q (a.q), r (a.r) { }
+
+  base_qr& operator = (const base_qr& a)
+    {
+      if (this != &a)
+	{
+	  q = a.q;
+	  r = a.r;
+	}
+      return *this;
+    }
+
+  qr_type Q (void) const { return q; }
+
+  qr_type R (void) const { return r; }
+
+  qr_type_t get_type (void) const;
+
+protected:
+
+  qr_type q, r;
+};
+
+#ifndef HAVE_QRUPDATE
+void warn_qrupdate_once (void);
+#endif
+
+#endif
--- a/liboctave/dbleQR.cc	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/dbleQR.cc	Mon Oct 12 10:42:49 2009 +0200
@@ -34,6 +34,10 @@
 #include "idx-vector.h"
 #include "oct-locbuf.h"
 
+#include "base-qr.cc"
+
+template class base_qr<Matrix>;
+
 extern "C"
 {
   F77_RET_T
@@ -80,14 +84,13 @@
 #endif
 }
 
-QR::QR (const Matrix& a, QR::type qr_type)
-  : q (), r ()
+QR::QR (const Matrix& a, qr_type_t qr_type)
 {
   init (a, qr_type);
 }
 
 void
-QR::init (const Matrix& a, QR::type qr_type)
+QR::init (const Matrix& a, qr_type_t qr_type)
 {
   octave_idx_type m = a.rows ();
   octave_idx_type n = a.cols ();
@@ -98,7 +101,7 @@
   octave_idx_type info = 0;
 
   Matrix afact = a;
-  if (m > n && qr_type == QR::std)
+  if (m > n && qr_type == qr_type_std)
     afact.resize (m, m);
 
   if (m > 0)
@@ -118,12 +121,12 @@
 }
 
 void QR::form (octave_idx_type n, Matrix& afact, 
-               double *tau, QR::type qr_type)
+               double *tau, qr_type_t qr_type)
 {
   octave_idx_type m = afact.rows (), min_mn = std::min (m, n);
   octave_idx_type info;
 
-  if (qr_type == QR::raw)
+  if (qr_type == qr_type_raw)
     {
       for (octave_idx_type j = 0; j < min_mn; j++)
 	{
@@ -141,7 +144,7 @@
         {
           // afact will become q.
           q = afact;
-          octave_idx_type k = qr_type == QR::economy ? n : m;
+          octave_idx_type k = qr_type == qr_type_economy ? n : m;
           r = Matrix (k, n);
           for (octave_idx_type j = 0; j < n; j++)
             {
@@ -185,32 +188,6 @@
     }
 }
 
-QR::QR (const Matrix& q_arg, const Matrix& r_arg)
-{
-  octave_idx_type qr = q_arg.rows (), qc = q_arg.columns ();
-  octave_idx_type rr = r_arg.rows (), rc = r_arg.columns ();
-  if (qc == rr && (qr == qc || (qr > qc && rr == rc)))
-    {
-      q = q_arg;
-      r = r_arg;
-    }
-  else
-    (*current_liboctave_error_handler) ("QR dimensions mismatch");
-}
-
-QR::type
-QR::get_type (void) const
-{
-  QR::type retval;
-  if (!q.is_empty () && q.is_square ())
-    retval = QR::std;
-  else if (q.rows () > q.columns () && r.is_square ())
-    retval = QR::economy;
-  else
-    retval = QR::raw;
-  return retval;
-}
-
 #ifdef HAVE_QRUPDATE
 
 void
--- a/liboctave/dbleQR.h	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/dbleQR.h	Mon Oct 12 10:42:49 2009 +0200
@@ -30,47 +30,31 @@
 #include "dMatrix.h"
 #include "dColVector.h"
 #include "dRowVector.h"
+#include "base-qr.h"
 
 class
 OCTAVE_API
-QR
+QR : public base_qr<Matrix>
 {
 public:
 
-  enum type
-    {
-      std,
-      raw,
-      economy
-    };
+  // Import them here to allow the QR:: prefix.
+  typedef qr_type_t type;
 
-  QR (void) : q (), r () { }
-
-  QR (const Matrix&, QR::type = QR::std);
+  static const type std = qr_type_std;
+  static const type raw = qr_type_raw;
+  static const type economy = qr_type_economy;
 
-  QR (const Matrix& q, const Matrix& r);
-
-  QR (const QR& a) : q (a.q), r (a.r) { }
+  QR (void) : base_qr<Matrix> () { }
 
-  QR& operator = (const QR& a)
-    {
-      if (this != &a)
-	{
-	  q = a.q;
-	  r = a.r;
-	}
-      return *this;
-    }
+  QR (const Matrix&, qr_type_t = qr_type_std);
 
-  ~QR (void) { }
-
-  void init (const Matrix&, QR::type);
+  QR (const Matrix& qx, const Matrix& rx) 
+    : base_qr<Matrix> (qx, rx) { }
 
-  Matrix Q (void) const { return q; }
+  QR (const QR& a) : base_qr<Matrix> (a) { }
 
-  Matrix R (void) const { return r; }
-
-  QR::type get_type (void) const;
+  void init (const Matrix&, qr_type_t);
 
   void update (const ColumnVector& u, const ColumnVector& v);
 
@@ -90,21 +74,12 @@
 
   void shift_cols (octave_idx_type i, octave_idx_type j);
 
-  friend std::ostream&  operator << (std::ostream&, const QR&);
-
 protected:
 
   void form (octave_idx_type n, Matrix& afact, 
-             double *tau, QR::type qr_type);
-
-  Matrix q;
-  Matrix r;
+             double *tau, qr_type_t qr_type);
 };
 
-#ifndef HAVE_QRUPDATE
-void warn_qrupdate_once (void);
-#endif
-
 #endif
 
 /*
--- a/liboctave/dbleQRP.cc	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/dbleQRP.cc	Mon Oct 12 10:42:49 2009 +0200
@@ -42,16 +42,16 @@
 
 // It would be best to share some of this code with QR class...
 
-QRP::QRP (const Matrix& a, QR::type qr_type)
+QRP::QRP (const Matrix& a, qr_type_t qr_type)
   : QR (), p ()
 {
   init (a, qr_type);
 }
 
 void
-QRP::init (const Matrix& a, QR::type qr_type)
+QRP::init (const Matrix& a, qr_type_t qr_type)
 {
-  assert (qr_type != QR::raw);
+  assert (qr_type != qr_type_raw);
 
   octave_idx_type m = a.rows ();
   octave_idx_type n = a.cols ();
@@ -62,7 +62,7 @@
   octave_idx_type info = 0;
 
   Matrix afact = a;
-  if (m > n && qr_type == QR::std)
+  if (m > n && qr_type == qr_type_std)
     afact.resize (m, m);
 
   MArray<octave_idx_type> jpvt (n, 0);
--- a/liboctave/dbleQRP.h	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/dbleQRP.h	Mon Oct 12 10:42:49 2009 +0200
@@ -38,7 +38,7 @@
 
   QRP (void) : QR (), p () { }
 
-  QRP (const Matrix&, QR::type = QR::std);
+  QRP (const Matrix&, qr_type_t = qr_type_std);
 
   QRP (const QRP& a) : QR (a), p (a.p) { }
 
@@ -55,7 +55,7 @@
 
   ~QRP (void) { }
 
-  void init (const Matrix&, QR::type = QR::std);
+  void init (const Matrix&, qr_type_t = qr_type_std);
 
   PermMatrix P (void) const { return p; }
 
--- a/liboctave/fCmplxQR.cc	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/fCmplxQR.cc	Mon Oct 12 10:42:49 2009 +0200
@@ -34,6 +34,10 @@
 #include "idx-vector.h"
 #include "oct-locbuf.h"
 
+#include "base-qr.cc"
+
+template class base_qr<FloatComplexMatrix>;
+
 extern "C"
 {
   F77_RET_T
@@ -82,14 +86,13 @@
 #endif
 }
 
-FloatComplexQR::FloatComplexQR (const FloatComplexMatrix& a, QR::type qr_type)
-  : q (), r ()
+FloatComplexQR::FloatComplexQR (const FloatComplexMatrix& a, qr_type_t qr_type)
 {
   init (a, qr_type);
 }
 
 void
-FloatComplexQR::init (const FloatComplexMatrix& a, QR::type qr_type)
+FloatComplexQR::init (const FloatComplexMatrix& a, qr_type_t qr_type)
 {
   octave_idx_type m = a.rows ();
   octave_idx_type n = a.cols ();
@@ -100,7 +103,7 @@
   octave_idx_type info = 0;
 
   FloatComplexMatrix afact = a;
-  if (m > n && qr_type == QR::std)
+  if (m > n && qr_type == qr_type_std)
     afact.resize (m, m);
 
   if (m > 0)
@@ -120,12 +123,12 @@
 }
 
 void FloatComplexQR::form (octave_idx_type n, FloatComplexMatrix& afact, 
-                           FloatComplex *tau, QR::type qr_type)
+                           FloatComplex *tau, qr_type_t qr_type)
 {
   octave_idx_type m = afact.rows (), min_mn = std::min (m, n);
   octave_idx_type info;
 
-  if (qr_type == QR::raw)
+  if (qr_type == qr_type_raw)
     {
       for (octave_idx_type j = 0; j < min_mn; j++)
 	{
@@ -143,7 +146,7 @@
         {
           // afact will become q.
           q = afact;
-          octave_idx_type k = qr_type == QR::economy ? n : m;
+          octave_idx_type k = qr_type == qr_type_economy ? n : m;
           r = FloatComplexMatrix (k, n);
           for (octave_idx_type j = 0; j < n; j++)
             {
@@ -187,32 +190,6 @@
     }
 }
 
-FloatComplexQR::FloatComplexQR (const FloatComplexMatrix& q_arg, const FloatComplexMatrix& r_arg)
-{
-  octave_idx_type qr = q_arg.rows (), qc = q_arg.columns ();
-  octave_idx_type rr = r_arg.rows (), rc = r_arg.columns ();
-  if (qc == rr && (qr == qc || (qr > qc && rr == rc)))
-    {
-      q = q_arg;
-      r = r_arg;
-    }
-  else
-    (*current_liboctave_error_handler) ("QR dimensions mismatch");
-}
-
-QR::type
-FloatComplexQR::get_type (void) const
-{
-  QR::type retval;
-  if (!q.is_empty () && q.is_square ())
-    retval = QR::std;
-  else if (q.rows () > q.columns () && r.is_square ())
-    retval = QR::economy;
-  else
-    retval = QR::raw;
-  return retval;
-}
-
 #ifdef HAVE_QRUPDATE
 
 void
--- a/liboctave/fCmplxQR.h	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/fCmplxQR.h	Mon Oct 12 10:42:49 2009 +0200
@@ -32,41 +32,24 @@
 #include "fCMatrix.h"
 #include "fCColVector.h"
 #include "fCRowVector.h"
-#include "dbleQR.h"
+#include "base-qr.h"
 
 class
 OCTAVE_API
-FloatComplexQR
+FloatComplexQR : public base_qr<FloatComplexMatrix>
 {
 public:
 
-  FloatComplexQR (void) : q (), r () { }
-
-  FloatComplexQR (const FloatComplexMatrix&, QR::type = QR::std);
+  FloatComplexQR (void) : base_qr<FloatComplexMatrix> () { }
 
-  FloatComplexQR (const FloatComplexMatrix& q, const FloatComplexMatrix& r);
-
-  FloatComplexQR (const FloatComplexQR& a) : q (a.q), r (a.r) { }
+  FloatComplexQR (const FloatComplexMatrix&, qr_type_t = qr_type_std);
 
-  FloatComplexQR& operator = (const FloatComplexQR& a)
-    {
-      if (this != &a)
-	{
-	  q = a.q;
-	  r = a.r;
-	}
-      return *this;
-    }
+  FloatComplexQR (const FloatComplexMatrix& qx, const FloatComplexMatrix& rx) 
+    : base_qr<FloatComplexMatrix> (qx, rx) { }
 
-  ~FloatComplexQR (void) { }
-
-  void init (const FloatComplexMatrix&, QR::type = QR::std);
+  FloatComplexQR (const FloatComplexQR& a) : base_qr<FloatComplexMatrix> (a) { }
 
-  FloatComplexMatrix Q (void) const { return q; }
-
-  FloatComplexMatrix R (void) const { return r; }
-
-  QR::type get_type (void) const;
+  void init (const FloatComplexMatrix&, qr_type_t = qr_type_std);
 
   void update (const FloatComplexColumnVector& u, const FloatComplexColumnVector& v);
 
@@ -86,15 +69,10 @@
 
   void shift_cols (octave_idx_type i, octave_idx_type j);
 
-  friend std::ostream&  operator << (std::ostream&, const FloatComplexQR&);
-
 protected:
 
   void form (octave_idx_type n, FloatComplexMatrix& afact, 
-             FloatComplex *tau, QR::type qr_type);
-
-  FloatComplexMatrix q;
-  FloatComplexMatrix r;
+             FloatComplex *tau, qr_type_t qr_type);
 };
 
 #endif
--- a/liboctave/fCmplxQRP.cc	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/fCmplxQRP.cc	Mon Oct 12 10:42:49 2009 +0200
@@ -42,16 +42,16 @@
 
 // It would be best to share some of this code with FloatComplexQR class...
 
-FloatComplexQRP::FloatComplexQRP (const FloatComplexMatrix& a, QR::type qr_type)
+FloatComplexQRP::FloatComplexQRP (const FloatComplexMatrix& a, qr_type_t qr_type)
   : FloatComplexQR (), p ()
 {
   init (a, qr_type);
 }
 
 void
-FloatComplexQRP::init (const FloatComplexMatrix& a, QR::type qr_type)
+FloatComplexQRP::init (const FloatComplexMatrix& a, qr_type_t qr_type)
 {
-  assert (qr_type != QR::raw);
+  assert (qr_type != qr_type_raw);
 
   octave_idx_type m = a.rows ();
   octave_idx_type n = a.cols ();
@@ -62,7 +62,7 @@
   octave_idx_type info = 0;
 
   FloatComplexMatrix afact = a;
-  if (m > n && qr_type == QR::std)
+  if (m > n && qr_type == qr_type_std)
     afact.resize (m, m);
 
   MArray<octave_idx_type> jpvt (n, 0);
--- a/liboctave/fCmplxQRP.h	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/fCmplxQRP.h	Mon Oct 12 10:42:49 2009 +0200
@@ -38,7 +38,7 @@
 
   FloatComplexQRP (void) : FloatComplexQR (), p () { }
 
-  FloatComplexQRP (const FloatComplexMatrix&, QR::type = QR::std);
+  FloatComplexQRP (const FloatComplexMatrix&, qr_type_t = qr_type_std);
 
   FloatComplexQRP (const FloatComplexQRP& a) : FloatComplexQR (a), p (a.p) { }
 
@@ -54,7 +54,7 @@
 
   ~FloatComplexQRP (void) { }
 
-  void init (const FloatComplexMatrix&, QR::type = QR::std);
+  void init (const FloatComplexMatrix&, qr_type_t = qr_type_std);
 
   PermMatrix P (void) const { return p; }
 
--- a/liboctave/floatQR.cc	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/floatQR.cc	Mon Oct 12 10:42:49 2009 +0200
@@ -34,6 +34,10 @@
 #include "idx-vector.h"
 #include "oct-locbuf.h"
 
+#include "base-qr.cc"
+
+template class base_qr<FloatMatrix>;
+
 extern "C"
 {
   F77_RET_T
@@ -80,14 +84,13 @@
 #endif
 }
 
-FloatQR::FloatQR (const FloatMatrix& a, QR::type qr_type)
-  : q (), r ()
+FloatQR::FloatQR (const FloatMatrix& a, qr_type_t qr_type)
 {
   init (a, qr_type);
 }
 
 void
-FloatQR::init (const FloatMatrix& a, QR::type qr_type)
+FloatQR::init (const FloatMatrix& a, qr_type_t qr_type)
 {
   octave_idx_type m = a.rows ();
   octave_idx_type n = a.cols ();
@@ -98,7 +101,7 @@
   octave_idx_type info = 0;
 
   FloatMatrix afact = a;
-  if (m > n && qr_type == QR::std)
+  if (m > n && qr_type == qr_type_std)
     afact.resize (m, m);
 
   if (m > 0)
@@ -118,12 +121,12 @@
 }
 
 void FloatQR::form (octave_idx_type n, FloatMatrix& afact, 
-                    float *tau, QR::type qr_type)
+                    float *tau, qr_type_t qr_type)
 {
   octave_idx_type m = afact.rows (), min_mn = std::min (m, n);
   octave_idx_type info;
 
-  if (qr_type == QR::raw)
+  if (qr_type == qr_type_raw)
     {
       for (octave_idx_type j = 0; j < min_mn; j++)
 	{
@@ -141,7 +144,7 @@
         {
           // afact will become q.
           q = afact;
-          octave_idx_type k = qr_type == QR::economy ? n : m;
+          octave_idx_type k = qr_type == qr_type_economy ? n : m;
           r = FloatMatrix (k, n);
           for (octave_idx_type j = 0; j < n; j++)
             {
@@ -185,32 +188,6 @@
     }
 }
 
-FloatQR::FloatQR (const FloatMatrix& q_arg, const FloatMatrix& r_arg)
-{
-  octave_idx_type qr = q_arg.rows (), qc = q_arg.columns ();
-  octave_idx_type rr = r_arg.rows (), rc = r_arg.columns ();
-  if (qc == rr && (qr == qc || (qr > qc && rr == rc)))
-    {
-      q = q_arg;
-      r = r_arg;
-    }
-  else
-    (*current_liboctave_error_handler) ("QR dimensions mismatch");
-}
-
-QR::type
-FloatQR::get_type (void) const
-{
-  QR::type retval;
-  if (!q.is_empty () && q.is_square ())
-    retval = QR::std;
-  else if (q.rows () > q.columns () && r.is_square ())
-    retval = QR::economy;
-  else
-    retval = QR::raw;
-  return retval;
-}
-
 #ifdef HAVE_QRUPDATE
 
 void
--- a/liboctave/floatQR.h	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/floatQR.h	Mon Oct 12 10:42:49 2009 +0200
@@ -30,41 +30,24 @@
 #include "fMatrix.h"
 #include "fColVector.h"
 #include "fRowVector.h"
-#include "dbleQR.h"
+#include "base-qr.h"
 
 class
 OCTAVE_API
-FloatQR
+FloatQR : public base_qr<FloatMatrix>
 {
 public:
 
-  FloatQR (void) : q (), r () { }
-
-  FloatQR (const FloatMatrix&, QR::type = QR::std);
+  FloatQR (void) : base_qr<FloatMatrix> () { }
 
-  FloatQR (const FloatMatrix& q, const FloatMatrix& r);
-
-  FloatQR (const FloatQR& a) : q (a.q), r (a.r) { }
+  FloatQR (const FloatMatrix&, qr_type_t = qr_type_std);
 
-  FloatQR& operator = (const FloatQR& a)
-    {
-      if (this != &a)
-	{
-	  q = a.q;
-	  r = a.r;
-	}
-      return *this;
-    }
+  FloatQR (const FloatMatrix& qx, const FloatMatrix& rx) 
+    : base_qr<FloatMatrix> (qx, rx) { }
 
-  ~FloatQR (void) { }
-
-  void init (const FloatMatrix&, QR::type);
+  FloatQR (const FloatQR& a) : base_qr<FloatMatrix> (a) { }
 
-  FloatMatrix Q (void) const { return q; }
-
-  FloatMatrix R (void) const { return r; }
-
-  QR::type get_type (void) const;
+  void init (const FloatMatrix&, qr_type_t);
 
   void update (const FloatColumnVector& u, const FloatColumnVector& v);
 
@@ -84,15 +67,10 @@
 
   void shift_cols (octave_idx_type i, octave_idx_type j);
 
-  friend std::ostream&  operator << (std::ostream&, const FloatQR&);
-
 protected:
 
   void form (octave_idx_type n, FloatMatrix& afact, 
-             float *tau, QR::type qr_type);
-
-  FloatMatrix q;
-  FloatMatrix r;
+             float *tau, qr_type_t qr_type);
 };
 
 #endif
--- a/liboctave/floatQRP.cc	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/floatQRP.cc	Mon Oct 12 10:42:49 2009 +0200
@@ -42,16 +42,16 @@
 
 // It would be best to share some of this code with QR class...
 
-FloatQRP::FloatQRP (const FloatMatrix& a, QR::type qr_type)
+FloatQRP::FloatQRP (const FloatMatrix& a, qr_type_t qr_type)
   : FloatQR (), p ()
 {
   init (a, qr_type);
 }
 
 void
-FloatQRP::init (const FloatMatrix& a, QR::type qr_type)
+FloatQRP::init (const FloatMatrix& a, qr_type_t qr_type)
 {
-  assert (qr_type != QR::raw);
+  assert (qr_type != qr_type_raw);
 
   octave_idx_type m = a.rows ();
   octave_idx_type n = a.cols ();
@@ -62,7 +62,7 @@
   octave_idx_type info = 0;
 
   FloatMatrix afact = a;
-  if (m > n && qr_type == QR::std)
+  if (m > n && qr_type == qr_type_std)
     afact.resize (m, m);
 
   MArray<octave_idx_type> jpvt (n, 0);
--- a/liboctave/floatQRP.h	Sun Oct 11 15:27:51 2009 -0700
+++ b/liboctave/floatQRP.h	Mon Oct 12 10:42:49 2009 +0200
@@ -38,7 +38,7 @@
 
   FloatQRP (void) : FloatQR (), p () { }
 
-  FloatQRP (const FloatMatrix&, QR::type = QR::std);
+  FloatQRP (const FloatMatrix&, qr_type_t = qr_type_std);
 
   FloatQRP (const FloatQRP& a) : FloatQR (a), p (a.p) { }
 
@@ -55,7 +55,7 @@
 
   ~FloatQRP (void) { }
 
-  void init (const FloatMatrix&, QR::type = QR::std);
+  void init (const FloatMatrix&, qr_type_t = qr_type_std);
 
   PermMatrix P (void) const { return p; }