fCmplxQR.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 "fCmplxQR.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<FloatComplexMatrix>;
00039 
00040 extern "C"
00041 {
00042   F77_RET_T
00043   F77_FUNC (cgeqrf, CGEQRF) (const octave_idx_type&, const octave_idx_type&,
00044                              FloatComplex*, const octave_idx_type&,
00045                              FloatComplex*, FloatComplex*,
00046                              const octave_idx_type&, octave_idx_type&);
00047 
00048   F77_RET_T
00049   F77_FUNC (cungqr, CUNGQR) (const octave_idx_type&, const octave_idx_type&,
00050                              const octave_idx_type&, FloatComplex*,
00051                              const octave_idx_type&, FloatComplex*,
00052                              FloatComplex*, const octave_idx_type&,
00053                              octave_idx_type&);
00054 
00055 #ifdef HAVE_QRUPDATE
00056 
00057   F77_RET_T
00058   F77_FUNC (cqr1up, CQR1UP) (const octave_idx_type&, const octave_idx_type&,
00059                              const octave_idx_type&, FloatComplex*,
00060                              const octave_idx_type&, FloatComplex*,
00061                              const octave_idx_type&, FloatComplex*,
00062                              FloatComplex*, FloatComplex*, float*);
00063 
00064   F77_RET_T
00065   F77_FUNC (cqrinc, CQRINC) (const octave_idx_type&, const octave_idx_type&,
00066                              const octave_idx_type&, FloatComplex*,
00067                              const octave_idx_type&, FloatComplex*,
00068                              const octave_idx_type&,const octave_idx_type&,
00069                              const FloatComplex*, float*);
00070 
00071   F77_RET_T
00072   F77_FUNC (cqrdec, CQRDEC) (const octave_idx_type&, const octave_idx_type&,
00073                              const octave_idx_type&, FloatComplex*,
00074                              const octave_idx_type&, FloatComplex*,
00075                              const octave_idx_type&, const octave_idx_type&,
00076                              float*);
00077 
00078   F77_RET_T
00079   F77_FUNC (cqrinr, CQRINR) (const octave_idx_type&, const octave_idx_type&,
00080                              FloatComplex*, const octave_idx_type&,
00081                              FloatComplex*, const octave_idx_type&,
00082                              const octave_idx_type&, const FloatComplex*,
00083                              float*);
00084 
00085   F77_RET_T
00086   F77_FUNC (cqrder, CQRDER) (const octave_idx_type&, const octave_idx_type&,
00087                              FloatComplex*, const octave_idx_type&,
00088                              FloatComplex*, const octave_idx_type&,
00089                              const octave_idx_type&, FloatComplex*, float*);
00090 
00091   F77_RET_T
00092   F77_FUNC (cqrshc, CQRSHC) (const octave_idx_type&, const octave_idx_type&,
00093                              const octave_idx_type&, FloatComplex*,
00094                              const octave_idx_type&, FloatComplex*,
00095                              const octave_idx_type&, const octave_idx_type&,
00096                              const octave_idx_type&, FloatComplex*,
00097                              float*);
00098 
00099 #endif
00100 }
00101 
00102 FloatComplexQR::FloatComplexQR (const FloatComplexMatrix& a, qr_type_t qr_type)
00103 {
00104   init (a, qr_type);
00105 }
00106 
00107 void
00108 FloatComplexQR::init (const FloatComplexMatrix& a, qr_type_t qr_type)
00109 {
00110   octave_idx_type m = a.rows ();
00111   octave_idx_type n = a.cols ();
00112 
00113   octave_idx_type min_mn = m < n ? m : n;
00114   OCTAVE_LOCAL_BUFFER (FloatComplex, tau, min_mn);
00115 
00116   octave_idx_type info = 0;
00117 
00118   FloatComplexMatrix afact = a;
00119   if (m > n && qr_type == qr_type_std)
00120     afact.resize (m, m);
00121 
00122   if (m > 0)
00123     {
00124       // workspace query.
00125       FloatComplex clwork;
00126       F77_XFCN (cgeqrf, CGEQRF, (m, n, afact.fortran_vec (), m, tau, &clwork, -1, info));
00127 
00128       // allocate buffer and do the job.
00129       octave_idx_type lwork = clwork.real ();
00130       lwork = std::max (lwork, static_cast<octave_idx_type> (1));
00131       OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);
00132       F77_XFCN (cgeqrf, CGEQRF, (m, n, afact.fortran_vec (), m, tau, work, lwork, info));
00133     }
00134 
00135   form (n, afact, tau, qr_type);
00136 }
00137 
00138 void FloatComplexQR::form (octave_idx_type n, FloatComplexMatrix& afact,
00139                            FloatComplex *tau, qr_type_t qr_type)
00140 {
00141   octave_idx_type m = afact.rows (), min_mn = std::min (m, n);
00142   octave_idx_type info;
00143 
00144   if (qr_type == qr_type_raw)
00145     {
00146       for (octave_idx_type j = 0; j < min_mn; j++)
00147         {
00148           octave_idx_type limit = j < min_mn - 1 ? j : min_mn - 1;
00149           for (octave_idx_type i = limit + 1; i < m; i++)
00150             afact.elem (i, j) *= tau[j];
00151         }
00152 
00153       r = afact;
00154     }
00155   else
00156     {
00157       // Attempt to minimize copying.
00158       if (m >= n)
00159         {
00160           // afact will become q.
00161           q = afact;
00162           octave_idx_type k = qr_type == qr_type_economy ? n : m;
00163           r = FloatComplexMatrix (k, n);
00164           for (octave_idx_type j = 0; j < n; j++)
00165             {
00166               octave_idx_type i = 0;
00167               for (; i <= j; i++)
00168                 r.xelem (i, j) = afact.xelem (i, j);
00169               for (;i < k; i++)
00170                 r.xelem (i, j) = 0;
00171             }
00172           afact = FloatComplexMatrix (); // optimize memory
00173         }
00174       else
00175         {
00176           // afact will become r.
00177           q = FloatComplexMatrix (m, m);
00178           for (octave_idx_type j = 0; j < m; j++)
00179             for (octave_idx_type i = j + 1; i < m; i++)
00180               {
00181                 q.xelem (i, j) = afact.xelem (i, j);
00182                 afact.xelem (i, j) = 0;
00183               }
00184           r = afact;
00185         }
00186 
00187 
00188       if (m > 0)
00189         {
00190           octave_idx_type k = q.columns ();
00191           // workspace query.
00192           FloatComplex clwork;
00193           F77_XFCN (cungqr, CUNGQR, (m, k, min_mn, q.fortran_vec (), m, tau,
00194                                      &clwork, -1, info));
00195 
00196           // allocate buffer and do the job.
00197           octave_idx_type lwork = clwork.real ();
00198           lwork = std::max (lwork, static_cast<octave_idx_type> (1));
00199           OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);
00200           F77_XFCN (cungqr, CUNGQR, (m, k, min_mn, q.fortran_vec (), m, tau,
00201                                      work, lwork, info));
00202         }
00203     }
00204 }
00205 
00206 #ifdef HAVE_QRUPDATE
00207 
00208 void
00209 FloatComplexQR::update (const FloatComplexColumnVector& u, const FloatComplexColumnVector& v)
00210 {
00211   octave_idx_type m = q.rows ();
00212   octave_idx_type n = r.columns ();
00213   octave_idx_type k = q.columns ();
00214 
00215   if (u.length () == m && v.length () == n)
00216     {
00217       FloatComplexColumnVector utmp = u, vtmp = v;
00218       OCTAVE_LOCAL_BUFFER (FloatComplex, w, k);
00219       OCTAVE_LOCAL_BUFFER (float, rw, k);
00220       F77_XFCN (cqr1up, CQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k,
00221                                  utmp.fortran_vec (), vtmp.fortran_vec (), w, rw));
00222     }
00223   else
00224     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
00225 }
00226 
00227 void
00228 FloatComplexQR::update (const FloatComplexMatrix& u, const FloatComplexMatrix& v)
00229 {
00230   octave_idx_type m = q.rows ();
00231   octave_idx_type n = r.columns ();
00232   octave_idx_type k = q.columns ();
00233 
00234   if (u.rows () == m && v.rows () == n && u.cols () == v.cols ())
00235     {
00236       OCTAVE_LOCAL_BUFFER (FloatComplex, w, k);
00237       OCTAVE_LOCAL_BUFFER (float, rw, k);
00238       for (volatile octave_idx_type i = 0; i < u.cols (); i++)
00239         {
00240           FloatComplexColumnVector utmp = u.column (i), vtmp = v.column (i);
00241           F77_XFCN (cqr1up, CQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k,
00242                                      utmp.fortran_vec (), vtmp.fortran_vec (), w, rw));
00243         }
00244     }
00245   else
00246     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
00247 }
00248 
00249 void
00250 FloatComplexQR::insert_col (const FloatComplexColumnVector& u, octave_idx_type j)
00251 {
00252   octave_idx_type m = q.rows ();
00253   octave_idx_type n = r.columns ();
00254   octave_idx_type k = q.columns ();
00255 
00256   if (u.length () != m)
00257     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00258   else if (j < 0 || j > n)
00259     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00260   else
00261     {
00262       if (k < m)
00263         {
00264           q.resize (m, k+1);
00265           r.resize (k+1, n+1);
00266         }
00267       else
00268         {
00269           r.resize (k, n+1);
00270         }
00271 
00272       FloatComplexColumnVector utmp = u;
00273       OCTAVE_LOCAL_BUFFER (float, rw, k);
00274       F77_XFCN (cqrinc, CQRINC, (m, n, k, q.fortran_vec (), q.rows (),
00275                                  r.fortran_vec (), r.rows (), j + 1,
00276                                  utmp.data (), rw));
00277     }
00278 }
00279 
00280 void
00281 FloatComplexQR::insert_col (const FloatComplexMatrix& u, const Array<octave_idx_type>& j)
00282 {
00283   octave_idx_type m = q.rows ();
00284   octave_idx_type n = r.columns ();
00285   octave_idx_type k = q.columns ();
00286 
00287   Array<octave_idx_type> jsi;
00288   Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);
00289   octave_idx_type nj = js.length ();
00290   bool dups = false;
00291   for (octave_idx_type i = 0; i < nj - 1; i++)
00292     dups = dups && js(i) == js(i+1);
00293 
00294   if (dups)
00295     (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
00296   else if (u.length () != m || u.columns () != nj)
00297     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00298   else if (nj > 0 && (js(0) < 0 || js(nj-1) > n))
00299     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00300   else if (nj > 0)
00301     {
00302       octave_idx_type kmax = std::min (k + nj, m);
00303       if (k < m)
00304         {
00305           q.resize (m, kmax);
00306           r.resize (kmax, n + nj);
00307         }
00308       else
00309         {
00310           r.resize (k, n + nj);
00311         }
00312 
00313       OCTAVE_LOCAL_BUFFER (float, rw, kmax);
00314       for (volatile octave_idx_type i = 0; i < js.length (); i++)
00315         {
00316           octave_idx_type ii = i;
00317           F77_XFCN (cqrinc, CQRINC, (m, n + ii, std::min (kmax, k + ii),
00318                                      q.fortran_vec (), q.rows (),
00319                                      r.fortran_vec (), r.rows (), js(ii) + 1,
00320                                      u.column (jsi(i)).data (), rw));
00321         }
00322     }
00323 }
00324 
00325 void
00326 FloatComplexQR::delete_col (octave_idx_type j)
00327 {
00328   octave_idx_type m = q.rows ();
00329   octave_idx_type k = r.rows ();
00330   octave_idx_type n = r.columns ();
00331 
00332   if (j < 0 || j > n-1)
00333     (*current_liboctave_error_handler) ("qrdelete: index out of range");
00334   else
00335     {
00336       OCTAVE_LOCAL_BUFFER (float, rw, k);
00337       F77_XFCN (cqrdec, CQRDEC, (m, n, k, q.fortran_vec (), q.rows (),
00338                                  r.fortran_vec (), r.rows (), j + 1, rw));
00339 
00340       if (k < m)
00341         {
00342           q.resize (m, k-1);
00343           r.resize (k-1, n-1);
00344         }
00345       else
00346         {
00347           r.resize (k, n-1);
00348         }
00349     }
00350 }
00351 
00352 void
00353 FloatComplexQR::delete_col (const Array<octave_idx_type>& j)
00354 {
00355   octave_idx_type m = q.rows ();
00356   octave_idx_type n = r.columns ();
00357   octave_idx_type k = q.columns ();
00358 
00359   Array<octave_idx_type> jsi;
00360   Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);
00361   octave_idx_type nj = js.length ();
00362   bool dups = false;
00363   for (octave_idx_type i = 0; i < nj - 1; i++)
00364     dups = dups && js(i) == js(i+1);
00365 
00366   if (dups)
00367     (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
00368   else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0))
00369     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00370   else if (nj > 0)
00371     {
00372       OCTAVE_LOCAL_BUFFER (float, rw, k);
00373       for (volatile octave_idx_type i = 0; i < js.length (); i++)
00374         {
00375           octave_idx_type ii = i;
00376           F77_XFCN (cqrdec, CQRDEC, (m, n - ii, k == m ? k : k - ii,
00377                                      q.fortran_vec (), q.rows (),
00378                                      r.fortran_vec (), r.rows (), js(ii) + 1, rw));
00379         }
00380       if (k < m)
00381         {
00382           q.resize (m, k - nj);
00383           r.resize (k - nj, n - nj);
00384         }
00385       else
00386         {
00387           r.resize (k, n - nj);
00388         }
00389 
00390     }
00391 }
00392 
00393 void
00394 FloatComplexQR::insert_row (const FloatComplexRowVector& u, octave_idx_type j)
00395 {
00396   octave_idx_type m = r.rows ();
00397   octave_idx_type n = r.columns ();
00398   octave_idx_type k = std::min (m, n);
00399 
00400   if (! q.is_square () || u.length () != n)
00401     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00402   else if (j < 0 || j > m)
00403     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00404   else
00405     {
00406       q.resize (m + 1, m + 1);
00407       r.resize (m + 1, n);
00408       FloatComplexRowVector utmp = u;
00409       OCTAVE_LOCAL_BUFFER (float, rw, k);
00410       F77_XFCN (cqrinr, CQRINR, (m, n, q.fortran_vec (), q.rows (),
00411                                  r.fortran_vec (), r.rows (),
00412                                  j + 1, utmp.fortran_vec (), rw));
00413 
00414     }
00415 }
00416 
00417 void
00418 FloatComplexQR::delete_row (octave_idx_type j)
00419 {
00420   octave_idx_type m = r.rows ();
00421   octave_idx_type n = r.columns ();
00422 
00423   if (! q.is_square ())
00424     (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
00425   else if (j < 0 || j > m-1)
00426     (*current_liboctave_error_handler) ("qrdelete: index out of range");
00427   else
00428     {
00429       OCTAVE_LOCAL_BUFFER (FloatComplex, w, m);
00430       OCTAVE_LOCAL_BUFFER (float, rw, m);
00431       F77_XFCN (cqrder, CQRDER, (m, n, q.fortran_vec (), q.rows (),
00432                                  r.fortran_vec (), r.rows (), j + 1,
00433                                  w, rw));
00434 
00435       q.resize (m - 1, m - 1);
00436       r.resize (m - 1, n);
00437     }
00438 }
00439 
00440 void
00441 FloatComplexQR::shift_cols (octave_idx_type i, octave_idx_type j)
00442 {
00443   octave_idx_type m = q.rows ();
00444   octave_idx_type k = r.rows ();
00445   octave_idx_type n = r.columns ();
00446 
00447   if (i < 0 || i > n-1 || j < 0 || j > n-1)
00448     (*current_liboctave_error_handler) ("qrshift: index out of range");
00449   else
00450     {
00451       OCTAVE_LOCAL_BUFFER (FloatComplex, w, k);
00452       OCTAVE_LOCAL_BUFFER (float, rw, k);
00453       F77_XFCN (cqrshc, CQRSHC, (m, n, k,
00454                                  q.fortran_vec (), q.rows (),
00455                                  r.fortran_vec (), r.rows (),
00456                                  i + 1, j + 1, w, rw));
00457     }
00458 }
00459 
00460 #else
00461 
00462 // Replacement update methods.
00463 
00464 void
00465 FloatComplexQR::update (const FloatComplexColumnVector& u, const FloatComplexColumnVector& v)
00466 {
00467   warn_qrupdate_once ();
00468 
00469   octave_idx_type m = q.rows ();
00470   octave_idx_type n = r.columns ();
00471 
00472   if (u.length () == m && v.length () == n)
00473     {
00474       init(q*r + FloatComplexMatrix (u) * FloatComplexMatrix (v).hermitian (), get_type ());
00475     }
00476   else
00477     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
00478 }
00479 
00480 void
00481 FloatComplexQR::update (const FloatComplexMatrix& u, const FloatComplexMatrix& v)
00482 {
00483   warn_qrupdate_once ();
00484 
00485   octave_idx_type m = q.rows ();
00486   octave_idx_type n = r.columns ();
00487 
00488   if (u.rows () == m && v.rows () == n && u.cols () == v.cols ())
00489     {
00490       init(q*r + u * v.hermitian (), get_type ());
00491     }
00492   else
00493     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
00494 }
00495 
00496 static
00497 FloatComplexMatrix insert_col (const FloatComplexMatrix& a, octave_idx_type i,
00498                                const FloatComplexColumnVector& x)
00499 {
00500   FloatComplexMatrix retval (a.rows (), a.columns () + 1);
00501   retval.assign (idx_vector::colon, idx_vector (0, i),
00502                  a.index (idx_vector::colon, idx_vector (0, i)));
00503   retval.assign (idx_vector::colon, idx_vector (i), x);
00504   retval.assign (idx_vector::colon, idx_vector (i+1, retval.columns ()),
00505                  a.index (idx_vector::colon, idx_vector (i, a.columns ())));
00506   return retval;
00507 }
00508 
00509 static
00510 FloatComplexMatrix insert_row (const FloatComplexMatrix& a, octave_idx_type i,
00511                                const FloatComplexRowVector& x)
00512 {
00513   FloatComplexMatrix retval (a.rows () + 1, a.columns ());
00514   retval.assign (idx_vector (0, i), idx_vector::colon,
00515                  a.index (idx_vector (0, i), idx_vector::colon));
00516   retval.assign (idx_vector (i), idx_vector::colon, x);
00517   retval.assign (idx_vector (i+1, retval.rows ()), idx_vector::colon,
00518                  a.index (idx_vector (i, a.rows ()), idx_vector::colon));
00519   return retval;
00520 }
00521 
00522 static
00523 FloatComplexMatrix delete_col (const FloatComplexMatrix& a, octave_idx_type i)
00524 {
00525   FloatComplexMatrix retval = a;
00526   retval.delete_elements (1, idx_vector (i));
00527   return retval;
00528 }
00529 
00530 static
00531 FloatComplexMatrix delete_row (const FloatComplexMatrix& a, octave_idx_type i)
00532 {
00533   FloatComplexMatrix retval = a;
00534   retval.delete_elements (0, idx_vector (i));
00535   return retval;
00536 }
00537 
00538 static
00539 FloatComplexMatrix shift_cols (const FloatComplexMatrix& a,
00540                                octave_idx_type i, octave_idx_type j)
00541 {
00542   octave_idx_type n = a.columns ();
00543   Array<octave_idx_type> p (n);
00544   for (octave_idx_type k = 0; k < n; k++) p(k) = k;
00545   if (i < j)
00546     {
00547       for (octave_idx_type k = i; k < j; k++) p(k) = k+1;
00548       p(j) = i;
00549     }
00550   else if (j < i)
00551     {
00552       p(j) = i;
00553       for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1;
00554     }
00555 
00556   return a.index (idx_vector::colon, idx_vector (p));
00557 }
00558 
00559 void
00560 FloatComplexQR::insert_col (const FloatComplexColumnVector& u, octave_idx_type j)
00561 {
00562   warn_qrupdate_once ();
00563 
00564   octave_idx_type m = q.rows ();
00565   octave_idx_type n = r.columns ();
00566 
00567   if (u.length () != m)
00568     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00569   else if (j < 0 || j > n)
00570     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00571   else
00572     {
00573       init (::insert_col (q*r, j, u), get_type ());
00574     }
00575 }
00576 
00577 void
00578 FloatComplexQR::insert_col (const FloatComplexMatrix& u, const Array<octave_idx_type>& j)
00579 {
00580   warn_qrupdate_once ();
00581 
00582   octave_idx_type m = q.rows ();
00583   octave_idx_type n = r.columns ();
00584 
00585   Array<octave_idx_type> jsi;
00586   Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);
00587   octave_idx_type nj = js.length ();
00588   bool dups = false;
00589   for (octave_idx_type i = 0; i < nj - 1; i++)
00590     dups = dups && js(i) == js(i+1);
00591 
00592   if (dups)
00593     (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
00594   else if (u.length () != m || u.columns () != nj)
00595     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00596   else if (nj > 0 && (js(0) < 0 || js(nj-1) > n))
00597     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00598   else if (nj > 0)
00599     {
00600       FloatComplexMatrix a = q*r;
00601       for (octave_idx_type i = 0; i < js.length (); i++)
00602         a = ::insert_col (a, js(i), u.column (i));
00603       init (a, get_type ());
00604     }
00605 }
00606 
00607 void
00608 FloatComplexQR::delete_col (octave_idx_type j)
00609 {
00610   warn_qrupdate_once ();
00611 
00612   octave_idx_type m = q.rows ();
00613   octave_idx_type n = r.columns ();
00614 
00615   if (j < 0 || j > n-1)
00616     (*current_liboctave_error_handler) ("qrdelete: index out of range");
00617   else
00618     {
00619       init (::delete_col (q*r, j), get_type ());
00620     }
00621 }
00622 
00623 void
00624 FloatComplexQR::delete_col (const Array<octave_idx_type>& j)
00625 {
00626   warn_qrupdate_once ();
00627 
00628   octave_idx_type m = q.rows ();
00629   octave_idx_type n = r.columns ();
00630 
00631   Array<octave_idx_type> jsi;
00632   Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);
00633   octave_idx_type nj = js.length ();
00634   bool dups = false;
00635   for (octave_idx_type i = 0; i < nj - 1; i++)
00636     dups = dups && js(i) == js(i+1);
00637 
00638   if (dups)
00639     (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
00640   else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0))
00641     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00642   else if (nj > 0)
00643     {
00644       FloatComplexMatrix a = q*r;
00645       for (octave_idx_type i = 0; i < js.length (); i++)
00646         a = ::delete_col (a, js(i));
00647       init (a, get_type ());
00648     }
00649 }
00650 
00651 void
00652 FloatComplexQR::insert_row (const FloatComplexRowVector& u, octave_idx_type j)
00653 {
00654   warn_qrupdate_once ();
00655 
00656   octave_idx_type m = r.rows ();
00657   octave_idx_type n = r.columns ();
00658 
00659   if (! q.is_square () || u.length () != n)
00660     (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
00661   else if (j < 0 || j > m)
00662     (*current_liboctave_error_handler) ("qrinsert: index out of range");
00663   else
00664     {
00665       init (::insert_row (q*r, j, u), get_type ());
00666     }
00667 }
00668 
00669 void
00670 FloatComplexQR::delete_row (octave_idx_type j)
00671 {
00672   warn_qrupdate_once ();
00673 
00674   octave_idx_type m = r.rows ();
00675   octave_idx_type n = r.columns ();
00676 
00677   if (! q.is_square ())
00678     (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
00679   else if (j < 0 || j > m-1)
00680     (*current_liboctave_error_handler) ("qrdelete: index out of range");
00681   else
00682     {
00683       init (::delete_row (q*r, j), get_type ());
00684     }
00685 }
00686 
00687 void
00688 FloatComplexQR::shift_cols (octave_idx_type i, octave_idx_type j)
00689 {
00690   warn_qrupdate_once ();
00691 
00692   octave_idx_type m = q.rows ();
00693   octave_idx_type n = r.columns ();
00694 
00695   if (i < 0 || i > n-1 || j < 0 || j > n-1)
00696     (*current_liboctave_error_handler) ("qrshift: index out of range");
00697   else
00698     {
00699       init (::shift_cols (q*r, i, j), get_type ());
00700     }
00701 }
00702 
00703 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines