dbleQR.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1994-2012 John W. Eaton
00004 Copyright (C) 2008-2009 Jaroslav Hajek
00005 Copyright (C) 2009 VZLU Prague
00006 
00007 This file is part of Octave.
00008 
00009 Octave is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as published by the
00011 Free Software Foundation; either version 3 of the License, or (at your
00012 option) any later version.
00013 
00014 Octave is distributed in the hope that it will be useful, but WITHOUT
00015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00017 for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with Octave; see the file COPYING.  If not, see
00021 <http://www.gnu.org/licenses/>.
00022 
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028 
00029 #include "dbleQR.h"
00030 #include "f77-fcn.h"
00031 #include "lo-error.h"
00032 #include "Range.h"
00033 #include "idx-vector.h"
00034 #include "oct-locbuf.h"
00035 
00036 #include "base-qr.cc"
00037 
00038 template class base_qr<Matrix>;
00039 
00040 extern "C"
00041 {
00042   F77_RET_T
00043   F77_FUNC (dgeqrf, DGEQRF) (const octave_idx_type&, const octave_idx_type&,
00044                              double*, const octave_idx_type&, double*,
00045                              double*, const octave_idx_type&,
00046                              octave_idx_type&);
00047 
00048   F77_RET_T
00049   F77_FUNC (dorgqr, DORGQR) (const octave_idx_type&, const octave_idx_type&,
00050                              const octave_idx_type&, double*,
00051                              const octave_idx_type&, double*, double*,
00052                              const octave_idx_type&, octave_idx_type&);
00053 
00054 #ifdef HAVE_QRUPDATE
00055 
00056   F77_RET_T
00057   F77_FUNC (dqr1up, DQR1UP) (const octave_idx_type&, const octave_idx_type&,
00058                              const octave_idx_type&, double*,
00059                              const octave_idx_type&, double*,
00060                              const octave_idx_type&, double*, double*, double*);
00061 
00062   F77_RET_T
00063   F77_FUNC (dqrinc, DQRINC) (const octave_idx_type&, const octave_idx_type&,
00064                              const octave_idx_type&, double*,
00065                              const octave_idx_type&, double*,
00066                              const octave_idx_type&, const octave_idx_type&,
00067                              const double*, double*);
00068 
00069   F77_RET_T
00070   F77_FUNC (dqrdec, DQRDEC) (const octave_idx_type&, const octave_idx_type&,
00071                              const octave_idx_type&, double*,
00072                              const octave_idx_type&, double*,
00073                              const octave_idx_type&, const octave_idx_type&,
00074                              double*);
00075 
00076   F77_RET_T
00077   F77_FUNC (dqrinr, DQRINR) (const octave_idx_type&, const octave_idx_type&,
00078                              double*, const octave_idx_type&, double*,
00079                              const octave_idx_type&, const octave_idx_type&,
00080                              const double*, double*);
00081 
00082   F77_RET_T
00083   F77_FUNC (dqrder, DQRDER) (const octave_idx_type&, const octave_idx_type&,
00084                              double*, const octave_idx_type&, double*,
00085                              const octave_idx_type&, const octave_idx_type&,
00086                              double*);
00087 
00088   F77_RET_T
00089   F77_FUNC (dqrshc, DQRSHC) (const octave_idx_type&, const octave_idx_type&,
00090                              const octave_idx_type&, double*,
00091                              const octave_idx_type&, double*,
00092                              const octave_idx_type&, const octave_idx_type&,
00093                              const octave_idx_type&, double*);
00094 
00095 #endif
00096 }
00097 
00098 const QR::type QR::raw, QR::std, QR::economy;
00099 
00100 QR::QR (const Matrix& a, qr_type_t qr_type)
00101 {
00102   init (a, qr_type);
00103 }
00104 
00105 void
00106 QR::init (const Matrix& a, qr_type_t qr_type)
00107 {
00108   octave_idx_type m = a.rows ();
00109   octave_idx_type n = a.cols ();
00110 
00111   octave_idx_type min_mn = m < n ? m : n;
00112   OCTAVE_LOCAL_BUFFER (double, tau, min_mn);
00113 
00114   octave_idx_type info = 0;
00115 
00116   Matrix afact = a;
00117   if (m > n && qr_type == qr_type_std)
00118     afact.resize (m, m);
00119 
00120   if (m > 0)
00121     {
00122       // workspace query.
00123       double rlwork;
00124       F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau, &rlwork, -1, info));
00125 
00126       // allocate buffer and do the job.
00127       octave_idx_type lwork = rlwork;
00128       lwork = std::max (lwork, static_cast<octave_idx_type> (1));
00129       OCTAVE_LOCAL_BUFFER (double, work, lwork);
00130       F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau, work, lwork, info));
00131     }
00132 
00133   form (n, afact, tau, qr_type);
00134 }
00135 
00136 void QR::form (octave_idx_type n, Matrix& afact,
00137                double *tau, qr_type_t qr_type)
00138 {
00139   octave_idx_type m = afact.rows (), min_mn = std::min (m, n);
00140   octave_idx_type info;
00141 
00142   if (qr_type == qr_type_raw)
00143     {
00144       for (octave_idx_type j = 0; j < min_mn; j++)
00145         {
00146           octave_idx_type limit = j < min_mn - 1 ? j : min_mn - 1;
00147           for (octave_idx_type i = limit + 1; i < m; i++)
00148             afact.elem (i, j) *= tau[j];
00149         }
00150 
00151       r = afact;
00152     }
00153   else
00154     {
00155       // Attempt to minimize copying.
00156       if (m >= n)
00157         {
00158           // afact will become q.
00159           q = afact;
00160           octave_idx_type k = qr_type == qr_type_economy ? n : m;
00161           r = Matrix (k, n);
00162           for (octave_idx_type j = 0; j < n; j++)
00163             {
00164               octave_idx_type i = 0;
00165               for (; i <= j; i++)
00166                 r.xelem (i, j) = afact.xelem (i, j);
00167               for (;i < k; i++)
00168                 r.xelem (i, j) = 0;
00169             }
00170           afact = Matrix (); // optimize memory
00171         }
00172       else
00173         {
00174           // afact will become r.
00175           q = Matrix (m, m);
00176           for (octave_idx_type j = 0; j < m; j++)
00177             for (octave_idx_type i = j + 1; i < m; i++)
00178               {
00179                 q.xelem (i, j) = afact.xelem (i, j);
00180                 afact.xelem (i, j) = 0;
00181               }
00182           r = afact;
00183         }
00184 
00185 
00186       if (m > 0)
00187         {
00188           octave_idx_type k = q.columns ();
00189           // workspace query.
00190           double rlwork;
00191           F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, q.fortran_vec (), m, tau,
00192                                      &rlwork, -1, info));
00193 
00194           // allocate buffer and do the job.
00195           octave_idx_type lwork = rlwork;
00196           lwork = std::max (lwork, static_cast<octave_idx_type> (1));
00197           OCTAVE_LOCAL_BUFFER (double, work, lwork);
00198           F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, q.fortran_vec (), m, tau,
00199                                      work, lwork, info));
00200         }
00201     }
00202 }
00203 
00204 #ifdef HAVE_QRUPDATE
00205 
00206 void
00207 QR::update (const ColumnVector& u, const ColumnVector& v)
00208 {
00209   octave_idx_type m = q.rows ();
00210   octave_idx_type n = r.columns ();
00211   octave_idx_type k = q.columns ();
00212 
00213   if (u.length () == m && v.length () == n)
00214     {
00215       ColumnVector utmp = u, vtmp = v;
00216       OCTAVE_LOCAL_BUFFER (double, w, 2*k);
00217       F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k,
00218                                  utmp.fortran_vec (), vtmp.fortran_vec (), w));
00219     }
00220   else
00221     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
00222 }
00223 
00224 void
00225 QR::update (const Matrix& u, const Matrix& v)
00226 {
00227   octave_idx_type m = q.rows ();
00228   octave_idx_type n = r.columns ();
00229   octave_idx_type k = q.columns ();
00230 
00231   if (u.rows () == m && v.rows () == n && u.cols () == v.cols ())
00232     {
00233       OCTAVE_LOCAL_BUFFER (double, w, 2*k);
00234       for (volatile octave_idx_type i = 0; i < u.cols (); i++)
00235         {
00236           ColumnVector utmp = u.column (i), vtmp = v.column (i);
00237           F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k,
00238                                      utmp.fortran_vec (), vtmp.fortran_vec (), w));
00239         }
00240     }
00241   else
00242     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
00243 }
00244 
00245 void
00246 QR::insert_col (const ColumnVector& u, octave_idx_type j)
00247 {
00248   octave_idx_type m = q.rows ();
00249   octave_idx_type n = r.columns ();
00250   octave_idx_type k = q.columns ();
00251 
00252   if (u.length () != m)
00253     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00254   else if (j < 0 || j > n)
00255     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00256   else
00257     {
00258       if (k < m)
00259         {
00260           q.resize (m, k+1);
00261           r.resize (k+1, n+1);
00262         }
00263       else
00264         {
00265           r.resize (k, n+1);
00266         }
00267 
00268       ColumnVector utmp = u;
00269       OCTAVE_LOCAL_BUFFER (double, w, k);
00270       F77_XFCN (dqrinc, DQRINC, (m, n, k, q.fortran_vec (), q.rows (),
00271                                  r.fortran_vec (), r.rows (), j + 1,
00272                                  utmp.data (), w));
00273     }
00274 }
00275 
00276 void
00277 QR::insert_col (const Matrix& u, const Array<octave_idx_type>& j)
00278 {
00279   octave_idx_type m = q.rows ();
00280   octave_idx_type n = r.columns ();
00281   octave_idx_type k = q.columns ();
00282 
00283   Array<octave_idx_type> jsi;
00284   Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);
00285   octave_idx_type nj = js.length ();
00286   bool dups = false;
00287   for (octave_idx_type i = 0; i < nj - 1; i++)
00288     dups = dups && js(i) == js(i+1);
00289 
00290   if (dups)
00291     (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
00292   else if (u.length () != m || u.columns () != nj)
00293     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00294   else if (nj > 0 && (js(0) < 0 || js(nj-1) > n))
00295     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00296   else if (nj > 0)
00297     {
00298       octave_idx_type kmax = std::min (k + nj, m);
00299       if (k < m)
00300         {
00301           q.resize (m, kmax);
00302           r.resize (kmax, n + nj);
00303         }
00304       else
00305         {
00306           r.resize (k, n + nj);
00307         }
00308 
00309       OCTAVE_LOCAL_BUFFER (double, w, kmax);
00310       for (volatile octave_idx_type i = 0; i < js.length (); i++)
00311         {
00312           octave_idx_type ii = i;
00313           ColumnVector utmp = u.column (jsi(i));
00314           F77_XFCN (dqrinc, DQRINC, (m, n + ii, std::min (kmax, k + ii),
00315                                      q.fortran_vec (), q.rows (),
00316                                      r.fortran_vec (), r.rows (), js(ii) + 1,
00317                                      utmp.data (), w));
00318         }
00319     }
00320 }
00321 
00322 void
00323 QR::delete_col (octave_idx_type j)
00324 {
00325   octave_idx_type m = q.rows ();
00326   octave_idx_type k = r.rows ();
00327   octave_idx_type n = r.columns ();
00328 
00329   if (j < 0 || j > n-1)
00330     (*current_liboctave_error_handler) ("qrdelete: index out of range");
00331   else
00332     {
00333       OCTAVE_LOCAL_BUFFER (double, w, k);
00334       F77_XFCN (dqrdec, DQRDEC, (m, n, k, q.fortran_vec (), q.rows (),
00335                                  r.fortran_vec (), r.rows (), j + 1, w));
00336 
00337       if (k < m)
00338         {
00339           q.resize (m, k-1);
00340           r.resize (k-1, n-1);
00341         }
00342       else
00343         {
00344           r.resize (k, n-1);
00345         }
00346     }
00347 }
00348 
00349 void
00350 QR::delete_col (const Array<octave_idx_type>& j)
00351 {
00352   octave_idx_type m = q.rows ();
00353   octave_idx_type n = r.columns ();
00354   octave_idx_type k = q.columns ();
00355 
00356   Array<octave_idx_type> jsi;
00357   Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);
00358   octave_idx_type nj = js.length ();
00359   bool dups = false;
00360   for (octave_idx_type i = 0; i < nj - 1; i++)
00361     dups = dups && js(i) == js(i+1);
00362 
00363   if (dups)
00364     (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
00365   else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0))
00366     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00367   else if (nj > 0)
00368     {
00369       OCTAVE_LOCAL_BUFFER (double, w, k);
00370       for (volatile octave_idx_type i = 0; i < js.length (); i++)
00371         {
00372           octave_idx_type ii = i;
00373           F77_XFCN (dqrdec, DQRDEC, (m, n - ii, k == m ? k : k - ii,
00374                                      q.fortran_vec (), q.rows (),
00375                                      r.fortran_vec (), r.rows (), js(ii) + 1, w));
00376         }
00377       if (k < m)
00378         {
00379           q.resize (m, k - nj);
00380           r.resize (k - nj, n - nj);
00381         }
00382       else
00383         {
00384           r.resize (k, n - nj);
00385         }
00386 
00387     }
00388 }
00389 
00390 void
00391 QR::insert_row (const RowVector& u, octave_idx_type j)
00392 {
00393   octave_idx_type m = r.rows ();
00394   octave_idx_type n = r.columns ();
00395   octave_idx_type k = std::min (m, n);
00396 
00397   if (! q.is_square () || u.length () != n)
00398     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00399   else if (j < 0 || j > m)
00400     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00401   else
00402     {
00403       q.resize (m + 1, m + 1);
00404       r.resize (m + 1, n);
00405       RowVector utmp = u;
00406       OCTAVE_LOCAL_BUFFER (double, w, k);
00407       F77_XFCN (dqrinr, DQRINR, (m, n, q.fortran_vec (), q.rows (),
00408                                  r.fortran_vec (), r.rows (),
00409                                  j + 1, utmp.fortran_vec (), w));
00410 
00411     }
00412 }
00413 
00414 void
00415 QR::delete_row (octave_idx_type j)
00416 {
00417   octave_idx_type m = r.rows ();
00418   octave_idx_type n = r.columns ();
00419 
00420   if (! q.is_square ())
00421     (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
00422   else if (j < 0 || j > m-1)
00423     (*current_liboctave_error_handler) ("qrdelete: index out of range");
00424   else
00425     {
00426       OCTAVE_LOCAL_BUFFER (double, w, 2*m);
00427       F77_XFCN (dqrder, DQRDER, (m, n, q.fortran_vec (), q.rows (),
00428                                  r.fortran_vec (), r.rows (), j + 1,
00429                                  w));
00430 
00431       q.resize (m - 1, m - 1);
00432       r.resize (m - 1, n);
00433     }
00434 }
00435 
00436 void
00437 QR::shift_cols (octave_idx_type i, octave_idx_type j)
00438 {
00439   octave_idx_type m = q.rows ();
00440   octave_idx_type k = r.rows ();
00441   octave_idx_type n = r.columns ();
00442 
00443   if (i < 0 || i > n-1 || j < 0 || j > n-1)
00444     (*current_liboctave_error_handler) ("qrshift: index out of range");
00445   else
00446     {
00447       OCTAVE_LOCAL_BUFFER (double, w, 2*k);
00448       F77_XFCN (dqrshc, DQRSHC, (m, n, k,
00449                                  q.fortran_vec (), q.rows (),
00450                                  r.fortran_vec (), r.rows (),
00451                                  i + 1, j + 1, w));
00452     }
00453 }
00454 
00455 #else
00456 
00457 // Replacement update methods.
00458 
00459 void
00460 QR::update (const ColumnVector& u, const ColumnVector& v)
00461 {
00462   warn_qrupdate_once ();
00463 
00464   octave_idx_type m = q.rows ();
00465   octave_idx_type n = r.columns ();
00466 
00467   if (u.length () == m && v.length () == n)
00468     {
00469       init(q*r + Matrix (u) * Matrix (v).transpose (), get_type ());
00470     }
00471   else
00472     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
00473 }
00474 
00475 void
00476 QR::update (const Matrix& u, const Matrix& v)
00477 {
00478   warn_qrupdate_once ();
00479 
00480   octave_idx_type m = q.rows ();
00481   octave_idx_type n = r.columns ();
00482 
00483   if (u.rows () == m && v.rows () == n && u.cols () == v.cols ())
00484     {
00485       init(q*r + u * v.transpose (), get_type ());
00486     }
00487   else
00488     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
00489 }
00490 
00491 static
00492 Matrix insert_col (const Matrix& a, octave_idx_type i,
00493                         const ColumnVector& x)
00494 {
00495   Matrix retval (a.rows (), a.columns () + 1);
00496   retval.assign (idx_vector::colon, idx_vector (0, i),
00497                  a.index (idx_vector::colon, idx_vector (0, i)));
00498   retval.assign (idx_vector::colon, idx_vector (i), x);
00499   retval.assign (idx_vector::colon, idx_vector (i+1, retval.columns ()),
00500                  a.index (idx_vector::colon, idx_vector (i, a.columns ())));
00501   return retval;
00502 }
00503 
00504 static
00505 Matrix insert_row (const Matrix& a, octave_idx_type i,
00506                         const RowVector& x)
00507 {
00508   Matrix retval (a.rows () + 1, a.columns ());
00509   retval.assign (idx_vector (0, i), idx_vector::colon,
00510                  a.index (idx_vector (0, i), idx_vector::colon));
00511   retval.assign (idx_vector (i), idx_vector::colon, x);
00512   retval.assign (idx_vector (i+1, retval.rows ()), idx_vector::colon,
00513                  a.index (idx_vector (i, a.rows ()), idx_vector::colon));
00514   return retval;
00515 }
00516 
00517 static
00518 Matrix delete_col (const Matrix& a, octave_idx_type i)
00519 {
00520   Matrix retval = a;
00521   retval.delete_elements (1, idx_vector (i));
00522   return retval;
00523 }
00524 
00525 static
00526 Matrix delete_row (const Matrix& a, octave_idx_type i)
00527 {
00528   Matrix retval = a;
00529   retval.delete_elements (0, idx_vector (i));
00530   return retval;
00531 }
00532 
00533 static
00534 Matrix shift_cols (const Matrix& a,
00535                         octave_idx_type i, octave_idx_type j)
00536 {
00537   octave_idx_type n = a.columns ();
00538   Array<octave_idx_type> p (n);
00539   for (octave_idx_type k = 0; k < n; k++) p(k) = k;
00540   if (i < j)
00541     {
00542       for (octave_idx_type k = i; k < j; k++) p(k) = k+1;
00543       p(j) = i;
00544     }
00545   else if (j < i)
00546     {
00547       p(j) = i;
00548       for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1;
00549     }
00550 
00551   return a.index (idx_vector::colon, idx_vector (p));
00552 }
00553 
00554 void
00555 QR::insert_col (const ColumnVector& u, octave_idx_type j)
00556 {
00557   warn_qrupdate_once ();
00558 
00559   octave_idx_type m = q.rows ();
00560   octave_idx_type n = r.columns ();
00561 
00562   if (u.length () != m)
00563     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00564   else if (j < 0 || j > n)
00565     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00566   else
00567     {
00568       init (::insert_col (q*r, j, u), get_type ());
00569     }
00570 }
00571 
00572 void
00573 QR::insert_col (const Matrix& u, const Array<octave_idx_type>& j)
00574 {
00575   warn_qrupdate_once ();
00576 
00577   octave_idx_type m = q.rows ();
00578   octave_idx_type n = r.columns ();
00579 
00580   Array<octave_idx_type> jsi;
00581   Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);
00582   octave_idx_type nj = js.length ();
00583   bool dups = false;
00584   for (octave_idx_type i = 0; i < nj - 1; i++)
00585     dups = dups && js(i) == js(i+1);
00586 
00587   if (dups)
00588     (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
00589   else if (u.length () != m || u.columns () != nj)
00590     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00591   else if (nj > 0 && (js(0) < 0 || js(nj-1) > n))
00592     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00593   else if (nj > 0)
00594     {
00595       Matrix a = q*r;
00596       for (octave_idx_type i = 0; i < js.length (); i++)
00597         a = ::insert_col (a, js(i), u.column (i));
00598       init (a, get_type ());
00599     }
00600 }
00601 
00602 void
00603 QR::delete_col (octave_idx_type j)
00604 {
00605   warn_qrupdate_once ();
00606 
00607   octave_idx_type m = q.rows ();
00608   octave_idx_type n = r.columns ();
00609 
00610   if (j < 0 || j > n-1)
00611     (*current_liboctave_error_handler) ("qrdelete: index out of range");
00612   else
00613     {
00614       init (::delete_col (q*r, j), get_type ());
00615     }
00616 }
00617 
00618 void
00619 QR::delete_col (const Array<octave_idx_type>& j)
00620 {
00621   warn_qrupdate_once ();
00622 
00623   octave_idx_type m = q.rows ();
00624   octave_idx_type n = r.columns ();
00625 
00626   Array<octave_idx_type> jsi;
00627   Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);
00628   octave_idx_type nj = js.length ();
00629   bool dups = false;
00630   for (octave_idx_type i = 0; i < nj - 1; i++)
00631     dups = dups && js(i) == js(i+1);
00632 
00633   if (dups)
00634     (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
00635   else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0))
00636     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00637   else if (nj > 0)
00638     {
00639       Matrix a = q*r;
00640       for (octave_idx_type i = 0; i < js.length (); i++)
00641         a = ::delete_col (a, js(i));
00642       init (a, get_type ());
00643     }
00644 }
00645 
00646 void
00647 QR::insert_row (const RowVector& u, octave_idx_type j)
00648 {
00649   warn_qrupdate_once ();
00650 
00651   octave_idx_type m = r.rows ();
00652   octave_idx_type n = r.columns ();
00653 
00654   if (! q.is_square () || u.length () != n)
00655     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00656   else if (j < 0 || j > m)
00657     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00658   else
00659     {
00660       init (::insert_row (q*r, j, u), get_type ());
00661     }
00662 }
00663 
00664 void
00665 QR::delete_row (octave_idx_type j)
00666 {
00667   octave_idx_type m = r.rows ();
00668   octave_idx_type n = r.columns ();
00669 
00670   if (! q.is_square ())
00671     (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
00672   else if (j < 0 || j > m-1)
00673     (*current_liboctave_error_handler) ("qrdelete: index out of range");
00674   else
00675     {
00676       init (::delete_row (q*r, j), get_type ());
00677     }
00678 }
00679 
00680 void
00681 QR::shift_cols (octave_idx_type i, octave_idx_type j)
00682 {
00683   warn_qrupdate_once ();
00684 
00685   octave_idx_type m = q.rows ();
00686   octave_idx_type n = r.columns ();
00687 
00688   if (i < 0 || i > n-1 || j < 0 || j > n-1)
00689     (*current_liboctave_error_handler) ("qrshift: index out of range");
00690   else
00691     {
00692       init (::shift_cols (q*r, i, j), get_type ());
00693     }
00694 }
00695 
00696 void warn_qrupdate_once (void)
00697 {
00698   static bool warned = false;
00699   if (! warned)
00700     {
00701       (*current_liboctave_warning_handler)
00702         ("In this version of Octave, QR & Cholesky updating routines\n"
00703          "simply update the matrix and recalculate factorizations.\n"
00704          "To use fast algorithms, link Octave with the qrupdate library.\n"
00705          "See <http://sourceforge.net/projects/qrupdate>.\n");
00706       warned = true;
00707     }
00708 }
00709 
00710 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines