diff liboctave/CmplxQR.cc @ 7553:56be6f31dd4e

implementation of QR factorization updating
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 04 Mar 2008 21:47:11 -0500
parents 29980c6b8604
children 40574114c514
line wrap: on
line diff
--- a/liboctave/CmplxQR.cc
+++ b/liboctave/CmplxQR.cc
@@ -21,6 +21,8 @@
 
 */
 
+// updating/downdating by Jaroslav Hajek 2008
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -28,6 +30,8 @@
 #include "CmplxQR.h"
 #include "f77-fcn.h"
 #include "lo-error.h"
+#include "Range.h"
+#include "idx-vector.h"
 
 extern "C"
 {
@@ -40,6 +44,30 @@
   F77_FUNC (zungqr, ZUNGQR) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&,
 			     Complex*, const octave_idx_type&, Complex*,
 			     Complex*, const octave_idx_type&, octave_idx_type&);
+
+  // these come from qrupdate
+
+  F77_RET_T
+  F77_FUNC (zqr1up, ZQR1UP) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 
+                             Complex*, Complex*, const Complex*, const Complex*);
+
+  F77_RET_T
+  F77_FUNC (zqrinc, ZQRINC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 
+                             Complex*, const Complex*, Complex*, const octave_idx_type&, const Complex*);
+
+  F77_RET_T
+  F77_FUNC (zqrdec, ZQRDEC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 
+                             Complex*, const Complex*, Complex*, const octave_idx_type&);
+
+  F77_RET_T
+  F77_FUNC (zqrinr, ZQRINR) (const octave_idx_type&, const octave_idx_type&, 
+                             const Complex*, Complex*, const Complex*, Complex*, 
+                             const octave_idx_type&, const Complex*);
+
+  F77_RET_T
+  F77_FUNC (zqrder, ZQRDER) (const octave_idx_type&, const octave_idx_type&, 
+                             const Complex*, Complex*, const Complex*, Complex *, 
+                             const octave_idx_type&);
 }
 
 ComplexQR::ComplexQR (const ComplexMatrix& a, QR::type qr_type)
@@ -127,6 +155,140 @@
     }
 }
 
+
+ComplexQR::ComplexQR (const ComplexMatrix &q, const ComplexMatrix& r)
+{
+  if (q.columns () != r.rows ()) 
+    {
+      (*current_liboctave_error_handler) ("QR dimensions mismatch");
+      return;
+    }
+
+  this->q = q;
+  this->r = r;
+}
+
+void
+ComplexQR::update (const ComplexMatrix& u, const ComplexMatrix& v)
+{
+  octave_idx_type m = q.rows ();
+  octave_idx_type n = r.columns ();
+  octave_idx_type k = q.columns ();
+
+  if (u.length () != m || v.length () != n)
+    (*current_liboctave_error_handler) ("QR update dimensions mismatch");
+  else
+    F77_XFCN (zqr1up, ZQR1UP, (m, n, k, q.fortran_vec (), r.fortran_vec (), 
+			       u.data (), v.data ()));
+}
+
+void
+ComplexQR::insert_col (const ComplexMatrix& u, octave_idx_type j)
+{
+  octave_idx_type m = q.rows ();
+  octave_idx_type n = r.columns ();
+  octave_idx_type k = q.columns ();
+
+  if (u.length () != m)
+    (*current_liboctave_error_handler) ("QR insert dimensions mismatch");
+  else if (j < 1 || j > n+1) 
+    (*current_liboctave_error_handler) ("QR insert index out of range");
+  else
+    {
+      ComplexMatrix r1 (m,n+1);
+
+      F77_XFCN (zqrinc, ZQRINC, (m, n, k, q.fortran_vec (), r.data (),
+				 r1.fortran_vec (), j, u.data ()));
+
+      r = r1;
+    }
+}
+
+void
+ComplexQR::delete_col (octave_idx_type j)
+{
+  octave_idx_type m = q.rows ();
+  octave_idx_type k = r.rows ();
+  octave_idx_type n = r.columns ();
+
+  if (k < m && k < n) 
+    (*current_liboctave_error_handler) ("QR delete dimensions mismatch");
+  else if (j < 1 || j > n) 
+    (*current_liboctave_error_handler) ("QR delete index out of range");
+  else
+    {
+      ComplexMatrix r1 (k, n-1);
+
+      F77_XFCN (zqrdec, ZQRDEC, (m, n, k, q.fortran_vec (), r.data (),
+				 r1.fortran_vec (), j));
+
+      r = r1;
+    }
+}
+
+void
+ComplexQR::insert_row (const ComplexMatrix& u, octave_idx_type j)
+{
+  octave_idx_type m = r.rows ();
+  octave_idx_type n = r.columns ();
+
+  if (! q.is_square () || u.length () != n)
+    (*current_liboctave_error_handler) ("QR insert dimensions mismatch");
+  else if (j < 1 || j > m+1) 
+    (*current_liboctave_error_handler) ("QR insert index out of range");
+  else
+    {
+      ComplexMatrix q1 (m+1, m+1);
+      ComplexMatrix r1 (m+1, n);
+
+      F77_XFCN (zqrinr, ZQRINR, (m, n, q.data (), q1.fortran_vec (), 
+				 r.data (), r1.fortran_vec (), j, u.data ()));
+
+      q = q1;
+      r = r1;
+    }
+}
+
+void
+ComplexQR::delete_row (octave_idx_type j)
+{
+  octave_idx_type m = r.rows ();
+  octave_idx_type n = r.columns ();
+
+  if (! q.is_square ())
+    (*current_liboctave_error_handler) ("QR insert dimensions mismatch");
+  else if (j < 1 || j > n) 
+    (*current_liboctave_error_handler) ("QR delete index out of range");
+  else
+    {
+      ComplexMatrix q1 (m-1, m-1);
+      ComplexMatrix r1 (m-1, n);
+
+      F77_XFCN (zqrder, ZQRDER, (m, n, q.data (), q1.fortran_vec (), 
+				 r.data (), r1.fortran_vec (), j ));
+
+      q = q1;
+      r = r1;
+    }
+}
+
+void
+ComplexQR::economize (void)
+{
+  idx_vector c (':'), i (Range (1, r.columns ()));
+  q = ComplexMatrix (q.index (c, i));
+  r = ComplexMatrix (r.index (i, c));
+#if 0
+  octave_idx_type r_nc = r.columns ();
+
+  if (r.rows () > r_nc)
+    {
+      q.resize (q.rows (), r_nc);
+      r.resize (r_nc, r_nc);
+    }
+#endif
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***