00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00125 FloatComplex clwork;
00126 F77_XFCN (cgeqrf, CGEQRF, (m, n, afact.fortran_vec (), m, tau, &clwork, -1, info));
00127
00128
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
00158 if (m >= n)
00159 {
00160
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 ();
00173 }
00174 else
00175 {
00176
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
00192 FloatComplex clwork;
00193 F77_XFCN (cungqr, CUNGQR, (m, k, min_mn, q.fortran_vec (), m, tau,
00194 &clwork, -1, info));
00195
00196
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
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