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