cgelss.c
Go to the documentation of this file.
00001 /* cgelss.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Table of constant values */
00017 
00018 static complex c_b1 = {0.f,0.f};
00019 static complex c_b2 = {1.f,0.f};
00020 static integer c__6 = 6;
00021 static integer c_n1 = -1;
00022 static integer c__1 = 1;
00023 static integer c__0 = 0;
00024 static real c_b78 = 0.f;
00025 
00026 /* Subroutine */ int cgelss_(integer *m, integer *n, integer *nrhs, complex *
00027         a, integer *lda, complex *b, integer *ldb, real *s, real *rcond, 
00028         integer *rank, complex *work, integer *lwork, real *rwork, integer *
00029         info)
00030 {
00031     /* System generated locals */
00032     integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3;
00033     real r__1;
00034 
00035     /* Local variables */
00036     integer i__, bl, ie, il, mm;
00037     real eps, thr, anrm, bnrm;
00038     integer itau;
00039     complex vdum[1];
00040     extern /* Subroutine */ int cgemm_(char *, char *, integer *, integer *, 
00041             integer *, complex *, complex *, integer *, complex *, integer *, 
00042             complex *, complex *, integer *);
00043     integer iascl, ibscl;
00044     extern /* Subroutine */ int cgemv_(char *, integer *, integer *, complex *
00045 , complex *, integer *, complex *, integer *, complex *, complex *
00046 , integer *);
00047     integer chunk;
00048     real sfmin;
00049     extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, 
00050             complex *, integer *);
00051     integer minmn, maxmn, itaup, itauq, mnthr, iwork;
00052     extern /* Subroutine */ int cgebrd_(integer *, integer *, complex *, 
00053             integer *, real *, real *, complex *, complex *, complex *, 
00054             integer *, integer *), slabad_(real *, real *);
00055     extern doublereal clange_(char *, integer *, integer *, complex *, 
00056             integer *, real *);
00057     extern /* Subroutine */ int cgelqf_(integer *, integer *, complex *, 
00058             integer *, complex *, complex *, integer *, integer *), clascl_(
00059             char *, integer *, integer *, real *, real *, integer *, integer *
00060 , complex *, integer *, integer *), cgeqrf_(integer *, 
00061             integer *, complex *, integer *, complex *, complex *, integer *, 
00062             integer *);
00063     extern doublereal slamch_(char *);
00064     extern /* Subroutine */ int clacpy_(char *, integer *, integer *, complex 
00065             *, integer *, complex *, integer *), claset_(char *, 
00066             integer *, integer *, complex *, complex *, complex *, integer *), xerbla_(char *, integer *), cbdsqr_(char *, 
00067             integer *, integer *, integer *, integer *, real *, real *, 
00068             complex *, integer *, complex *, integer *, complex *, integer *, 
00069             real *, integer *);
00070     extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
00071             integer *, integer *);
00072     real bignum;
00073     extern /* Subroutine */ int cungbr_(char *, integer *, integer *, integer 
00074             *, complex *, integer *, complex *, complex *, integer *, integer 
00075             *), slascl_(char *, integer *, integer *, real *, real *, 
00076             integer *, integer *, real *, integer *, integer *), 
00077             cunmbr_(char *, char *, char *, integer *, integer *, integer *, 
00078             complex *, integer *, complex *, complex *, integer *, complex *, 
00079             integer *, integer *), csrscl_(integer *, 
00080             real *, complex *, integer *), slaset_(char *, integer *, integer 
00081             *, real *, real *, real *, integer *), cunmlq_(char *, 
00082             char *, integer *, integer *, integer *, complex *, integer *, 
00083             complex *, complex *, integer *, complex *, integer *, integer *);
00084     integer ldwork;
00085     extern /* Subroutine */ int cunmqr_(char *, char *, integer *, integer *, 
00086             integer *, complex *, integer *, complex *, complex *, integer *, 
00087             complex *, integer *, integer *);
00088     integer minwrk, maxwrk;
00089     real smlnum;
00090     integer irwork;
00091     logical lquery;
00092 
00093 
00094 /*  -- LAPACK driver routine (version 3.2) -- */
00095 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00096 /*     November 2006 */
00097 
00098 /*     .. Scalar Arguments .. */
00099 /*     .. */
00100 /*     .. Array Arguments .. */
00101 /*     .. */
00102 
00103 /*  Purpose */
00104 /*  ======= */
00105 
00106 /*  CGELSS computes the minimum norm solution to a complex linear */
00107 /*  least squares problem: */
00108 
00109 /*  Minimize 2-norm(| b - A*x |). */
00110 
00111 /*  using the singular value decomposition (SVD) of A. A is an M-by-N */
00112 /*  matrix which may be rank-deficient. */
00113 
00114 /*  Several right hand side vectors b and solution vectors x can be */
00115 /*  handled in a single call; they are stored as the columns of the */
00116 /*  M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix */
00117 /*  X. */
00118 
00119 /*  The effective rank of A is determined by treating as zero those */
00120 /*  singular values which are less than RCOND times the largest singular */
00121 /*  value. */
00122 
00123 /*  Arguments */
00124 /*  ========= */
00125 
00126 /*  M       (input) INTEGER */
00127 /*          The number of rows of the matrix A. M >= 0. */
00128 
00129 /*  N       (input) INTEGER */
00130 /*          The number of columns of the matrix A. N >= 0. */
00131 
00132 /*  NRHS    (input) INTEGER */
00133 /*          The number of right hand sides, i.e., the number of columns */
00134 /*          of the matrices B and X. NRHS >= 0. */
00135 
00136 /*  A       (input/output) COMPLEX array, dimension (LDA,N) */
00137 /*          On entry, the M-by-N matrix A. */
00138 /*          On exit, the first min(m,n) rows of A are overwritten with */
00139 /*          its right singular vectors, stored rowwise. */
00140 
00141 /*  LDA     (input) INTEGER */
00142 /*          The leading dimension of the array A. LDA >= max(1,M). */
00143 
00144 /*  B       (input/output) COMPLEX array, dimension (LDB,NRHS) */
00145 /*          On entry, the M-by-NRHS right hand side matrix B. */
00146 /*          On exit, B is overwritten by the N-by-NRHS solution matrix X. */
00147 /*          If m >= n and RANK = n, the residual sum-of-squares for */
00148 /*          the solution in the i-th column is given by the sum of */
00149 /*          squares of the modulus of elements n+1:m in that column. */
00150 
00151 /*  LDB     (input) INTEGER */
00152 /*          The leading dimension of the array B.  LDB >= max(1,M,N). */
00153 
00154 /*  S       (output) REAL array, dimension (min(M,N)) */
00155 /*          The singular values of A in decreasing order. */
00156 /*          The condition number of A in the 2-norm = S(1)/S(min(m,n)). */
00157 
00158 /*  RCOND   (input) REAL */
00159 /*          RCOND is used to determine the effective rank of A. */
00160 /*          Singular values S(i) <= RCOND*S(1) are treated as zero. */
00161 /*          If RCOND < 0, machine precision is used instead. */
00162 
00163 /*  RANK    (output) INTEGER */
00164 /*          The effective rank of A, i.e., the number of singular values */
00165 /*          which are greater than RCOND*S(1). */
00166 
00167 /*  WORK    (workspace/output) COMPLEX array, dimension (MAX(1,LWORK)) */
00168 /*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
00169 
00170 /*  LWORK   (input) INTEGER */
00171 /*          The dimension of the array WORK. LWORK >= 1, and also: */
00172 /*          LWORK >=  2*min(M,N) + max(M,N,NRHS) */
00173 /*          For good performance, LWORK should generally be larger. */
00174 
00175 /*          If LWORK = -1, then a workspace query is assumed; the routine */
00176 /*          only calculates the optimal size of the WORK array, returns */
00177 /*          this value as the first entry of the WORK array, and no error */
00178 /*          message related to LWORK is issued by XERBLA. */
00179 
00180 /*  RWORK   (workspace) REAL array, dimension (5*min(M,N)) */
00181 
00182 /*  INFO    (output) INTEGER */
00183 /*          = 0:  successful exit */
00184 /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
00185 /*          > 0:  the algorithm for computing the SVD failed to converge; */
00186 /*                if INFO = i, i off-diagonal elements of an intermediate */
00187 /*                bidiagonal form did not converge to zero. */
00188 
00189 /*  ===================================================================== */
00190 
00191 /*     .. Parameters .. */
00192 /*     .. */
00193 /*     .. Local Scalars .. */
00194 /*     .. */
00195 /*     .. Local Arrays .. */
00196 /*     .. */
00197 /*     .. External Subroutines .. */
00198 /*     .. */
00199 /*     .. External Functions .. */
00200 /*     .. */
00201 /*     .. Intrinsic Functions .. */
00202 /*     .. */
00203 /*     .. Executable Statements .. */
00204 
00205 /*     Test the input arguments */
00206 
00207     /* Parameter adjustments */
00208     a_dim1 = *lda;
00209     a_offset = 1 + a_dim1;
00210     a -= a_offset;
00211     b_dim1 = *ldb;
00212     b_offset = 1 + b_dim1;
00213     b -= b_offset;
00214     --s;
00215     --work;
00216     --rwork;
00217 
00218     /* Function Body */
00219     *info = 0;
00220     minmn = min(*m,*n);
00221     maxmn = max(*m,*n);
00222     lquery = *lwork == -1;
00223     if (*m < 0) {
00224         *info = -1;
00225     } else if (*n < 0) {
00226         *info = -2;
00227     } else if (*nrhs < 0) {
00228         *info = -3;
00229     } else if (*lda < max(1,*m)) {
00230         *info = -5;
00231     } else if (*ldb < max(1,maxmn)) {
00232         *info = -7;
00233     }
00234 
00235 /*     Compute workspace */
00236 /*      (Note: Comments in the code beginning "Workspace:" describe the */
00237 /*       minimal amount of workspace needed at that point in the code, */
00238 /*       as well as the preferred amount for good performance. */
00239 /*       CWorkspace refers to complex workspace, and RWorkspace refers */
00240 /*       to real workspace. NB refers to the optimal block size for the */
00241 /*       immediately following subroutine, as returned by ILAENV.) */
00242 
00243     if (*info == 0) {
00244         minwrk = 1;
00245         maxwrk = 1;
00246         if (minmn > 0) {
00247             mm = *m;
00248             mnthr = ilaenv_(&c__6, "CGELSS", " ", m, n, nrhs, &c_n1);
00249             if (*m >= *n && *m >= mnthr) {
00250 
00251 /*              Path 1a - overdetermined, with many more rows than */
00252 /*                        columns */
00253 
00254                 mm = *n;
00255 /* Computing MAX */
00256                 i__1 = maxwrk, i__2 = *n + *n * ilaenv_(&c__1, "CGEQRF", 
00257                         " ", m, n, &c_n1, &c_n1);
00258                 maxwrk = max(i__1,i__2);
00259 /* Computing MAX */
00260                 i__1 = maxwrk, i__2 = *n + *nrhs * ilaenv_(&c__1, "CUNMQR", 
00261                         "LC", m, nrhs, n, &c_n1);
00262                 maxwrk = max(i__1,i__2);
00263             }
00264             if (*m >= *n) {
00265 
00266 /*              Path 1 - overdetermined or exactly determined */
00267 
00268 /* Computing MAX */
00269                 i__1 = maxwrk, i__2 = (*n << 1) + (mm + *n) * ilaenv_(&c__1, 
00270                         "CGEBRD", " ", &mm, n, &c_n1, &c_n1);
00271                 maxwrk = max(i__1,i__2);
00272 /* Computing MAX */
00273                 i__1 = maxwrk, i__2 = (*n << 1) + *nrhs * ilaenv_(&c__1, 
00274                         "CUNMBR", "QLC", &mm, nrhs, n, &c_n1);
00275                 maxwrk = max(i__1,i__2);
00276 /* Computing MAX */
00277                 i__1 = maxwrk, i__2 = (*n << 1) + (*n - 1) * ilaenv_(&c__1, 
00278                         "CUNGBR", "P", n, n, n, &c_n1);
00279                 maxwrk = max(i__1,i__2);
00280 /* Computing MAX */
00281                 i__1 = maxwrk, i__2 = *n * *nrhs;
00282                 maxwrk = max(i__1,i__2);
00283                 minwrk = (*n << 1) + max(*nrhs,*m);
00284             }
00285             if (*n > *m) {
00286                 minwrk = (*m << 1) + max(*nrhs,*n);
00287                 if (*n >= mnthr) {
00288 
00289 /*                 Path 2a - underdetermined, with many more columns */
00290 /*                 than rows */
00291 
00292                     maxwrk = *m + *m * ilaenv_(&c__1, "CGELQF", " ", m, n, &
00293                             c_n1, &c_n1);
00294 /* Computing MAX */
00295                     i__1 = maxwrk, i__2 = *m * 3 + *m * *m + (*m << 1) * 
00296                             ilaenv_(&c__1, "CGEBRD", " ", m, m, &c_n1, &c_n1);
00297                     maxwrk = max(i__1,i__2);
00298 /* Computing MAX */
00299                     i__1 = maxwrk, i__2 = *m * 3 + *m * *m + *nrhs * ilaenv_(&
00300                             c__1, "CUNMBR", "QLC", m, nrhs, m, &c_n1);
00301                     maxwrk = max(i__1,i__2);
00302 /* Computing MAX */
00303                     i__1 = maxwrk, i__2 = *m * 3 + *m * *m + (*m - 1) * 
00304                             ilaenv_(&c__1, "CUNGBR", "P", m, m, m, &c_n1);
00305                     maxwrk = max(i__1,i__2);
00306                     if (*nrhs > 1) {
00307 /* Computing MAX */
00308                         i__1 = maxwrk, i__2 = *m * *m + *m + *m * *nrhs;
00309                         maxwrk = max(i__1,i__2);
00310                     } else {
00311 /* Computing MAX */
00312                         i__1 = maxwrk, i__2 = *m * *m + (*m << 1);
00313                         maxwrk = max(i__1,i__2);
00314                     }
00315 /* Computing MAX */
00316                     i__1 = maxwrk, i__2 = *m + *nrhs * ilaenv_(&c__1, "CUNMLQ"
00317 , "LC", n, nrhs, m, &c_n1);
00318                     maxwrk = max(i__1,i__2);
00319                 } else {
00320 
00321 /*                 Path 2 - underdetermined */
00322 
00323                     maxwrk = (*m << 1) + (*n + *m) * ilaenv_(&c__1, "CGEBRD", 
00324                             " ", m, n, &c_n1, &c_n1);
00325 /* Computing MAX */
00326                     i__1 = maxwrk, i__2 = (*m << 1) + *nrhs * ilaenv_(&c__1, 
00327                             "CUNMBR", "QLC", m, nrhs, m, &c_n1);
00328                     maxwrk = max(i__1,i__2);
00329 /* Computing MAX */
00330                     i__1 = maxwrk, i__2 = (*m << 1) + *m * ilaenv_(&c__1, 
00331                             "CUNGBR", "P", m, n, m, &c_n1);
00332                     maxwrk = max(i__1,i__2);
00333 /* Computing MAX */
00334                     i__1 = maxwrk, i__2 = *n * *nrhs;
00335                     maxwrk = max(i__1,i__2);
00336                 }
00337             }
00338             maxwrk = max(minwrk,maxwrk);
00339         }
00340         work[1].r = (real) maxwrk, work[1].i = 0.f;
00341 
00342         if (*lwork < minwrk && ! lquery) {
00343             *info = -12;
00344         }
00345     }
00346 
00347     if (*info != 0) {
00348         i__1 = -(*info);
00349         xerbla_("CGELSS", &i__1);
00350         return 0;
00351     } else if (lquery) {
00352         return 0;
00353     }
00354 
00355 /*     Quick return if possible */
00356 
00357     if (*m == 0 || *n == 0) {
00358         *rank = 0;
00359         return 0;
00360     }
00361 
00362 /*     Get machine parameters */
00363 
00364     eps = slamch_("P");
00365     sfmin = slamch_("S");
00366     smlnum = sfmin / eps;
00367     bignum = 1.f / smlnum;
00368     slabad_(&smlnum, &bignum);
00369 
00370 /*     Scale A if max element outside range [SMLNUM,BIGNUM] */
00371 
00372     anrm = clange_("M", m, n, &a[a_offset], lda, &rwork[1]);
00373     iascl = 0;
00374     if (anrm > 0.f && anrm < smlnum) {
00375 
00376 /*        Scale matrix norm up to SMLNUM */
00377 
00378         clascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &a[a_offset], lda, 
00379                 info);
00380         iascl = 1;
00381     } else if (anrm > bignum) {
00382 
00383 /*        Scale matrix norm down to BIGNUM */
00384 
00385         clascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &a[a_offset], lda, 
00386                 info);
00387         iascl = 2;
00388     } else if (anrm == 0.f) {
00389 
00390 /*        Matrix all zero. Return zero solution. */
00391 
00392         i__1 = max(*m,*n);
00393         claset_("F", &i__1, nrhs, &c_b1, &c_b1, &b[b_offset], ldb);
00394         slaset_("F", &minmn, &c__1, &c_b78, &c_b78, &s[1], &minmn);
00395         *rank = 0;
00396         goto L70;
00397     }
00398 
00399 /*     Scale B if max element outside range [SMLNUM,BIGNUM] */
00400 
00401     bnrm = clange_("M", m, nrhs, &b[b_offset], ldb, &rwork[1]);
00402     ibscl = 0;
00403     if (bnrm > 0.f && bnrm < smlnum) {
00404 
00405 /*        Scale matrix norm up to SMLNUM */
00406 
00407         clascl_("G", &c__0, &c__0, &bnrm, &smlnum, m, nrhs, &b[b_offset], ldb, 
00408                  info);
00409         ibscl = 1;
00410     } else if (bnrm > bignum) {
00411 
00412 /*        Scale matrix norm down to BIGNUM */
00413 
00414         clascl_("G", &c__0, &c__0, &bnrm, &bignum, m, nrhs, &b[b_offset], ldb, 
00415                  info);
00416         ibscl = 2;
00417     }
00418 
00419 /*     Overdetermined case */
00420 
00421     if (*m >= *n) {
00422 
00423 /*        Path 1 - overdetermined or exactly determined */
00424 
00425         mm = *m;
00426         if (*m >= mnthr) {
00427 
00428 /*           Path 1a - overdetermined, with many more rows than columns */
00429 
00430             mm = *n;
00431             itau = 1;
00432             iwork = itau + *n;
00433 
00434 /*           Compute A=Q*R */
00435 /*           (CWorkspace: need 2*N, prefer N+N*NB) */
00436 /*           (RWorkspace: none) */
00437 
00438             i__1 = *lwork - iwork + 1;
00439             cgeqrf_(m, n, &a[a_offset], lda, &work[itau], &work[iwork], &i__1, 
00440                      info);
00441 
00442 /*           Multiply B by transpose(Q) */
00443 /*           (CWorkspace: need N+NRHS, prefer N+NRHS*NB) */
00444 /*           (RWorkspace: none) */
00445 
00446             i__1 = *lwork - iwork + 1;
00447             cunmqr_("L", "C", m, nrhs, n, &a[a_offset], lda, &work[itau], &b[
00448                     b_offset], ldb, &work[iwork], &i__1, info);
00449 
00450 /*           Zero out below R */
00451 
00452             if (*n > 1) {
00453                 i__1 = *n - 1;
00454                 i__2 = *n - 1;
00455                 claset_("L", &i__1, &i__2, &c_b1, &c_b1, &a[a_dim1 + 2], lda);
00456             }
00457         }
00458 
00459         ie = 1;
00460         itauq = 1;
00461         itaup = itauq + *n;
00462         iwork = itaup + *n;
00463 
00464 /*        Bidiagonalize R in A */
00465 /*        (CWorkspace: need 2*N+MM, prefer 2*N+(MM+N)*NB) */
00466 /*        (RWorkspace: need N) */
00467 
00468         i__1 = *lwork - iwork + 1;
00469         cgebrd_(&mm, n, &a[a_offset], lda, &s[1], &rwork[ie], &work[itauq], &
00470                 work[itaup], &work[iwork], &i__1, info);
00471 
00472 /*        Multiply B by transpose of left bidiagonalizing vectors of R */
00473 /*        (CWorkspace: need 2*N+NRHS, prefer 2*N+NRHS*NB) */
00474 /*        (RWorkspace: none) */
00475 
00476         i__1 = *lwork - iwork + 1;
00477         cunmbr_("Q", "L", "C", &mm, nrhs, n, &a[a_offset], lda, &work[itauq], 
00478                 &b[b_offset], ldb, &work[iwork], &i__1, info);
00479 
00480 /*        Generate right bidiagonalizing vectors of R in A */
00481 /*        (CWorkspace: need 3*N-1, prefer 2*N+(N-1)*NB) */
00482 /*        (RWorkspace: none) */
00483 
00484         i__1 = *lwork - iwork + 1;
00485         cungbr_("P", n, n, n, &a[a_offset], lda, &work[itaup], &work[iwork], &
00486                 i__1, info);
00487         irwork = ie + *n;
00488 
00489 /*        Perform bidiagonal QR iteration */
00490 /*          multiply B by transpose of left singular vectors */
00491 /*          compute right singular vectors in A */
00492 /*        (CWorkspace: none) */
00493 /*        (RWorkspace: need BDSPAC) */
00494 
00495         cbdsqr_("U", n, n, &c__0, nrhs, &s[1], &rwork[ie], &a[a_offset], lda, 
00496                 vdum, &c__1, &b[b_offset], ldb, &rwork[irwork], info);
00497         if (*info != 0) {
00498             goto L70;
00499         }
00500 
00501 /*        Multiply B by reciprocals of singular values */
00502 
00503 /* Computing MAX */
00504         r__1 = *rcond * s[1];
00505         thr = dmax(r__1,sfmin);
00506         if (*rcond < 0.f) {
00507 /* Computing MAX */
00508             r__1 = eps * s[1];
00509             thr = dmax(r__1,sfmin);
00510         }
00511         *rank = 0;
00512         i__1 = *n;
00513         for (i__ = 1; i__ <= i__1; ++i__) {
00514             if (s[i__] > thr) {
00515                 csrscl_(nrhs, &s[i__], &b[i__ + b_dim1], ldb);
00516                 ++(*rank);
00517             } else {
00518                 claset_("F", &c__1, nrhs, &c_b1, &c_b1, &b[i__ + b_dim1], ldb);
00519             }
00520 /* L10: */
00521         }
00522 
00523 /*        Multiply B by right singular vectors */
00524 /*        (CWorkspace: need N, prefer N*NRHS) */
00525 /*        (RWorkspace: none) */
00526 
00527         if (*lwork >= *ldb * *nrhs && *nrhs > 1) {
00528             cgemm_("C", "N", n, nrhs, n, &c_b2, &a[a_offset], lda, &b[
00529                     b_offset], ldb, &c_b1, &work[1], ldb);
00530             clacpy_("G", n, nrhs, &work[1], ldb, &b[b_offset], ldb)
00531                     ;
00532         } else if (*nrhs > 1) {
00533             chunk = *lwork / *n;
00534             i__1 = *nrhs;
00535             i__2 = chunk;
00536             for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) {
00537 /* Computing MIN */
00538                 i__3 = *nrhs - i__ + 1;
00539                 bl = min(i__3,chunk);
00540                 cgemm_("C", "N", n, &bl, n, &c_b2, &a[a_offset], lda, &b[i__ *
00541                          b_dim1 + 1], ldb, &c_b1, &work[1], n);
00542                 clacpy_("G", n, &bl, &work[1], n, &b[i__ * b_dim1 + 1], ldb);
00543 /* L20: */
00544             }
00545         } else {
00546             cgemv_("C", n, n, &c_b2, &a[a_offset], lda, &b[b_offset], &c__1, &
00547                     c_b1, &work[1], &c__1);
00548             ccopy_(n, &work[1], &c__1, &b[b_offset], &c__1);
00549         }
00550 
00551     } else /* if(complicated condition) */ {
00552 /* Computing MAX */
00553         i__2 = max(*m,*nrhs), i__1 = *n - (*m << 1);
00554         if (*n >= mnthr && *lwork >= *m * 3 + *m * *m + max(i__2,i__1)) {
00555 
00556 /*        Underdetermined case, M much less than N */
00557 
00558 /*        Path 2a - underdetermined, with many more columns than rows */
00559 /*        and sufficient workspace for an efficient algorithm */
00560 
00561             ldwork = *m;
00562 /* Computing MAX */
00563             i__2 = max(*m,*nrhs), i__1 = *n - (*m << 1);
00564             if (*lwork >= *m * 3 + *m * *lda + max(i__2,i__1)) {
00565                 ldwork = *lda;
00566             }
00567             itau = 1;
00568             iwork = *m + 1;
00569 
00570 /*        Compute A=L*Q */
00571 /*        (CWorkspace: need 2*M, prefer M+M*NB) */
00572 /*        (RWorkspace: none) */
00573 
00574             i__2 = *lwork - iwork + 1;
00575             cgelqf_(m, n, &a[a_offset], lda, &work[itau], &work[iwork], &i__2, 
00576                      info);
00577             il = iwork;
00578 
00579 /*        Copy L to WORK(IL), zeroing out above it */
00580 
00581             clacpy_("L", m, m, &a[a_offset], lda, &work[il], &ldwork);
00582             i__2 = *m - 1;
00583             i__1 = *m - 1;
00584             claset_("U", &i__2, &i__1, &c_b1, &c_b1, &work[il + ldwork], &
00585                     ldwork);
00586             ie = 1;
00587             itauq = il + ldwork * *m;
00588             itaup = itauq + *m;
00589             iwork = itaup + *m;
00590 
00591 /*        Bidiagonalize L in WORK(IL) */
00592 /*        (CWorkspace: need M*M+4*M, prefer M*M+3*M+2*M*NB) */
00593 /*        (RWorkspace: need M) */
00594 
00595             i__2 = *lwork - iwork + 1;
00596             cgebrd_(m, m, &work[il], &ldwork, &s[1], &rwork[ie], &work[itauq], 
00597                      &work[itaup], &work[iwork], &i__2, info);
00598 
00599 /*        Multiply B by transpose of left bidiagonalizing vectors of L */
00600 /*        (CWorkspace: need M*M+3*M+NRHS, prefer M*M+3*M+NRHS*NB) */
00601 /*        (RWorkspace: none) */
00602 
00603             i__2 = *lwork - iwork + 1;
00604             cunmbr_("Q", "L", "C", m, nrhs, m, &work[il], &ldwork, &work[
00605                     itauq], &b[b_offset], ldb, &work[iwork], &i__2, info);
00606 
00607 /*        Generate right bidiagonalizing vectors of R in WORK(IL) */
00608 /*        (CWorkspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB) */
00609 /*        (RWorkspace: none) */
00610 
00611             i__2 = *lwork - iwork + 1;
00612             cungbr_("P", m, m, m, &work[il], &ldwork, &work[itaup], &work[
00613                     iwork], &i__2, info);
00614             irwork = ie + *m;
00615 
00616 /*        Perform bidiagonal QR iteration, computing right singular */
00617 /*        vectors of L in WORK(IL) and multiplying B by transpose of */
00618 /*        left singular vectors */
00619 /*        (CWorkspace: need M*M) */
00620 /*        (RWorkspace: need BDSPAC) */
00621 
00622             cbdsqr_("U", m, m, &c__0, nrhs, &s[1], &rwork[ie], &work[il], &
00623                     ldwork, &a[a_offset], lda, &b[b_offset], ldb, &rwork[
00624                     irwork], info);
00625             if (*info != 0) {
00626                 goto L70;
00627             }
00628 
00629 /*        Multiply B by reciprocals of singular values */
00630 
00631 /* Computing MAX */
00632             r__1 = *rcond * s[1];
00633             thr = dmax(r__1,sfmin);
00634             if (*rcond < 0.f) {
00635 /* Computing MAX */
00636                 r__1 = eps * s[1];
00637                 thr = dmax(r__1,sfmin);
00638             }
00639             *rank = 0;
00640             i__2 = *m;
00641             for (i__ = 1; i__ <= i__2; ++i__) {
00642                 if (s[i__] > thr) {
00643                     csrscl_(nrhs, &s[i__], &b[i__ + b_dim1], ldb);
00644                     ++(*rank);
00645                 } else {
00646                     claset_("F", &c__1, nrhs, &c_b1, &c_b1, &b[i__ + b_dim1], 
00647                             ldb);
00648                 }
00649 /* L30: */
00650             }
00651             iwork = il + *m * ldwork;
00652 
00653 /*        Multiply B by right singular vectors of L in WORK(IL) */
00654 /*        (CWorkspace: need M*M+2*M, prefer M*M+M+M*NRHS) */
00655 /*        (RWorkspace: none) */
00656 
00657             if (*lwork >= *ldb * *nrhs + iwork - 1 && *nrhs > 1) {
00658                 cgemm_("C", "N", m, nrhs, m, &c_b2, &work[il], &ldwork, &b[
00659                         b_offset], ldb, &c_b1, &work[iwork], ldb);
00660                 clacpy_("G", m, nrhs, &work[iwork], ldb, &b[b_offset], ldb);
00661             } else if (*nrhs > 1) {
00662                 chunk = (*lwork - iwork + 1) / *m;
00663                 i__2 = *nrhs;
00664                 i__1 = chunk;
00665                 for (i__ = 1; i__1 < 0 ? i__ >= i__2 : i__ <= i__2; i__ += 
00666                         i__1) {
00667 /* Computing MIN */
00668                     i__3 = *nrhs - i__ + 1;
00669                     bl = min(i__3,chunk);
00670                     cgemm_("C", "N", m, &bl, m, &c_b2, &work[il], &ldwork, &b[
00671                             i__ * b_dim1 + 1], ldb, &c_b1, &work[iwork], m);
00672                     clacpy_("G", m, &bl, &work[iwork], m, &b[i__ * b_dim1 + 1]
00673 , ldb);
00674 /* L40: */
00675                 }
00676             } else {
00677                 cgemv_("C", m, m, &c_b2, &work[il], &ldwork, &b[b_dim1 + 1], &
00678                         c__1, &c_b1, &work[iwork], &c__1);
00679                 ccopy_(m, &work[iwork], &c__1, &b[b_dim1 + 1], &c__1);
00680             }
00681 
00682 /*        Zero out below first M rows of B */
00683 
00684             i__1 = *n - *m;
00685             claset_("F", &i__1, nrhs, &c_b1, &c_b1, &b[*m + 1 + b_dim1], ldb);
00686             iwork = itau + *m;
00687 
00688 /*        Multiply transpose(Q) by B */
00689 /*        (CWorkspace: need M+NRHS, prefer M+NHRS*NB) */
00690 /*        (RWorkspace: none) */
00691 
00692             i__1 = *lwork - iwork + 1;
00693             cunmlq_("L", "C", n, nrhs, m, &a[a_offset], lda, &work[itau], &b[
00694                     b_offset], ldb, &work[iwork], &i__1, info);
00695 
00696         } else {
00697 
00698 /*        Path 2 - remaining underdetermined cases */
00699 
00700             ie = 1;
00701             itauq = 1;
00702             itaup = itauq + *m;
00703             iwork = itaup + *m;
00704 
00705 /*        Bidiagonalize A */
00706 /*        (CWorkspace: need 3*M, prefer 2*M+(M+N)*NB) */
00707 /*        (RWorkspace: need N) */
00708 
00709             i__1 = *lwork - iwork + 1;
00710             cgebrd_(m, n, &a[a_offset], lda, &s[1], &rwork[ie], &work[itauq], 
00711                     &work[itaup], &work[iwork], &i__1, info);
00712 
00713 /*        Multiply B by transpose of left bidiagonalizing vectors */
00714 /*        (CWorkspace: need 2*M+NRHS, prefer 2*M+NRHS*NB) */
00715 /*        (RWorkspace: none) */
00716 
00717             i__1 = *lwork - iwork + 1;
00718             cunmbr_("Q", "L", "C", m, nrhs, n, &a[a_offset], lda, &work[itauq]
00719 , &b[b_offset], ldb, &work[iwork], &i__1, info);
00720 
00721 /*        Generate right bidiagonalizing vectors in A */
00722 /*        (CWorkspace: need 3*M, prefer 2*M+M*NB) */
00723 /*        (RWorkspace: none) */
00724 
00725             i__1 = *lwork - iwork + 1;
00726             cungbr_("P", m, n, m, &a[a_offset], lda, &work[itaup], &work[
00727                     iwork], &i__1, info);
00728             irwork = ie + *m;
00729 
00730 /*        Perform bidiagonal QR iteration, */
00731 /*           computing right singular vectors of A in A and */
00732 /*           multiplying B by transpose of left singular vectors */
00733 /*        (CWorkspace: none) */
00734 /*        (RWorkspace: need BDSPAC) */
00735 
00736             cbdsqr_("L", m, n, &c__0, nrhs, &s[1], &rwork[ie], &a[a_offset], 
00737                     lda, vdum, &c__1, &b[b_offset], ldb, &rwork[irwork], info);
00738             if (*info != 0) {
00739                 goto L70;
00740             }
00741 
00742 /*        Multiply B by reciprocals of singular values */
00743 
00744 /* Computing MAX */
00745             r__1 = *rcond * s[1];
00746             thr = dmax(r__1,sfmin);
00747             if (*rcond < 0.f) {
00748 /* Computing MAX */
00749                 r__1 = eps * s[1];
00750                 thr = dmax(r__1,sfmin);
00751             }
00752             *rank = 0;
00753             i__1 = *m;
00754             for (i__ = 1; i__ <= i__1; ++i__) {
00755                 if (s[i__] > thr) {
00756                     csrscl_(nrhs, &s[i__], &b[i__ + b_dim1], ldb);
00757                     ++(*rank);
00758                 } else {
00759                     claset_("F", &c__1, nrhs, &c_b1, &c_b1, &b[i__ + b_dim1], 
00760                             ldb);
00761                 }
00762 /* L50: */
00763             }
00764 
00765 /*        Multiply B by right singular vectors of A */
00766 /*        (CWorkspace: need N, prefer N*NRHS) */
00767 /*        (RWorkspace: none) */
00768 
00769             if (*lwork >= *ldb * *nrhs && *nrhs > 1) {
00770                 cgemm_("C", "N", n, nrhs, m, &c_b2, &a[a_offset], lda, &b[
00771                         b_offset], ldb, &c_b1, &work[1], ldb);
00772                 clacpy_("G", n, nrhs, &work[1], ldb, &b[b_offset], ldb);
00773             } else if (*nrhs > 1) {
00774                 chunk = *lwork / *n;
00775                 i__1 = *nrhs;
00776                 i__2 = chunk;
00777                 for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += 
00778                         i__2) {
00779 /* Computing MIN */
00780                     i__3 = *nrhs - i__ + 1;
00781                     bl = min(i__3,chunk);
00782                     cgemm_("C", "N", n, &bl, m, &c_b2, &a[a_offset], lda, &b[
00783                             i__ * b_dim1 + 1], ldb, &c_b1, &work[1], n);
00784                     clacpy_("F", n, &bl, &work[1], n, &b[i__ * b_dim1 + 1], 
00785                             ldb);
00786 /* L60: */
00787                 }
00788             } else {
00789                 cgemv_("C", m, n, &c_b2, &a[a_offset], lda, &b[b_offset], &
00790                         c__1, &c_b1, &work[1], &c__1);
00791                 ccopy_(n, &work[1], &c__1, &b[b_offset], &c__1);
00792             }
00793         }
00794     }
00795 
00796 /*     Undo scaling */
00797 
00798     if (iascl == 1) {
00799         clascl_("G", &c__0, &c__0, &anrm, &smlnum, n, nrhs, &b[b_offset], ldb, 
00800                  info);
00801         slascl_("G", &c__0, &c__0, &smlnum, &anrm, &minmn, &c__1, &s[1], &
00802                 minmn, info);
00803     } else if (iascl == 2) {
00804         clascl_("G", &c__0, &c__0, &anrm, &bignum, n, nrhs, &b[b_offset], ldb, 
00805                  info);
00806         slascl_("G", &c__0, &c__0, &bignum, &anrm, &minmn, &c__1, &s[1], &
00807                 minmn, info);
00808     }
00809     if (ibscl == 1) {
00810         clascl_("G", &c__0, &c__0, &smlnum, &bnrm, n, nrhs, &b[b_offset], ldb, 
00811                  info);
00812     } else if (ibscl == 2) {
00813         clascl_("G", &c__0, &c__0, &bignum, &bnrm, n, nrhs, &b[b_offset], ldb, 
00814                  info);
00815     }
00816 L70:
00817     work[1].r = (real) maxwrk, work[1].i = 0.f;
00818     return 0;
00819 
00820 /*     End of CGELSS */
00821 
00822 } /* cgelss_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:26