cgelsd.c
Go to the documentation of this file.
00001 /* cgelsd.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 integer c__9 = 9;
00020 static integer c__0 = 0;
00021 static integer c__6 = 6;
00022 static integer c_n1 = -1;
00023 static integer c__1 = 1;
00024 static real c_b80 = 0.f;
00025 
00026 /* Subroutine */ int cgelsd_(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         iwork, integer *info)
00030 {
00031     /* System generated locals */
00032     integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3, i__4;
00033 
00034     /* Builtin functions */
00035     double log(doublereal);
00036 
00037     /* Local variables */
00038     integer ie, il, mm;
00039     real eps, anrm, bnrm;
00040     integer itau, nlvl, iascl, ibscl;
00041     real sfmin;
00042     integer minmn, maxmn, itaup, itauq, mnthr, nwork;
00043     extern /* Subroutine */ int cgebrd_(integer *, integer *, complex *, 
00044             integer *, real *, real *, complex *, complex *, complex *, 
00045             integer *, integer *), slabad_(real *, real *);
00046     extern doublereal clange_(char *, integer *, integer *, complex *, 
00047             integer *, real *);
00048     extern /* Subroutine */ int cgelqf_(integer *, integer *, complex *, 
00049             integer *, complex *, complex *, integer *, integer *), clalsd_(
00050             char *, integer *, integer *, integer *, real *, real *, complex *
00051 , integer *, real *, integer *, complex *, real *, integer *, 
00052             integer *), clascl_(char *, integer *, integer *, real *, 
00053             real *, integer *, integer *, complex *, integer *, integer *), cgeqrf_(integer *, integer *, complex *, integer *, 
00054             complex *, complex *, integer *, integer *);
00055     extern doublereal slamch_(char *);
00056     extern /* Subroutine */ int clacpy_(char *, integer *, integer *, complex 
00057             *, integer *, complex *, integer *), claset_(char *, 
00058             integer *, integer *, complex *, complex *, complex *, integer *), xerbla_(char *, integer *);
00059     extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
00060             integer *, integer *);
00061     real bignum;
00062     extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, 
00063             real *, integer *, integer *, real *, integer *, integer *), cunmbr_(char *, char *, char *, integer *, integer *, 
00064             integer *, complex *, integer *, complex *, complex *, integer *, 
00065             complex *, integer *, integer *), slaset_(
00066             char *, integer *, integer *, real *, real *, real *, integer *), cunmlq_(char *, char *, integer *, integer *, integer *, 
00067             complex *, integer *, complex *, complex *, integer *, complex *, 
00068             integer *, integer *);
00069     integer ldwork;
00070     extern /* Subroutine */ int cunmqr_(char *, char *, integer *, integer *, 
00071             integer *, complex *, integer *, complex *, complex *, integer *, 
00072             complex *, integer *, integer *);
00073     integer liwork, minwrk, maxwrk;
00074     real smlnum;
00075     integer lrwork;
00076     logical lquery;
00077     integer nrwork, smlsiz;
00078 
00079 
00080 /*  -- LAPACK driver routine (version 3.2) -- */
00081 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00082 /*     November 2006 */
00083 
00084 /*     .. Scalar Arguments .. */
00085 /*     .. */
00086 /*     .. Array Arguments .. */
00087 /*     .. */
00088 
00089 /*  Purpose */
00090 /*  ======= */
00091 
00092 /*  CGELSD computes the minimum-norm solution to a real linear least */
00093 /*  squares problem: */
00094 /*      minimize 2-norm(| b - A*x |) */
00095 /*  using the singular value decomposition (SVD) of A. A is an M-by-N */
00096 /*  matrix which may be rank-deficient. */
00097 
00098 /*  Several right hand side vectors b and solution vectors x can be */
00099 /*  handled in a single call; they are stored as the columns of the */
00100 /*  M-by-NRHS right hand side matrix B and the N-by-NRHS solution */
00101 /*  matrix X. */
00102 
00103 /*  The problem is solved in three steps: */
00104 /*  (1) Reduce the coefficient matrix A to bidiagonal form with */
00105 /*      Householder tranformations, reducing the original problem */
00106 /*      into a "bidiagonal least squares problem" (BLS) */
00107 /*  (2) Solve the BLS using a divide and conquer approach. */
00108 /*  (3) Apply back all the Householder tranformations to solve */
00109 /*      the original least squares problem. */
00110 
00111 /*  The effective rank of A is determined by treating as zero those */
00112 /*  singular values which are less than RCOND times the largest singular */
00113 /*  value. */
00114 
00115 /*  The divide and conquer algorithm makes very mild assumptions about */
00116 /*  floating point arithmetic. It will work on machines with a guard */
00117 /*  digit in add/subtract, or on those binary machines without guard */
00118 /*  digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or */
00119 /*  Cray-2. It could conceivably fail on hexadecimal or decimal machines */
00120 /*  without guard digits, but we know of none. */
00121 
00122 /*  Arguments */
00123 /*  ========= */
00124 
00125 /*  M       (input) INTEGER */
00126 /*          The number of rows of the matrix A. M >= 0. */
00127 
00128 /*  N       (input) INTEGER */
00129 /*          The number of columns of the matrix A. N >= 0. */
00130 
00131 /*  NRHS    (input) INTEGER */
00132 /*          The number of right hand sides, i.e., the number of columns */
00133 /*          of the matrices B and X. NRHS >= 0. */
00134 
00135 /*  A       (input/output) COMPLEX array, dimension (LDA,N) */
00136 /*          On entry, the M-by-N matrix A. */
00137 /*          On exit, A has been destroyed. */
00138 
00139 /*  LDA     (input) INTEGER */
00140 /*          The leading dimension of the array A. LDA >= max(1,M). */
00141 
00142 /*  B       (input/output) COMPLEX array, dimension (LDB,NRHS) */
00143 /*          On entry, the M-by-NRHS right hand side matrix B. */
00144 /*          On exit, B is overwritten by the N-by-NRHS solution matrix X. */
00145 /*          If m >= n and RANK = n, the residual sum-of-squares for */
00146 /*          the solution in the i-th column is given by the sum of */
00147 /*          squares of the modulus of elements n+1:m in that column. */
00148 
00149 /*  LDB     (input) INTEGER */
00150 /*          The leading dimension of the array B.  LDB >= max(1,M,N). */
00151 
00152 /*  S       (output) REAL array, dimension (min(M,N)) */
00153 /*          The singular values of A in decreasing order. */
00154 /*          The condition number of A in the 2-norm = S(1)/S(min(m,n)). */
00155 
00156 /*  RCOND   (input) REAL */
00157 /*          RCOND is used to determine the effective rank of A. */
00158 /*          Singular values S(i) <= RCOND*S(1) are treated as zero. */
00159 /*          If RCOND < 0, machine precision is used instead. */
00160 
00161 /*  RANK    (output) INTEGER */
00162 /*          The effective rank of A, i.e., the number of singular values */
00163 /*          which are greater than RCOND*S(1). */
00164 
00165 /*  WORK    (workspace/output) COMPLEX array, dimension (MAX(1,LWORK)) */
00166 /*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
00167 
00168 /*  LWORK   (input) INTEGER */
00169 /*          The dimension of the array WORK. LWORK must be at least 1. */
00170 /*          The exact minimum amount of workspace needed depends on M, */
00171 /*          N and NRHS. As long as LWORK is at least */
00172 /*              2 * N + N * NRHS */
00173 /*          if M is greater than or equal to N or */
00174 /*              2 * M + M * NRHS */
00175 /*          if M is less than N, the code will execute correctly. */
00176 /*          For good performance, LWORK should generally be larger. */
00177 
00178 /*          If LWORK = -1, then a workspace query is assumed; the routine */
00179 /*          only calculates the optimal size of the array WORK and the */
00180 /*          minimum sizes of the arrays RWORK and IWORK, and returns */
00181 /*          these values as the first entries of the WORK, RWORK and */
00182 /*          IWORK arrays, and no error message related to LWORK is issued */
00183 /*          by XERBLA. */
00184 
00185 /*  RWORK   (workspace) REAL array, dimension (MAX(1,LRWORK)) */
00186 /*          LRWORK >= */
00187 /*             10*N + 2*N*SMLSIZ + 8*N*NLVL + 3*SMLSIZ*NRHS + */
00188 /*             (SMLSIZ+1)**2 */
00189 /*          if M is greater than or equal to N or */
00190 /*             10*M + 2*M*SMLSIZ + 8*M*NLVL + 3*SMLSIZ*NRHS + */
00191 /*             (SMLSIZ+1)**2 */
00192 /*          if M is less than N, the code will execute correctly. */
00193 /*          SMLSIZ is returned by ILAENV and is equal to the maximum */
00194 /*          size of the subproblems at the bottom of the computation */
00195 /*          tree (usually about 25), and */
00196 /*             NLVL = MAX( 0, INT( LOG_2( MIN( M,N )/(SMLSIZ+1) ) ) + 1 ) */
00197 /*          On exit, if INFO = 0, RWORK(1) returns the minimum LRWORK. */
00198 
00199 /*  IWORK   (workspace) INTEGER array, dimension (MAX(1,LIWORK)) */
00200 /*          LIWORK >= max(1, 3*MINMN*NLVL + 11*MINMN), */
00201 /*          where MINMN = MIN( M,N ). */
00202 /*          On exit, if INFO = 0, IWORK(1) returns the minimum LIWORK. */
00203 
00204 /*  INFO    (output) INTEGER */
00205 /*          = 0: successful exit */
00206 /*          < 0: if INFO = -i, the i-th argument had an illegal value. */
00207 /*          > 0:  the algorithm for computing the SVD failed to converge; */
00208 /*                if INFO = i, i off-diagonal elements of an intermediate */
00209 /*                bidiagonal form did not converge to zero. */
00210 
00211 /*  Further Details */
00212 /*  =============== */
00213 
00214 /*  Based on contributions by */
00215 /*     Ming Gu and Ren-Cang Li, Computer Science Division, University of */
00216 /*       California at Berkeley, USA */
00217 /*     Osni Marques, LBNL/NERSC, USA */
00218 
00219 /*  ===================================================================== */
00220 
00221 /*     .. Parameters .. */
00222 /*     .. */
00223 /*     .. Local Scalars .. */
00224 /*     .. */
00225 /*     .. External Subroutines .. */
00226 /*     .. */
00227 /*     .. External Functions .. */
00228 /*     .. */
00229 /*     .. Intrinsic Functions .. */
00230 /*     .. */
00231 /*     .. Executable Statements .. */
00232 
00233 /*     Test the input arguments. */
00234 
00235     /* Parameter adjustments */
00236     a_dim1 = *lda;
00237     a_offset = 1 + a_dim1;
00238     a -= a_offset;
00239     b_dim1 = *ldb;
00240     b_offset = 1 + b_dim1;
00241     b -= b_offset;
00242     --s;
00243     --work;
00244     --rwork;
00245     --iwork;
00246 
00247     /* Function Body */
00248     *info = 0;
00249     minmn = min(*m,*n);
00250     maxmn = max(*m,*n);
00251     lquery = *lwork == -1;
00252     if (*m < 0) {
00253         *info = -1;
00254     } else if (*n < 0) {
00255         *info = -2;
00256     } else if (*nrhs < 0) {
00257         *info = -3;
00258     } else if (*lda < max(1,*m)) {
00259         *info = -5;
00260     } else if (*ldb < max(1,maxmn)) {
00261         *info = -7;
00262     }
00263 
00264 /*     Compute workspace. */
00265 /*     (Note: Comments in the code beginning "Workspace:" describe the */
00266 /*     minimal amount of workspace needed at that point in the code, */
00267 /*     as well as the preferred amount for good performance. */
00268 /*     NB refers to the optimal block size for the immediately */
00269 /*     following subroutine, as returned by ILAENV.) */
00270 
00271     if (*info == 0) {
00272         minwrk = 1;
00273         maxwrk = 1;
00274         liwork = 1;
00275         lrwork = 1;
00276         if (minmn > 0) {
00277             smlsiz = ilaenv_(&c__9, "CGELSD", " ", &c__0, &c__0, &c__0, &c__0);
00278             mnthr = ilaenv_(&c__6, "CGELSD", " ", m, n, nrhs, &c_n1);
00279 /* Computing MAX */
00280             i__1 = (integer) (log((real) minmn / (real) (smlsiz + 1)) / log(
00281                     2.f)) + 1;
00282             nlvl = max(i__1,0);
00283             liwork = minmn * 3 * nlvl + minmn * 11;
00284             mm = *m;
00285             if (*m >= *n && *m >= mnthr) {
00286 
00287 /*              Path 1a - overdetermined, with many more rows than */
00288 /*                        columns. */
00289 
00290                 mm = *n;
00291 /* Computing MAX */
00292                 i__1 = maxwrk, i__2 = *n * ilaenv_(&c__1, "CGEQRF", " ", m, n, 
00293                          &c_n1, &c_n1);
00294                 maxwrk = max(i__1,i__2);
00295 /* Computing MAX */
00296                 i__1 = maxwrk, i__2 = *nrhs * ilaenv_(&c__1, "CUNMQR", "LC", 
00297                         m, nrhs, n, &c_n1);
00298                 maxwrk = max(i__1,i__2);
00299             }
00300             if (*m >= *n) {
00301 
00302 /*              Path 1 - overdetermined or exactly determined. */
00303 
00304 /* Computing 2nd power */
00305                 i__1 = smlsiz + 1;
00306                 lrwork = *n * 10 + (*n << 1) * smlsiz + (*n << 3) * nlvl + 
00307                         smlsiz * 3 * *nrhs + i__1 * i__1;
00308 /* Computing MAX */
00309                 i__1 = maxwrk, i__2 = (*n << 1) + (mm + *n) * ilaenv_(&c__1, 
00310                         "CGEBRD", " ", &mm, n, &c_n1, &c_n1);
00311                 maxwrk = max(i__1,i__2);
00312 /* Computing MAX */
00313                 i__1 = maxwrk, i__2 = (*n << 1) + *nrhs * ilaenv_(&c__1, 
00314                         "CUNMBR", "QLC", &mm, nrhs, n, &c_n1);
00315                 maxwrk = max(i__1,i__2);
00316 /* Computing MAX */
00317                 i__1 = maxwrk, i__2 = (*n << 1) + (*n - 1) * ilaenv_(&c__1, 
00318                         "CUNMBR", "PLN", n, nrhs, n, &c_n1);
00319                 maxwrk = max(i__1,i__2);
00320 /* Computing MAX */
00321                 i__1 = maxwrk, i__2 = (*n << 1) + *n * *nrhs;
00322                 maxwrk = max(i__1,i__2);
00323 /* Computing MAX */
00324                 i__1 = (*n << 1) + mm, i__2 = (*n << 1) + *n * *nrhs;
00325                 minwrk = max(i__1,i__2);
00326             }
00327             if (*n > *m) {
00328 /* Computing 2nd power */
00329                 i__1 = smlsiz + 1;
00330                 lrwork = *m * 10 + (*m << 1) * smlsiz + (*m << 3) * nlvl + 
00331                         smlsiz * 3 * *nrhs + i__1 * i__1;
00332                 if (*n >= mnthr) {
00333 
00334 /*                 Path 2a - underdetermined, with many more columns */
00335 /*                           than rows. */
00336 
00337                     maxwrk = *m + *m * ilaenv_(&c__1, "CGELQF", " ", m, n, &
00338                             c_n1, &c_n1);
00339 /* Computing MAX */
00340                     i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m << 1) * 
00341                             ilaenv_(&c__1, "CGEBRD", " ", m, m, &c_n1, &c_n1);
00342                     maxwrk = max(i__1,i__2);
00343 /* Computing MAX */
00344                     i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + *nrhs * 
00345                             ilaenv_(&c__1, "CUNMBR", "QLC", m, nrhs, m, &c_n1);
00346                     maxwrk = max(i__1,i__2);
00347 /* Computing MAX */
00348                     i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m - 1) * 
00349                             ilaenv_(&c__1, "CUNMLQ", "LC", n, nrhs, m, &c_n1);
00350                     maxwrk = max(i__1,i__2);
00351                     if (*nrhs > 1) {
00352 /* Computing MAX */
00353                         i__1 = maxwrk, i__2 = *m * *m + *m + *m * *nrhs;
00354                         maxwrk = max(i__1,i__2);
00355                     } else {
00356 /* Computing MAX */
00357                         i__1 = maxwrk, i__2 = *m * *m + (*m << 1);
00358                         maxwrk = max(i__1,i__2);
00359                     }
00360 /* Computing MAX */
00361                     i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + *m * *nrhs;
00362                     maxwrk = max(i__1,i__2);
00363 /*     XXX: Ensure the Path 2a case below is triggered.  The workspace */
00364 /*     calculation should use queries for all routines eventually. */
00365 /* Computing MAX */
00366 /* Computing MAX */
00367                     i__3 = *m, i__4 = (*m << 1) - 4, i__3 = max(i__3,i__4), 
00368                             i__3 = max(i__3,*nrhs), i__4 = *n - *m * 3;
00369                     i__1 = maxwrk, i__2 = (*m << 2) + *m * *m + max(i__3,i__4)
00370                             ;
00371                     maxwrk = max(i__1,i__2);
00372                 } else {
00373 
00374 /*                 Path 2 - underdetermined. */
00375 
00376                     maxwrk = (*m << 1) + (*n + *m) * ilaenv_(&c__1, "CGEBRD", 
00377                             " ", m, n, &c_n1, &c_n1);
00378 /* Computing MAX */
00379                     i__1 = maxwrk, i__2 = (*m << 1) + *nrhs * ilaenv_(&c__1, 
00380                             "CUNMBR", "QLC", m, nrhs, m, &c_n1);
00381                     maxwrk = max(i__1,i__2);
00382 /* Computing MAX */
00383                     i__1 = maxwrk, i__2 = (*m << 1) + *m * ilaenv_(&c__1, 
00384                             "CUNMBR", "PLN", n, nrhs, m, &c_n1);
00385                     maxwrk = max(i__1,i__2);
00386 /* Computing MAX */
00387                     i__1 = maxwrk, i__2 = (*m << 1) + *m * *nrhs;
00388                     maxwrk = max(i__1,i__2);
00389                 }
00390 /* Computing MAX */
00391                 i__1 = (*m << 1) + *n, i__2 = (*m << 1) + *m * *nrhs;
00392                 minwrk = max(i__1,i__2);
00393             }
00394         }
00395         minwrk = min(minwrk,maxwrk);
00396         work[1].r = (real) maxwrk, work[1].i = 0.f;
00397         iwork[1] = liwork;
00398         rwork[1] = (real) lrwork;
00399 
00400         if (*lwork < minwrk && ! lquery) {
00401             *info = -12;
00402         }
00403     }
00404 
00405     if (*info != 0) {
00406         i__1 = -(*info);
00407         xerbla_("CGELSD", &i__1);
00408         return 0;
00409     } else if (lquery) {
00410         return 0;
00411     }
00412 
00413 /*     Quick return if possible. */
00414 
00415     if (*m == 0 || *n == 0) {
00416         *rank = 0;
00417         return 0;
00418     }
00419 
00420 /*     Get machine parameters. */
00421 
00422     eps = slamch_("P");
00423     sfmin = slamch_("S");
00424     smlnum = sfmin / eps;
00425     bignum = 1.f / smlnum;
00426     slabad_(&smlnum, &bignum);
00427 
00428 /*     Scale A if max entry outside range [SMLNUM,BIGNUM]. */
00429 
00430     anrm = clange_("M", m, n, &a[a_offset], lda, &rwork[1]);
00431     iascl = 0;
00432     if (anrm > 0.f && anrm < smlnum) {
00433 
00434 /*        Scale matrix norm up to SMLNUM */
00435 
00436         clascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &a[a_offset], lda, 
00437                 info);
00438         iascl = 1;
00439     } else if (anrm > bignum) {
00440 
00441 /*        Scale matrix norm down to BIGNUM. */
00442 
00443         clascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &a[a_offset], lda, 
00444                 info);
00445         iascl = 2;
00446     } else if (anrm == 0.f) {
00447 
00448 /*        Matrix all zero. Return zero solution. */
00449 
00450         i__1 = max(*m,*n);
00451         claset_("F", &i__1, nrhs, &c_b1, &c_b1, &b[b_offset], ldb);
00452         slaset_("F", &minmn, &c__1, &c_b80, &c_b80, &s[1], &c__1);
00453         *rank = 0;
00454         goto L10;
00455     }
00456 
00457 /*     Scale B if max entry outside range [SMLNUM,BIGNUM]. */
00458 
00459     bnrm = clange_("M", m, nrhs, &b[b_offset], ldb, &rwork[1]);
00460     ibscl = 0;
00461     if (bnrm > 0.f && bnrm < smlnum) {
00462 
00463 /*        Scale matrix norm up to SMLNUM. */
00464 
00465         clascl_("G", &c__0, &c__0, &bnrm, &smlnum, m, nrhs, &b[b_offset], ldb, 
00466                  info);
00467         ibscl = 1;
00468     } else if (bnrm > bignum) {
00469 
00470 /*        Scale matrix norm down to BIGNUM. */
00471 
00472         clascl_("G", &c__0, &c__0, &bnrm, &bignum, m, nrhs, &b[b_offset], ldb, 
00473                  info);
00474         ibscl = 2;
00475     }
00476 
00477 /*     If M < N make sure B(M+1:N,:) = 0 */
00478 
00479     if (*m < *n) {
00480         i__1 = *n - *m;
00481         claset_("F", &i__1, nrhs, &c_b1, &c_b1, &b[*m + 1 + b_dim1], ldb);
00482     }
00483 
00484 /*     Overdetermined case. */
00485 
00486     if (*m >= *n) {
00487 
00488 /*        Path 1 - overdetermined or exactly determined. */
00489 
00490         mm = *m;
00491         if (*m >= mnthr) {
00492 
00493 /*           Path 1a - overdetermined, with many more rows than columns */
00494 
00495             mm = *n;
00496             itau = 1;
00497             nwork = itau + *n;
00498 
00499 /*           Compute A=Q*R. */
00500 /*           (RWorkspace: need N) */
00501 /*           (CWorkspace: need N, prefer N*NB) */
00502 
00503             i__1 = *lwork - nwork + 1;
00504             cgeqrf_(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &i__1, 
00505                      info);
00506 
00507 /*           Multiply B by transpose(Q). */
00508 /*           (RWorkspace: need N) */
00509 /*           (CWorkspace: need NRHS, prefer NRHS*NB) */
00510 
00511             i__1 = *lwork - nwork + 1;
00512             cunmqr_("L", "C", m, nrhs, n, &a[a_offset], lda, &work[itau], &b[
00513                     b_offset], ldb, &work[nwork], &i__1, info);
00514 
00515 /*           Zero out below R. */
00516 
00517             if (*n > 1) {
00518                 i__1 = *n - 1;
00519                 i__2 = *n - 1;
00520                 claset_("L", &i__1, &i__2, &c_b1, &c_b1, &a[a_dim1 + 2], lda);
00521             }
00522         }
00523 
00524         itauq = 1;
00525         itaup = itauq + *n;
00526         nwork = itaup + *n;
00527         ie = 1;
00528         nrwork = ie + *n;
00529 
00530 /*        Bidiagonalize R in A. */
00531 /*        (RWorkspace: need N) */
00532 /*        (CWorkspace: need 2*N+MM, prefer 2*N+(MM+N)*NB) */
00533 
00534         i__1 = *lwork - nwork + 1;
00535         cgebrd_(&mm, n, &a[a_offset], lda, &s[1], &rwork[ie], &work[itauq], &
00536                 work[itaup], &work[nwork], &i__1, info);
00537 
00538 /*        Multiply B by transpose of left bidiagonalizing vectors of R. */
00539 /*        (CWorkspace: need 2*N+NRHS, prefer 2*N+NRHS*NB) */
00540 
00541         i__1 = *lwork - nwork + 1;
00542         cunmbr_("Q", "L", "C", &mm, nrhs, n, &a[a_offset], lda, &work[itauq], 
00543                 &b[b_offset], ldb, &work[nwork], &i__1, info);
00544 
00545 /*        Solve the bidiagonal least squares problem. */
00546 
00547         clalsd_("U", &smlsiz, n, nrhs, &s[1], &rwork[ie], &b[b_offset], ldb, 
00548                 rcond, rank, &work[nwork], &rwork[nrwork], &iwork[1], info);
00549         if (*info != 0) {
00550             goto L10;
00551         }
00552 
00553 /*        Multiply B by right bidiagonalizing vectors of R. */
00554 
00555         i__1 = *lwork - nwork + 1;
00556         cunmbr_("P", "L", "N", n, nrhs, n, &a[a_offset], lda, &work[itaup], &
00557                 b[b_offset], ldb, &work[nwork], &i__1, info);
00558 
00559     } else /* if(complicated condition) */ {
00560 /* Computing MAX */
00561         i__1 = *m, i__2 = (*m << 1) - 4, i__1 = max(i__1,i__2), i__1 = max(
00562                 i__1,*nrhs), i__2 = *n - *m * 3;
00563         if (*n >= mnthr && *lwork >= (*m << 2) + *m * *m + max(i__1,i__2)) {
00564 
00565 /*        Path 2a - underdetermined, with many more columns than rows */
00566 /*        and sufficient workspace for an efficient algorithm. */
00567 
00568             ldwork = *m;
00569 /* Computing MAX */
00570 /* Computing MAX */
00571             i__3 = *m, i__4 = (*m << 1) - 4, i__3 = max(i__3,i__4), i__3 = 
00572                     max(i__3,*nrhs), i__4 = *n - *m * 3;
00573             i__1 = (*m << 2) + *m * *lda + max(i__3,i__4), i__2 = *m * *lda + 
00574                     *m + *m * *nrhs;
00575             if (*lwork >= max(i__1,i__2)) {
00576                 ldwork = *lda;
00577             }
00578             itau = 1;
00579             nwork = *m + 1;
00580 
00581 /*        Compute A=L*Q. */
00582 /*        (CWorkspace: need 2*M, prefer M+M*NB) */
00583 
00584             i__1 = *lwork - nwork + 1;
00585             cgelqf_(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &i__1, 
00586                      info);
00587             il = nwork;
00588 
00589 /*        Copy L to WORK(IL), zeroing out above its diagonal. */
00590 
00591             clacpy_("L", m, m, &a[a_offset], lda, &work[il], &ldwork);
00592             i__1 = *m - 1;
00593             i__2 = *m - 1;
00594             claset_("U", &i__1, &i__2, &c_b1, &c_b1, &work[il + ldwork], &
00595                     ldwork);
00596             itauq = il + ldwork * *m;
00597             itaup = itauq + *m;
00598             nwork = itaup + *m;
00599             ie = 1;
00600             nrwork = ie + *m;
00601 
00602 /*        Bidiagonalize L in WORK(IL). */
00603 /*        (RWorkspace: need M) */
00604 /*        (CWorkspace: need M*M+4*M, prefer M*M+4*M+2*M*NB) */
00605 
00606             i__1 = *lwork - nwork + 1;
00607             cgebrd_(m, m, &work[il], &ldwork, &s[1], &rwork[ie], &work[itauq], 
00608                      &work[itaup], &work[nwork], &i__1, info);
00609 
00610 /*        Multiply B by transpose of left bidiagonalizing vectors of L. */
00611 /*        (CWorkspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB) */
00612 
00613             i__1 = *lwork - nwork + 1;
00614             cunmbr_("Q", "L", "C", m, nrhs, m, &work[il], &ldwork, &work[
00615                     itauq], &b[b_offset], ldb, &work[nwork], &i__1, info);
00616 
00617 /*        Solve the bidiagonal least squares problem. */
00618 
00619             clalsd_("U", &smlsiz, m, nrhs, &s[1], &rwork[ie], &b[b_offset], 
00620                     ldb, rcond, rank, &work[nwork], &rwork[nrwork], &iwork[1], 
00621                      info);
00622             if (*info != 0) {
00623                 goto L10;
00624             }
00625 
00626 /*        Multiply B by right bidiagonalizing vectors of L. */
00627 
00628             i__1 = *lwork - nwork + 1;
00629             cunmbr_("P", "L", "N", m, nrhs, m, &work[il], &ldwork, &work[
00630                     itaup], &b[b_offset], ldb, &work[nwork], &i__1, info);
00631 
00632 /*        Zero out below first M rows of B. */
00633 
00634             i__1 = *n - *m;
00635             claset_("F", &i__1, nrhs, &c_b1, &c_b1, &b[*m + 1 + b_dim1], ldb);
00636             nwork = itau + *m;
00637 
00638 /*        Multiply transpose(Q) by B. */
00639 /*        (CWorkspace: need NRHS, prefer NRHS*NB) */
00640 
00641             i__1 = *lwork - nwork + 1;
00642             cunmlq_("L", "C", n, nrhs, m, &a[a_offset], lda, &work[itau], &b[
00643                     b_offset], ldb, &work[nwork], &i__1, info);
00644 
00645         } else {
00646 
00647 /*        Path 2 - remaining underdetermined cases. */
00648 
00649             itauq = 1;
00650             itaup = itauq + *m;
00651             nwork = itaup + *m;
00652             ie = 1;
00653             nrwork = ie + *m;
00654 
00655 /*        Bidiagonalize A. */
00656 /*        (RWorkspace: need M) */
00657 /*        (CWorkspace: need 2*M+N, prefer 2*M+(M+N)*NB) */
00658 
00659             i__1 = *lwork - nwork + 1;
00660             cgebrd_(m, n, &a[a_offset], lda, &s[1], &rwork[ie], &work[itauq], 
00661                     &work[itaup], &work[nwork], &i__1, info);
00662 
00663 /*        Multiply B by transpose of left bidiagonalizing vectors. */
00664 /*        (CWorkspace: need 2*M+NRHS, prefer 2*M+NRHS*NB) */
00665 
00666             i__1 = *lwork - nwork + 1;
00667             cunmbr_("Q", "L", "C", m, nrhs, n, &a[a_offset], lda, &work[itauq]
00668 , &b[b_offset], ldb, &work[nwork], &i__1, info);
00669 
00670 /*        Solve the bidiagonal least squares problem. */
00671 
00672             clalsd_("L", &smlsiz, m, nrhs, &s[1], &rwork[ie], &b[b_offset], 
00673                     ldb, rcond, rank, &work[nwork], &rwork[nrwork], &iwork[1], 
00674                      info);
00675             if (*info != 0) {
00676                 goto L10;
00677             }
00678 
00679 /*        Multiply B by right bidiagonalizing vectors of A. */
00680 
00681             i__1 = *lwork - nwork + 1;
00682             cunmbr_("P", "L", "N", n, nrhs, m, &a[a_offset], lda, &work[itaup]
00683 , &b[b_offset], ldb, &work[nwork], &i__1, info);
00684 
00685         }
00686     }
00687 
00688 /*     Undo scaling. */
00689 
00690     if (iascl == 1) {
00691         clascl_("G", &c__0, &c__0, &anrm, &smlnum, n, nrhs, &b[b_offset], ldb, 
00692                  info);
00693         slascl_("G", &c__0, &c__0, &smlnum, &anrm, &minmn, &c__1, &s[1], &
00694                 minmn, info);
00695     } else if (iascl == 2) {
00696         clascl_("G", &c__0, &c__0, &anrm, &bignum, n, nrhs, &b[b_offset], ldb, 
00697                  info);
00698         slascl_("G", &c__0, &c__0, &bignum, &anrm, &minmn, &c__1, &s[1], &
00699                 minmn, info);
00700     }
00701     if (ibscl == 1) {
00702         clascl_("G", &c__0, &c__0, &smlnum, &bnrm, n, nrhs, &b[b_offset], ldb, 
00703                  info);
00704     } else if (ibscl == 2) {
00705         clascl_("G", &c__0, &c__0, &bignum, &bnrm, n, nrhs, &b[b_offset], ldb, 
00706                  info);
00707     }
00708 
00709 L10:
00710     work[1].r = (real) maxwrk, work[1].i = 0.f;
00711     iwork[1] = liwork;
00712     rwork[1] = (real) lrwork;
00713     return 0;
00714 
00715 /*     End of CGELSD */
00716 
00717 } /* cgelsd_ */


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