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


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