00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 #include <vector>
00027
00028 #include "lo-error.h"
00029 #include "SparseQR.h"
00030 #include "oct-locbuf.h"
00031
00032 SparseQR::SparseQR_rep::SparseQR_rep (const SparseMatrix& a, int order)
00033 : count (1), nrows (0)
00034 #ifdef HAVE_CXSPARSE
00035 , S (0), N (0)
00036 #endif
00037 {
00038 #ifdef HAVE_CXSPARSE
00039 CXSPARSE_DNAME () A;
00040 A.nzmax = a.nnz ();
00041 A.m = a.rows ();
00042 A.n = a.cols ();
00043 nrows = A.m;
00044
00045
00046 A.p = const_cast<octave_idx_type *>(a.cidx ());
00047 A.i = const_cast<octave_idx_type *>(a.ridx ());
00048 A.x = const_cast<double *>(a.data ());
00049 A.nz = -1;
00050 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00051 #if defined(CS_VER) && (CS_VER >= 2)
00052 S = CXSPARSE_DNAME (_sqr) (order, &A, 1);
00053 #else
00054 S = CXSPARSE_DNAME (_sqr) (&A, order - 1, 1);
00055 #endif
00056
00057 N = CXSPARSE_DNAME (_qr) (&A, S);
00058 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00059 if (!N)
00060 (*current_liboctave_error_handler)
00061 ("SparseQR: sparse matrix QR factorization filled");
00062 count = 1;
00063 #else
00064 (*current_liboctave_error_handler)
00065 ("SparseQR: sparse matrix QR factorization not implemented");
00066 #endif
00067 }
00068
00069 SparseQR::SparseQR_rep::~SparseQR_rep (void)
00070 {
00071 #ifdef HAVE_CXSPARSE
00072 CXSPARSE_DNAME (_sfree) (S);
00073 CXSPARSE_DNAME (_nfree) (N);
00074 #endif
00075 }
00076
00077 SparseMatrix
00078 SparseQR::SparseQR_rep::V (void) const
00079 {
00080 #ifdef HAVE_CXSPARSE
00081
00082
00083 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00084 CXSPARSE_DNAME (_dropzeros) (N->L);
00085 CXSPARSE_DNAME () *D = CXSPARSE_DNAME (_transpose) (N->L, 1);
00086 CXSPARSE_DNAME (_spfree) (N->L);
00087 N->L = CXSPARSE_DNAME (_transpose) (D, 1);
00088 CXSPARSE_DNAME (_spfree) (D);
00089 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00090
00091 octave_idx_type nc = N->L->n;
00092 octave_idx_type nz = N->L->nzmax;
00093 SparseMatrix ret (N->L->m, nc, nz);
00094 for (octave_idx_type j = 0; j < nc+1; j++)
00095 ret.xcidx (j) = N->L->p[j];
00096 for (octave_idx_type j = 0; j < nz; j++)
00097 {
00098 ret.xridx (j) = N->L->i[j];
00099 ret.xdata (j) = N->L->x[j];
00100 }
00101 return ret;
00102 #else
00103 return SparseMatrix ();
00104 #endif
00105 }
00106
00107 ColumnVector
00108 SparseQR::SparseQR_rep::Pinv (void) const
00109 {
00110 #ifdef HAVE_CXSPARSE
00111 ColumnVector ret(N->L->m);
00112 for (octave_idx_type i = 0; i < N->L->m; i++)
00113 #if defined(CS_VER) && (CS_VER >= 2)
00114 ret.xelem(i) = S->pinv[i];
00115 #else
00116 ret.xelem(i) = S->Pinv[i];
00117 #endif
00118 return ret;
00119 #else
00120 return ColumnVector ();
00121 #endif
00122 }
00123
00124 ColumnVector
00125 SparseQR::SparseQR_rep::P (void) const
00126 {
00127 #ifdef HAVE_CXSPARSE
00128 ColumnVector ret(N->L->m);
00129 for (octave_idx_type i = 0; i < N->L->m; i++)
00130 #if defined(CS_VER) && (CS_VER >= 2)
00131 ret.xelem(S->pinv[i]) = i;
00132 #else
00133 ret.xelem(S->Pinv[i]) = i;
00134 #endif
00135 return ret;
00136 #else
00137 return ColumnVector ();
00138 #endif
00139 }
00140
00141 SparseMatrix
00142 SparseQR::SparseQR_rep::R (const bool econ) const
00143 {
00144 #ifdef HAVE_CXSPARSE
00145
00146
00147 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00148 CXSPARSE_DNAME (_dropzeros) (N->U);
00149 CXSPARSE_DNAME () *D = CXSPARSE_DNAME (_transpose) (N->U, 1);
00150 CXSPARSE_DNAME (_spfree) (N->U);
00151 N->U = CXSPARSE_DNAME (_transpose) (D, 1);
00152 CXSPARSE_DNAME (_spfree) (D);
00153 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00154
00155 octave_idx_type nc = N->U->n;
00156 octave_idx_type nz = N->U->nzmax;
00157
00158 SparseMatrix ret ((econ ? (nc > nrows ? nrows : nc) : nrows), nc, nz);
00159
00160 for (octave_idx_type j = 0; j < nc+1; j++)
00161 ret.xcidx (j) = N->U->p[j];
00162 for (octave_idx_type j = 0; j < nz; j++)
00163 {
00164 ret.xridx (j) = N->U->i[j];
00165 ret.xdata (j) = N->U->x[j];
00166 }
00167 return ret;
00168 #else
00169 return SparseMatrix ();
00170 #endif
00171 }
00172
00173 Matrix
00174 SparseQR::SparseQR_rep::C (const Matrix &b) const
00175 {
00176 #ifdef HAVE_CXSPARSE
00177 octave_idx_type b_nr = b.rows();
00178 octave_idx_type b_nc = b.cols();
00179 octave_idx_type nc = N->L->n;
00180 octave_idx_type nr = nrows;
00181 const double *bvec = b.fortran_vec();
00182 Matrix ret (b_nr, b_nc);
00183 double *vec = ret.fortran_vec();
00184 if (nr < 0 || nc < 0 || nr != b_nr)
00185 (*current_liboctave_error_handler) ("matrix dimension mismatch");
00186 else if (nr == 0 || nc == 0 || b_nc == 0)
00187 ret = Matrix (nc, b_nc, 0.0);
00188 else
00189 {
00190 OCTAVE_LOCAL_BUFFER (double, buf, S->m2);
00191 for (volatile octave_idx_type j = 0, idx = 0; j < b_nc; j++, idx+=b_nr)
00192 {
00193 octave_quit ();
00194 for (octave_idx_type i = nr; i < S->m2; i++)
00195 buf[i] = 0.;
00196 volatile octave_idx_type nm = (nr < nc ? nr : nc);
00197 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00198 #if defined(CS_VER) && (CS_VER >= 2)
00199 CXSPARSE_DNAME (_ipvec) (S->pinv, bvec + idx, buf, b_nr);
00200 #else
00201 CXSPARSE_DNAME (_ipvec) (b_nr, S->Pinv, bvec + idx, buf);
00202 #endif
00203 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00204
00205 for (volatile octave_idx_type i = 0; i < nm; i++)
00206 {
00207 octave_quit ();
00208 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00209 CXSPARSE_DNAME (_happly) (N->L, i, N->B[i], buf);
00210 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00211 }
00212 for (octave_idx_type i = 0; i < b_nr; i++)
00213 vec[i+idx] = buf[i];
00214 }
00215 }
00216 return ret;
00217 #else
00218 return Matrix ();
00219 #endif
00220 }
00221
00222 Matrix
00223 SparseQR::SparseQR_rep::Q (void) const
00224 {
00225 #ifdef HAVE_CXSPARSE
00226 octave_idx_type nc = N->L->n;
00227 octave_idx_type nr = nrows;
00228 Matrix ret (nr, nr);
00229 double *vec = ret.fortran_vec();
00230 if (nr < 0 || nc < 0)
00231 (*current_liboctave_error_handler) ("matrix dimension mismatch");
00232 else if (nr == 0 || nc == 0)
00233 ret = Matrix (nc, nr, 0.0);
00234 else
00235 {
00236 OCTAVE_LOCAL_BUFFER (double, bvec, nr + 1);
00237 for (octave_idx_type i = 0; i < nr; i++)
00238 bvec[i] = 0.;
00239 OCTAVE_LOCAL_BUFFER (double, buf, S->m2);
00240 for (volatile octave_idx_type j = 0, idx = 0; j < nr; j++, idx+=nr)
00241 {
00242 octave_quit ();
00243 bvec[j] = 1.0;
00244 for (octave_idx_type i = nr; i < S->m2; i++)
00245 buf[i] = 0.;
00246 volatile octave_idx_type nm = (nr < nc ? nr : nc);
00247 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00248 #if defined(CS_VER) && (CS_VER >= 2)
00249 CXSPARSE_DNAME (_ipvec) (S->pinv, bvec, buf, nr);
00250 #else
00251 CXSPARSE_DNAME (_ipvec) (nr, S->Pinv, bvec, buf);
00252 #endif
00253 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00254
00255 for (volatile octave_idx_type i = 0; i < nm; i++)
00256 {
00257 octave_quit ();
00258 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00259 CXSPARSE_DNAME (_happly) (N->L, i, N->B[i], buf);
00260 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00261 }
00262 for (octave_idx_type i = 0; i < nr; i++)
00263 vec[i+idx] = buf[i];
00264 bvec[j] = 0.0;
00265 }
00266 }
00267 return ret.transpose ();
00268 #else
00269 return Matrix ();
00270 #endif
00271 }
00272
00273 Matrix
00274 qrsolve(const SparseMatrix&a, const Matrix &b, octave_idx_type& info)
00275 {
00276 info = -1;
00277 #ifdef HAVE_CXSPARSE
00278 octave_idx_type nr = a.rows();
00279 octave_idx_type nc = a.cols();
00280 octave_idx_type b_nc = b.cols();
00281 octave_idx_type b_nr = b.rows();
00282 const double *bvec = b.fortran_vec();
00283 Matrix x;
00284
00285 if (nr < 0 || nc < 0 || nr != b_nr)
00286 (*current_liboctave_error_handler)
00287 ("matrix dimension mismatch in solution of minimum norm problem");
00288 else if (nr == 0 || nc == 0 || b_nc == 0)
00289 x = Matrix (nc, b_nc, 0.0);
00290 else if (nr >= nc)
00291 {
00292 SparseQR q (a, 3);
00293 if (! q.ok ())
00294 return Matrix();
00295 x.resize(nc, b_nc);
00296 double *vec = x.fortran_vec();
00297 OCTAVE_LOCAL_BUFFER (double, buf, q.S()->m2);
00298 for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
00299 i++, idx+=nc, bidx+=b_nr)
00300 {
00301 octave_quit ();
00302 for (octave_idx_type j = nr; j < q.S()->m2; j++)
00303 buf[j] = 0.;
00304 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00305 #if defined(CS_VER) && (CS_VER >= 2)
00306 CXSPARSE_DNAME (_ipvec) (q.S()->pinv, bvec + bidx, buf, nr);
00307 #else
00308 CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, bvec + bidx, buf);
00309 #endif
00310 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00311 for (volatile octave_idx_type j = 0; j < nc; j++)
00312 {
00313 octave_quit ();
00314 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00315 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00316 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00317 }
00318 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00319 CXSPARSE_DNAME (_usolve) (q.N()->U, buf);
00320 #if defined(CS_VER) && (CS_VER >= 2)
00321 CXSPARSE_DNAME (_ipvec) (q.S()->q, buf, vec + idx, nc);
00322 #else
00323 CXSPARSE_DNAME (_ipvec) (nc, q.S()->Q, buf, vec + idx);
00324 #endif
00325 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00326 }
00327 info = 0;
00328 }
00329 else
00330 {
00331 SparseMatrix at = a.hermitian();
00332 SparseQR q (at, 3);
00333 if (! q.ok ())
00334 return Matrix();
00335 x.resize(nc, b_nc);
00336 double *vec = x.fortran_vec();
00337 volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2);
00338 OCTAVE_LOCAL_BUFFER (double, buf, nbuf);
00339 for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
00340 i++, idx+=nc, bidx+=b_nr)
00341 {
00342 octave_quit ();
00343 for (octave_idx_type j = nr; j < nbuf; j++)
00344 buf[j] = 0.;
00345 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00346 #if defined(CS_VER) && (CS_VER >= 2)
00347 CXSPARSE_DNAME (_pvec) (q.S()->q, bvec + bidx, buf, nr);
00348 #else
00349 CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, bvec + bidx, buf);
00350 #endif
00351 CXSPARSE_DNAME (_utsolve) (q.N()->U, buf);
00352 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00353 for (volatile octave_idx_type j = nr-1; j >= 0; j--)
00354 {
00355 octave_quit ();
00356 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00357 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00358 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00359 }
00360 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00361 #if defined(CS_VER) && (CS_VER >= 2)
00362 CXSPARSE_DNAME (_pvec) (q.S()->pinv, buf, vec + idx, nc);
00363 #else
00364 CXSPARSE_DNAME (_pvec) (nc, q.S()->Pinv, buf, vec + idx);
00365 #endif
00366 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00367 }
00368 info = 0;
00369 }
00370
00371 return x;
00372 #else
00373 return Matrix ();
00374 #endif
00375 }
00376
00377 SparseMatrix
00378 qrsolve(const SparseMatrix&a, const SparseMatrix &b, octave_idx_type &info)
00379 {
00380 info = -1;
00381 #ifdef HAVE_CXSPARSE
00382 octave_idx_type nr = a.rows();
00383 octave_idx_type nc = a.cols();
00384 octave_idx_type b_nr = b.rows();
00385 octave_idx_type b_nc = b.cols();
00386 SparseMatrix x;
00387 volatile octave_idx_type ii, x_nz;
00388
00389 if (nr < 0 || nc < 0 || nr != b_nr)
00390 (*current_liboctave_error_handler)
00391 ("matrix dimension mismatch in solution of minimum norm problem");
00392 else if (nr == 0 || nc == 0 || b_nc == 0)
00393 x = SparseMatrix (nc, b_nc);
00394 else if (nr >= nc)
00395 {
00396 SparseQR q (a, 3);
00397 if (! q.ok ())
00398 return SparseMatrix();
00399 x = SparseMatrix (nc, b_nc, b.nnz());
00400 x.xcidx(0) = 0;
00401 x_nz = b.nnz();
00402 ii = 0;
00403 OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
00404 OCTAVE_LOCAL_BUFFER (double, buf, q.S()->m2);
00405 for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
00406 {
00407 octave_quit ();
00408 for (octave_idx_type j = 0; j < b_nr; j++)
00409 Xx[j] = b.xelem(j,i);
00410 for (octave_idx_type j = nr; j < q.S()->m2; j++)
00411 buf[j] = 0.;
00412 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00413 #if defined(CS_VER) && (CS_VER >= 2)
00414 CXSPARSE_DNAME (_ipvec) (q.S()->pinv, Xx, buf, nr);
00415 #else
00416 CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xx, buf);
00417 #endif
00418 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00419 for (volatile octave_idx_type j = 0; j < nc; j++)
00420 {
00421 octave_quit ();
00422 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00423 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00424 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00425 }
00426 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00427 CXSPARSE_DNAME (_usolve) (q.N()->U, buf);
00428 #if defined(CS_VER) && (CS_VER >= 2)
00429 CXSPARSE_DNAME (_ipvec) (q.S()->q, buf, Xx, nc);
00430 #else
00431 CXSPARSE_DNAME (_ipvec) (nc, q.S()->Q, buf, Xx);
00432 #endif
00433 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00434
00435 for (octave_idx_type j = 0; j < nc; j++)
00436 {
00437 double tmp = Xx[j];
00438 if (tmp != 0.0)
00439 {
00440 if (ii == x_nz)
00441 {
00442
00443 octave_idx_type sz = x_nz * (b_nc - i) / b_nc;
00444 sz = (sz > 10 ? sz : 10) + x_nz;
00445 x.change_capacity (sz);
00446 x_nz = sz;
00447 }
00448 x.xdata(ii) = tmp;
00449 x.xridx(ii++) = j;
00450 }
00451 }
00452 x.xcidx(i+1) = ii;
00453 }
00454 info = 0;
00455 }
00456 else
00457 {
00458 SparseMatrix at = a.hermitian();
00459 SparseQR q (at, 3);
00460 if (! q.ok ())
00461 return SparseMatrix();
00462 x = SparseMatrix (nc, b_nc, b.nnz());
00463 x.xcidx(0) = 0;
00464 x_nz = b.nnz();
00465 ii = 0;
00466 volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2);
00467 OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
00468 OCTAVE_LOCAL_BUFFER (double, buf, nbuf);
00469 for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
00470 {
00471 octave_quit ();
00472 for (octave_idx_type j = 0; j < b_nr; j++)
00473 Xx[j] = b.xelem(j,i);
00474 for (octave_idx_type j = nr; j < nbuf; j++)
00475 buf[j] = 0.;
00476 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00477 #if defined(CS_VER) && (CS_VER >= 2)
00478 CXSPARSE_DNAME (_pvec) (q.S()->q, Xx, buf, nr);
00479 #else
00480 CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xx, buf);
00481 #endif
00482 CXSPARSE_DNAME (_utsolve) (q.N()->U, buf);
00483 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00484 for (volatile octave_idx_type j = nr-1; j >= 0; j--)
00485 {
00486 octave_quit ();
00487 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00488 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00489 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00490 }
00491 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00492 #if defined(CS_VER) && (CS_VER >= 2)
00493 CXSPARSE_DNAME (_pvec) (q.S()->pinv, buf, Xx, nc);
00494 #else
00495 CXSPARSE_DNAME (_pvec) (nc, q.S()->Pinv, buf, Xx);
00496 #endif
00497 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00498
00499 for (octave_idx_type j = 0; j < nc; j++)
00500 {
00501 double tmp = Xx[j];
00502 if (tmp != 0.0)
00503 {
00504 if (ii == x_nz)
00505 {
00506
00507 octave_idx_type sz = x_nz * (b_nc - i) / b_nc;
00508 sz = (sz > 10 ? sz : 10) + x_nz;
00509 x.change_capacity (sz);
00510 x_nz = sz;
00511 }
00512 x.xdata(ii) = tmp;
00513 x.xridx(ii++) = j;
00514 }
00515 }
00516 x.xcidx(i+1) = ii;
00517 }
00518 info = 0;
00519 }
00520
00521 x.maybe_compress ();
00522 return x;
00523 #else
00524 return SparseMatrix ();
00525 #endif
00526 }
00527
00528 ComplexMatrix
00529 qrsolve(const SparseMatrix&a, const ComplexMatrix &b, octave_idx_type &info)
00530 {
00531 info = -1;
00532 #ifdef HAVE_CXSPARSE
00533 octave_idx_type nr = a.rows();
00534 octave_idx_type nc = a.cols();
00535 octave_idx_type b_nc = b.cols();
00536 octave_idx_type b_nr = b.rows();
00537 ComplexMatrix x;
00538
00539 if (nr < 0 || nc < 0 || nr != b_nr)
00540 (*current_liboctave_error_handler)
00541 ("matrix dimension mismatch in solution of minimum norm problem");
00542 else if (nr == 0 || nc == 0 || b_nc == 0)
00543 x = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0));
00544 else if (nr >= nc)
00545 {
00546 SparseQR q (a, 3);
00547 if (! q.ok ())
00548 return ComplexMatrix();
00549 x.resize(nc, b_nc);
00550 Complex *vec = x.fortran_vec();
00551 OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
00552 OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));
00553 OCTAVE_LOCAL_BUFFER (double, buf, q.S()->m2);
00554 for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
00555 {
00556 octave_quit ();
00557 for (octave_idx_type j = 0; j < b_nr; j++)
00558 {
00559 Complex c = b.xelem (j,i);
00560 Xx[j] = std::real (c);
00561 Xz[j] = std::imag (c);
00562 }
00563 for (octave_idx_type j = nr; j < q.S()->m2; j++)
00564 buf[j] = 0.;
00565 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00566 #if defined(CS_VER) && (CS_VER >= 2)
00567 CXSPARSE_DNAME (_ipvec) (q.S()->pinv, Xx, buf, nr);
00568 #else
00569 CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xx, buf);
00570 #endif
00571 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00572 for (volatile octave_idx_type j = 0; j < nc; j++)
00573 {
00574 octave_quit ();
00575 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00576 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00577 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00578 }
00579 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00580 CXSPARSE_DNAME (_usolve) (q.N()->U, buf);
00581 #if defined(CS_VER) && (CS_VER >= 2)
00582 CXSPARSE_DNAME (_ipvec) (q.S()->q, buf, Xx, nc);
00583 #else
00584 CXSPARSE_DNAME (_ipvec) (nc, q.S()->Q, buf, Xx);
00585 #endif
00586 for (octave_idx_type j = nr; j < q.S()->m2; j++)
00587 buf[j] = 0.;
00588 #if defined(CS_VER) && (CS_VER >= 2)
00589 CXSPARSE_DNAME (_ipvec) (q.S()->pinv, Xz, buf, nr);
00590 #else
00591 CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xz, buf);
00592 #endif
00593 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00594 for (volatile octave_idx_type j = 0; j < nc; j++)
00595 {
00596 octave_quit ();
00597 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00598 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00599 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00600 }
00601 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00602 CXSPARSE_DNAME (_usolve) (q.N()->U, buf);
00603 #if defined(CS_VER) && (CS_VER >= 2)
00604 CXSPARSE_DNAME (_ipvec) (q.S()->q, buf, Xz, nc);
00605 #else
00606 CXSPARSE_DNAME (_ipvec) (nc, q.S()->Q, buf, Xz);
00607 #endif
00608 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00609 for (octave_idx_type j = 0; j < nc; j++)
00610 vec[j+idx] = Complex (Xx[j], Xz[j]);
00611 }
00612 info = 0;
00613 }
00614 else
00615 {
00616 SparseMatrix at = a.hermitian();
00617 SparseQR q (at, 3);
00618 if (! q.ok ())
00619 return ComplexMatrix();
00620 x.resize(nc, b_nc);
00621 Complex *vec = x.fortran_vec();
00622 volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2);
00623 OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
00624 OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));
00625 OCTAVE_LOCAL_BUFFER (double, buf, nbuf);
00626 for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
00627 {
00628 octave_quit ();
00629 for (octave_idx_type j = 0; j < b_nr; j++)
00630 {
00631 Complex c = b.xelem (j,i);
00632 Xx[j] = std::real (c);
00633 Xz[j] = std::imag (c);
00634 }
00635 for (octave_idx_type j = nr; j < nbuf; j++)
00636 buf[j] = 0.;
00637 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00638 #if defined(CS_VER) && (CS_VER >= 2)
00639 CXSPARSE_DNAME (_pvec) (q.S()->q, Xx, buf, nr);
00640 #else
00641 CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xx, buf);
00642 #endif
00643 CXSPARSE_DNAME (_utsolve) (q.N()->U, buf);
00644 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00645 for (volatile octave_idx_type j = nr-1; j >= 0; j--)
00646 {
00647 octave_quit ();
00648 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00649 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00650 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00651 }
00652 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00653 #if defined(CS_VER) && (CS_VER >= 2)
00654 CXSPARSE_DNAME (_pvec) (q.S()->pinv, buf, Xx, nc);
00655 #else
00656 CXSPARSE_DNAME (_pvec) (nc, q.S()->Pinv, buf, Xx);
00657 #endif
00658 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00659 for (octave_idx_type j = nr; j < nbuf; j++)
00660 buf[j] = 0.;
00661 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00662 #if defined(CS_VER) && (CS_VER >= 2)
00663 CXSPARSE_DNAME (_pvec) (q.S()->q, Xz, buf, nr);
00664 #else
00665 CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xz, buf);
00666 #endif
00667 CXSPARSE_DNAME (_utsolve) (q.N()->U, buf);
00668 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00669 for (volatile octave_idx_type j = nr-1; j >= 0; j--)
00670 {
00671 octave_quit ();
00672 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00673 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00674 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00675 }
00676 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00677 #if defined(CS_VER) && (CS_VER >= 2)
00678 CXSPARSE_DNAME (_pvec) (q.S()->pinv, buf, Xz, nc);
00679 #else
00680 CXSPARSE_DNAME (_pvec) (nc, q.S()->Pinv, buf, Xz);
00681 #endif
00682 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00683 for (octave_idx_type j = 0; j < nc; j++)
00684 vec[j+idx] = Complex (Xx[j], Xz[j]);
00685 }
00686 info = 0;
00687 }
00688
00689 return x;
00690 #else
00691 return ComplexMatrix ();
00692 #endif
00693 }
00694
00695 SparseComplexMatrix
00696 qrsolve(const SparseMatrix&a, const SparseComplexMatrix &b, octave_idx_type &info)
00697 {
00698 info = -1;
00699 #ifdef HAVE_CXSPARSE
00700 octave_idx_type nr = a.rows();
00701 octave_idx_type nc = a.cols();
00702 octave_idx_type b_nr = b.rows();
00703 octave_idx_type b_nc = b.cols();
00704 SparseComplexMatrix x;
00705 volatile octave_idx_type ii, x_nz;
00706
00707 if (nr < 0 || nc < 0 || nr != b_nr)
00708 (*current_liboctave_error_handler)
00709 ("matrix dimension mismatch in solution of minimum norm problem");
00710 else if (nr == 0 || nc == 0 || b_nc == 0)
00711 x = SparseComplexMatrix (nc, b_nc);
00712 else if (nr >= nc)
00713 {
00714 SparseQR q (a, 3);
00715 if (! q.ok ())
00716 return SparseComplexMatrix();
00717 x = SparseComplexMatrix (nc, b_nc, b.nnz());
00718 x.xcidx(0) = 0;
00719 x_nz = b.nnz();
00720 ii = 0;
00721 OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
00722 OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));
00723 OCTAVE_LOCAL_BUFFER (double, buf, q.S()->m2);
00724 for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
00725 {
00726 octave_quit ();
00727 for (octave_idx_type j = 0; j < b_nr; j++)
00728 {
00729 Complex c = b.xelem (j,i);
00730 Xx[j] = std::real (c);
00731 Xz[j] = std::imag (c);
00732 }
00733 for (octave_idx_type j = nr; j < q.S()->m2; j++)
00734 buf[j] = 0.;
00735 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00736 #if defined(CS_VER) && (CS_VER >= 2)
00737 CXSPARSE_DNAME (_ipvec) (q.S()->pinv, Xx, buf, nr);
00738 #else
00739 CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xx, buf);
00740 #endif
00741 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00742 for (volatile octave_idx_type j = 0; j < nc; j++)
00743 {
00744 octave_quit ();
00745 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00746 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00747 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00748 }
00749 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00750 CXSPARSE_DNAME (_usolve) (q.N()->U, buf);
00751 #if defined(CS_VER) && (CS_VER >= 2)
00752 CXSPARSE_DNAME (_ipvec) (q.S()->q, buf, Xx, nc);
00753 #else
00754 CXSPARSE_DNAME (_ipvec) (nc, q.S()->Q, buf, Xx);
00755 #endif
00756 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00757 for (octave_idx_type j = nr; j < q.S()->m2; j++)
00758 buf[j] = 0.;
00759 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00760 #if defined(CS_VER) && (CS_VER >= 2)
00761 CXSPARSE_DNAME (_ipvec) (q.S()->pinv, Xz, buf, nr);
00762 #else
00763 CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xz, buf);
00764 #endif
00765 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00766 for (volatile octave_idx_type j = 0; j < nc; j++)
00767 {
00768 octave_quit ();
00769 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00770 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00771 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00772 }
00773 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00774 CXSPARSE_DNAME (_usolve) (q.N()->U, buf);
00775 #if defined(CS_VER) && (CS_VER >= 2)
00776 CXSPARSE_DNAME (_ipvec) (q.S()->q, buf, Xz, nc);
00777 #else
00778 CXSPARSE_DNAME (_ipvec) (nc, q.S()->Q, buf, Xz);
00779 #endif
00780 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00781
00782 for (octave_idx_type j = 0; j < nc; j++)
00783 {
00784 Complex tmp = Complex (Xx[j], Xz[j]);
00785 if (tmp != 0.0)
00786 {
00787 if (ii == x_nz)
00788 {
00789
00790 octave_idx_type sz = x_nz * (b_nc - i) / b_nc;
00791 sz = (sz > 10 ? sz : 10) + x_nz;
00792 x.change_capacity (sz);
00793 x_nz = sz;
00794 }
00795 x.xdata(ii) = tmp;
00796 x.xridx(ii++) = j;
00797 }
00798 }
00799 x.xcidx(i+1) = ii;
00800 }
00801 info = 0;
00802 }
00803 else
00804 {
00805 SparseMatrix at = a.hermitian();
00806 SparseQR q (at, 3);
00807 if (! q.ok ())
00808 return SparseComplexMatrix();
00809 x = SparseComplexMatrix (nc, b_nc, b.nnz());
00810 x.xcidx(0) = 0;
00811 x_nz = b.nnz();
00812 ii = 0;
00813 volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2);
00814 OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
00815 OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));
00816 OCTAVE_LOCAL_BUFFER (double, buf, nbuf);
00817 for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
00818 {
00819 octave_quit ();
00820 for (octave_idx_type j = 0; j < b_nr; j++)
00821 {
00822 Complex c = b.xelem (j,i);
00823 Xx[j] = std::real (c);
00824 Xz[j] = std::imag (c);
00825 }
00826 for (octave_idx_type j = nr; j < nbuf; j++)
00827 buf[j] = 0.;
00828 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00829 #if defined(CS_VER) && (CS_VER >= 2)
00830 CXSPARSE_DNAME (_pvec) (q.S()->q, Xx, buf, nr);
00831 #else
00832 CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xx, buf);
00833 #endif
00834 CXSPARSE_DNAME (_utsolve) (q.N()->U, buf);
00835 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00836 for (volatile octave_idx_type j = nr-1; j >= 0; j--)
00837 {
00838 octave_quit ();
00839 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00840 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00841 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00842 }
00843 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00844 #if defined(CS_VER) && (CS_VER >= 2)
00845 CXSPARSE_DNAME (_pvec) (q.S()->pinv, buf, Xx, nc);
00846 #else
00847 CXSPARSE_DNAME (_pvec) (nc, q.S()->Pinv, buf, Xx);
00848 #endif
00849 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00850 for (octave_idx_type j = nr; j < nbuf; j++)
00851 buf[j] = 0.;
00852 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00853 #if defined(CS_VER) && (CS_VER >= 2)
00854 CXSPARSE_DNAME (_pvec) (q.S()->q, Xz, buf, nr);
00855 #else
00856 CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xz, buf);
00857 #endif
00858 CXSPARSE_DNAME (_utsolve) (q.N()->U, buf);
00859 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00860 for (volatile octave_idx_type j = nr-1; j >= 0; j--)
00861 {
00862 octave_quit ();
00863 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00864 CXSPARSE_DNAME (_happly) (q.N()->L, j, q.N()->B[j], buf);
00865 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00866 }
00867 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00868 #if defined(CS_VER) && (CS_VER >= 2)
00869 CXSPARSE_DNAME (_pvec) (q.S()->pinv, buf, Xz, nc);
00870 #else
00871 CXSPARSE_DNAME (_pvec) (nc, q.S()->Pinv, buf, Xz);
00872 #endif
00873 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00874
00875 for (octave_idx_type j = 0; j < nc; j++)
00876 {
00877 Complex tmp = Complex (Xx[j], Xz[j]);
00878 if (tmp != 0.0)
00879 {
00880 if (ii == x_nz)
00881 {
00882
00883 octave_idx_type sz = x_nz * (b_nc - i) / b_nc;
00884 sz = (sz > 10 ? sz : 10) + x_nz;
00885 x.change_capacity (sz);
00886 x_nz = sz;
00887 }
00888 x.xdata(ii) = tmp;
00889 x.xridx(ii++) = j;
00890 }
00891 }
00892 x.xcidx(i+1) = ii;
00893 }
00894 info = 0;
00895 }
00896
00897 x.maybe_compress ();
00898 return x;
00899 #else
00900 return SparseComplexMatrix ();
00901 #endif
00902 }
00903
00904 Matrix
00905 qrsolve(const SparseMatrix &a, const MArray<double> &b,
00906 octave_idx_type &info)
00907 {
00908 return qrsolve (a, Matrix (b), info);
00909 }
00910
00911 ComplexMatrix
00912 qrsolve(const SparseMatrix &a, const MArray<Complex> &b,
00913 octave_idx_type &info)
00914 {
00915 return qrsolve (a, ComplexMatrix (b), info);
00916 }