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


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:32