LAPACK 3.3.0

sgelss.f

Go to the documentation of this file.
00001       SUBROUTINE SGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
00002      $                   WORK, LWORK, INFO )
00003 *
00004 *  -- LAPACK driver routine (version 3.2) --
00005 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00006 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00007 *     November 2006
00008 *
00009 *     .. Scalar Arguments ..
00010       INTEGER            INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
00011       REAL               RCOND
00012 *     ..
00013 *     .. Array Arguments ..
00014       REAL               A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
00015 *     ..
00016 *
00017 *  Purpose
00018 *  =======
00019 *
00020 *  SGELSS computes the minimum norm solution to a real linear least
00021 *  squares problem:
00022 *
00023 *  Minimize 2-norm(| b - A*x |).
00024 *
00025 *  using the singular value decomposition (SVD) of A. A is an M-by-N
00026 *  matrix which may be rank-deficient.
00027 *
00028 *  Several right hand side vectors b and solution vectors x can be
00029 *  handled in a single call; they are stored as the columns of the
00030 *  M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix
00031 *  X.
00032 *
00033 *  The effective rank of A is determined by treating as zero those
00034 *  singular values which are less than RCOND times the largest singular
00035 *  value.
00036 *
00037 *  Arguments
00038 *  =========
00039 *
00040 *  M       (input) INTEGER
00041 *          The number of rows of the matrix A. M >= 0.
00042 *
00043 *  N       (input) INTEGER
00044 *          The number of columns of the matrix A. N >= 0.
00045 *
00046 *  NRHS    (input) INTEGER
00047 *          The number of right hand sides, i.e., the number of columns
00048 *          of the matrices B and X. NRHS >= 0.
00049 *
00050 *  A       (input/output) REAL array, dimension (LDA,N)
00051 *          On entry, the M-by-N matrix A.
00052 *          On exit, the first min(m,n) rows of A are overwritten with
00053 *          its right singular vectors, stored rowwise.
00054 *
00055 *  LDA     (input) INTEGER
00056 *          The leading dimension of the array A.  LDA >= max(1,M).
00057 *
00058 *  B       (input/output) REAL array, dimension (LDB,NRHS)
00059 *          On entry, the M-by-NRHS right hand side matrix B.
00060 *          On exit, B is overwritten by the N-by-NRHS solution
00061 *          matrix X.  If m >= n and RANK = n, the residual
00062 *          sum-of-squares for the solution in the i-th column is given
00063 *          by the sum of squares of elements n+1:m in that column.
00064 *
00065 *  LDB     (input) INTEGER
00066 *          The leading dimension of the array B. LDB >= max(1,max(M,N)).
00067 *
00068 *  S       (output) REAL array, dimension (min(M,N))
00069 *          The singular values of A in decreasing order.
00070 *          The condition number of A in the 2-norm = S(1)/S(min(m,n)).
00071 *
00072 *  RCOND   (input) REAL
00073 *          RCOND is used to determine the effective rank of A.
00074 *          Singular values S(i) <= RCOND*S(1) are treated as zero.
00075 *          If RCOND < 0, machine precision is used instead.
00076 *
00077 *  RANK    (output) INTEGER
00078 *          The effective rank of A, i.e., the number of singular values
00079 *          which are greater than RCOND*S(1).
00080 *
00081 *  WORK    (workspace/output) REAL array, dimension (MAX(1,LWORK))
00082 *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
00083 *
00084 *  LWORK   (input) INTEGER
00085 *          The dimension of the array WORK. LWORK >= 1, and also:
00086 *          LWORK >= 3*min(M,N) + max( 2*min(M,N), max(M,N), NRHS )
00087 *          For good performance, LWORK should generally be larger.
00088 *
00089 *          If LWORK = -1, then a workspace query is assumed; the routine
00090 *          only calculates the optimal size of the WORK array, returns
00091 *          this value as the first entry of the WORK array, and no error
00092 *          message related to LWORK is issued by XERBLA.
00093 *
00094 *  INFO    (output) INTEGER
00095 *          = 0:  successful exit
00096 *          < 0:  if INFO = -i, the i-th argument had an illegal value.
00097 *          > 0:  the algorithm for computing the SVD failed to converge;
00098 *                if INFO = i, i off-diagonal elements of an intermediate
00099 *                bidiagonal form did not converge to zero.
00100 *
00101 *  =====================================================================
00102 *
00103 *     .. Parameters ..
00104       REAL               ZERO, ONE
00105       PARAMETER          ( ZERO = 0.0E+0, ONE = 1.0E+0 )
00106 *     ..
00107 *     .. Local Scalars ..
00108       LOGICAL            LQUERY
00109       INTEGER            BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
00110      $                   ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
00111      $                   MAXWRK, MINMN, MINWRK, MM, MNTHR
00112       REAL               ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
00113 *     ..
00114 *     .. Local Arrays ..
00115       REAL               VDUM( 1 )
00116 *     ..
00117 *     .. External Subroutines ..
00118       EXTERNAL           SBDSQR, SCOPY, SGEBRD, SGELQF, SGEMM, SGEMV,
00119      $                   SGEQRF, SLABAD, SLACPY, SLASCL, SLASET, SORGBR,
00120      $                   SORMBR, SORMLQ, SORMQR, SRSCL, XERBLA
00121 *     ..
00122 *     .. External Functions ..
00123       INTEGER            ILAENV
00124       REAL               SLAMCH, SLANGE
00125       EXTERNAL           ILAENV, SLAMCH, SLANGE
00126 *     ..
00127 *     .. Intrinsic Functions ..
00128       INTRINSIC          MAX, MIN
00129 *     ..
00130 *     .. Executable Statements ..
00131 *
00132 *     Test the input arguments
00133 *
00134       INFO = 0
00135       MINMN = MIN( M, N )
00136       MAXMN = MAX( M, N )
00137       LQUERY = ( LWORK.EQ.-1 )
00138       IF( M.LT.0 ) THEN
00139          INFO = -1
00140       ELSE IF( N.LT.0 ) THEN
00141          INFO = -2
00142       ELSE IF( NRHS.LT.0 ) THEN
00143          INFO = -3
00144       ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
00145          INFO = -5
00146       ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THEN
00147          INFO = -7
00148       END IF
00149 *
00150 *     Compute workspace
00151 *      (Note: Comments in the code beginning "Workspace:" describe the
00152 *       minimal amount of workspace needed at that point in the code,
00153 *       as well as the preferred amount for good performance.
00154 *       NB refers to the optimal block size for the immediately
00155 *       following subroutine, as returned by ILAENV.)
00156 *
00157       IF( INFO.EQ.0 ) THEN
00158          MINWRK = 1
00159          MAXWRK = 1
00160          IF( MINMN.GT.0 ) THEN
00161             MM = M
00162             MNTHR = ILAENV( 6, 'SGELSS', ' ', M, N, NRHS, -1 )
00163             IF( M.GE.N .AND. M.GE.MNTHR ) THEN
00164 *
00165 *              Path 1a - overdetermined, with many more rows than
00166 *                        columns
00167 *
00168                MM = N
00169                MAXWRK = MAX( MAXWRK, N + N*ILAENV( 1, 'SGEQRF', ' ', M,
00170      $                       N, -1, -1 ) )
00171                MAXWRK = MAX( MAXWRK, N + NRHS*ILAENV( 1, 'SORMQR', 'LT',
00172      $                       M, NRHS, N, -1 ) )
00173             END IF
00174             IF( M.GE.N ) THEN
00175 *
00176 *              Path 1 - overdetermined or exactly determined
00177 *
00178 *              Compute workspace needed for SBDSQR
00179 *
00180                BDSPAC = MAX( 1, 5*N )
00181                MAXWRK = MAX( MAXWRK, 3*N + ( MM + N )*ILAENV( 1,
00182      $                       'SGEBRD', ' ', MM, N, -1, -1 ) )
00183                MAXWRK = MAX( MAXWRK, 3*N + NRHS*ILAENV( 1, 'SORMBR',
00184      $                       'QLT', MM, NRHS, N, -1 ) )
00185                MAXWRK = MAX( MAXWRK, 3*N + ( N - 1 )*ILAENV( 1,
00186      $                       'SORGBR', 'P', N, N, N, -1 ) )
00187                MAXWRK = MAX( MAXWRK, BDSPAC )
00188                MAXWRK = MAX( MAXWRK, N*NRHS )
00189                MINWRK = MAX( 3*N + MM, 3*N + NRHS, BDSPAC )
00190                MAXWRK = MAX( MINWRK, MAXWRK )
00191             END IF
00192             IF( N.GT.M ) THEN
00193 *
00194 *              Compute workspace needed for SBDSQR
00195 *
00196                BDSPAC = MAX( 1, 5*M )
00197                MINWRK = MAX( 3*M+NRHS, 3*M+N, BDSPAC )
00198                IF( N.GE.MNTHR ) THEN
00199 *
00200 *                 Path 2a - underdetermined, with many more columns
00201 *                 than rows
00202 *
00203                   MAXWRK = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1,
00204      $                                  -1 )
00205                   MAXWRK = MAX( MAXWRK, M*M + 4*M + 2*M*ILAENV( 1,
00206      $                          'SGEBRD', ' ', M, M, -1, -1 ) )
00207                   MAXWRK = MAX( MAXWRK, M*M + 4*M + NRHS*ILAENV( 1,
00208      $                          'SORMBR', 'QLT', M, NRHS, M, -1 ) )
00209                   MAXWRK = MAX( MAXWRK, M*M + 4*M +
00210      $                          ( M - 1 )*ILAENV( 1, 'SORGBR', 'P', M,
00211      $                          M, M, -1 ) )
00212                   MAXWRK = MAX( MAXWRK, M*M + M + BDSPAC )
00213                   IF( NRHS.GT.1 ) THEN
00214                      MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
00215                   ELSE
00216                      MAXWRK = MAX( MAXWRK, M*M + 2*M )
00217                   END IF
00218                   MAXWRK = MAX( MAXWRK, M + NRHS*ILAENV( 1, 'SORMLQ',
00219      $                          'LT', N, NRHS, M, -1 ) )
00220                ELSE
00221 *
00222 *                 Path 2 - underdetermined
00223 *
00224                   MAXWRK = 3*M + ( N + M )*ILAENV( 1, 'SGEBRD', ' ', M,
00225      $                     N, -1, -1 )
00226                   MAXWRK = MAX( MAXWRK, 3*M + NRHS*ILAENV( 1, 'SORMBR',
00227      $                          'QLT', M, NRHS, M, -1 ) )
00228                   MAXWRK = MAX( MAXWRK, 3*M + M*ILAENV( 1, 'SORGBR',
00229      $                          'P', M, N, M, -1 ) )
00230                   MAXWRK = MAX( MAXWRK, BDSPAC )
00231                   MAXWRK = MAX( MAXWRK, N*NRHS )
00232                END IF
00233             END IF
00234             MAXWRK = MAX( MINWRK, MAXWRK )
00235          END IF
00236          WORK( 1 ) = MAXWRK
00237 *
00238          IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY )
00239      $      INFO = -12
00240       END IF
00241 *
00242       IF( INFO.NE.0 ) THEN
00243          CALL XERBLA( 'SGELSS', -INFO )
00244          RETURN
00245       ELSE IF( LQUERY ) THEN
00246          RETURN
00247       END IF
00248 *
00249 *     Quick return if possible
00250 *
00251       IF( M.EQ.0 .OR. N.EQ.0 ) THEN
00252          RANK = 0
00253          RETURN
00254       END IF
00255 *
00256 *     Get machine parameters
00257 *
00258       EPS = SLAMCH( 'P' )
00259       SFMIN = SLAMCH( 'S' )
00260       SMLNUM = SFMIN / EPS
00261       BIGNUM = ONE / SMLNUM
00262       CALL SLABAD( SMLNUM, BIGNUM )
00263 *
00264 *     Scale A if max element outside range [SMLNUM,BIGNUM]
00265 *
00266       ANRM = SLANGE( 'M', M, N, A, LDA, WORK )
00267       IASCL = 0
00268       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00269 *
00270 *        Scale matrix norm up to SMLNUM
00271 *
00272          CALL SLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
00273          IASCL = 1
00274       ELSE IF( ANRM.GT.BIGNUM ) THEN
00275 *
00276 *        Scale matrix norm down to BIGNUM
00277 *
00278          CALL SLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
00279          IASCL = 2
00280       ELSE IF( ANRM.EQ.ZERO ) THEN
00281 *
00282 *        Matrix all zero. Return zero solution.
00283 *
00284          CALL SLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )
00285          CALL SLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 )
00286          RANK = 0
00287          GO TO 70
00288       END IF
00289 *
00290 *     Scale B if max element outside range [SMLNUM,BIGNUM]
00291 *
00292       BNRM = SLANGE( 'M', M, NRHS, B, LDB, WORK )
00293       IBSCL = 0
00294       IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00295 *
00296 *        Scale matrix norm up to SMLNUM
00297 *
00298          CALL SLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
00299          IBSCL = 1
00300       ELSE IF( BNRM.GT.BIGNUM ) THEN
00301 *
00302 *        Scale matrix norm down to BIGNUM
00303 *
00304          CALL SLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
00305          IBSCL = 2
00306       END IF
00307 *
00308 *     Overdetermined case
00309 *
00310       IF( M.GE.N ) THEN
00311 *
00312 *        Path 1 - overdetermined or exactly determined
00313 *
00314          MM = M
00315          IF( M.GE.MNTHR ) THEN
00316 *
00317 *           Path 1a - overdetermined, with many more rows than columns
00318 *
00319             MM = N
00320             ITAU = 1
00321             IWORK = ITAU + N
00322 *
00323 *           Compute A=Q*R
00324 *           (Workspace: need 2*N, prefer N+N*NB)
00325 *
00326             CALL SGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
00327      $                   LWORK-IWORK+1, INFO )
00328 *
00329 *           Multiply B by transpose(Q)
00330 *           (Workspace: need N+NRHS, prefer N+NRHS*NB)
00331 *
00332             CALL SORMQR( 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAU ), B,
00333      $                   LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
00334 *
00335 *           Zero out below R
00336 *
00337             IF( N.GT.1 )
00338      $         CALL SLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
00339          END IF
00340 *
00341          IE = 1
00342          ITAUQ = IE + N
00343          ITAUP = ITAUQ + N
00344          IWORK = ITAUP + N
00345 *
00346 *        Bidiagonalize R in A
00347 *        (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB)
00348 *
00349          CALL SGEBRD( MM, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
00350      $                WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
00351      $                INFO )
00352 *
00353 *        Multiply B by transpose of left bidiagonalizing vectors of R
00354 *        (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB)
00355 *
00356          CALL SORMBR( 'Q', 'L', 'T', MM, NRHS, N, A, LDA, WORK( ITAUQ ),
00357      $                B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
00358 *
00359 *        Generate right bidiagonalizing vectors of R in A
00360 *        (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
00361 *
00362          CALL SORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
00363      $                WORK( IWORK ), LWORK-IWORK+1, INFO )
00364          IWORK = IE + N
00365 *
00366 *        Perform bidiagonal QR iteration
00367 *          multiply B by transpose of left singular vectors
00368 *          compute right singular vectors in A
00369 *        (Workspace: need BDSPAC)
00370 *
00371          CALL SBDSQR( 'U', N, N, 0, NRHS, S, WORK( IE ), A, LDA, VDUM,
00372      $                1, B, LDB, WORK( IWORK ), INFO )
00373          IF( INFO.NE.0 )
00374      $      GO TO 70
00375 *
00376 *        Multiply B by reciprocals of singular values
00377 *
00378          THR = MAX( RCOND*S( 1 ), SFMIN )
00379          IF( RCOND.LT.ZERO )
00380      $      THR = MAX( EPS*S( 1 ), SFMIN )
00381          RANK = 0
00382          DO 10 I = 1, N
00383             IF( S( I ).GT.THR ) THEN
00384                CALL SRSCL( NRHS, S( I ), B( I, 1 ), LDB )
00385                RANK = RANK + 1
00386             ELSE
00387                CALL SLASET( 'F', 1, NRHS, ZERO, ZERO, B( I, 1 ), LDB )
00388             END IF
00389    10    CONTINUE
00390 *
00391 *        Multiply B by right singular vectors
00392 *        (Workspace: need N, prefer N*NRHS)
00393 *
00394          IF( LWORK.GE.LDB*NRHS .AND. NRHS.GT.1 ) THEN
00395             CALL SGEMM( 'T', 'N', N, NRHS, N, ONE, A, LDA, B, LDB, ZERO,
00396      $                  WORK, LDB )
00397             CALL SLACPY( 'G', N, NRHS, WORK, LDB, B, LDB )
00398          ELSE IF( NRHS.GT.1 ) THEN
00399             CHUNK = LWORK / N
00400             DO 20 I = 1, NRHS, CHUNK
00401                BL = MIN( NRHS-I+1, CHUNK )
00402                CALL SGEMM( 'T', 'N', N, BL, N, ONE, A, LDA, B( 1, I ),
00403      $                     LDB, ZERO, WORK, N )
00404                CALL SLACPY( 'G', N, BL, WORK, N, B( 1, I ), LDB )
00405    20       CONTINUE
00406          ELSE
00407             CALL SGEMV( 'T', N, N, ONE, A, LDA, B, 1, ZERO, WORK, 1 )
00408             CALL SCOPY( N, WORK, 1, B, 1 )
00409          END IF
00410 *
00411       ELSE IF( N.GE.MNTHR .AND. LWORK.GE.4*M+M*M+
00412      $         MAX( M, 2*M-4, NRHS, N-3*M ) ) THEN
00413 *
00414 *        Path 2a - underdetermined, with many more columns than rows
00415 *        and sufficient workspace for an efficient algorithm
00416 *
00417          LDWORK = M
00418          IF( LWORK.GE.MAX( 4*M+M*LDA+MAX( M, 2*M-4, NRHS, N-3*M ),
00419      $       M*LDA+M+M*NRHS ) )LDWORK = LDA
00420          ITAU = 1
00421          IWORK = M + 1
00422 *
00423 *        Compute A=L*Q
00424 *        (Workspace: need 2*M, prefer M+M*NB)
00425 *
00426          CALL SGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
00427      $                LWORK-IWORK+1, INFO )
00428          IL = IWORK
00429 *
00430 *        Copy L to WORK(IL), zeroing out above it
00431 *
00432          CALL SLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK )
00433          CALL SLASET( 'U', M-1, M-1, ZERO, ZERO, WORK( IL+LDWORK ),
00434      $                LDWORK )
00435          IE = IL + LDWORK*M
00436          ITAUQ = IE + M
00437          ITAUP = ITAUQ + M
00438          IWORK = ITAUP + M
00439 *
00440 *        Bidiagonalize L in WORK(IL)
00441 *        (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB)
00442 *
00443          CALL SGEBRD( M, M, WORK( IL ), LDWORK, S, WORK( IE ),
00444      $                WORK( ITAUQ ), WORK( ITAUP ), WORK( IWORK ),
00445      $                LWORK-IWORK+1, INFO )
00446 *
00447 *        Multiply B by transpose of left bidiagonalizing vectors of L
00448 *        (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB)
00449 *
00450          CALL SORMBR( 'Q', 'L', 'T', M, NRHS, M, WORK( IL ), LDWORK,
00451      $                WORK( ITAUQ ), B, LDB, WORK( IWORK ),
00452      $                LWORK-IWORK+1, INFO )
00453 *
00454 *        Generate right bidiagonalizing vectors of R in WORK(IL)
00455 *        (Workspace: need M*M+5*M-1, prefer M*M+4*M+(M-1)*NB)
00456 *
00457          CALL SORGBR( 'P', M, M, M, WORK( IL ), LDWORK, WORK( ITAUP ),
00458      $                WORK( IWORK ), LWORK-IWORK+1, INFO )
00459          IWORK = IE + M
00460 *
00461 *        Perform bidiagonal QR iteration,
00462 *           computing right singular vectors of L in WORK(IL) and
00463 *           multiplying B by transpose of left singular vectors
00464 *        (Workspace: need M*M+M+BDSPAC)
00465 *
00466          CALL SBDSQR( 'U', M, M, 0, NRHS, S, WORK( IE ), WORK( IL ),
00467      $                LDWORK, A, LDA, B, LDB, WORK( IWORK ), INFO )
00468          IF( INFO.NE.0 )
00469      $      GO TO 70
00470 *
00471 *        Multiply B by reciprocals of singular values
00472 *
00473          THR = MAX( RCOND*S( 1 ), SFMIN )
00474          IF( RCOND.LT.ZERO )
00475      $      THR = MAX( EPS*S( 1 ), SFMIN )
00476          RANK = 0
00477          DO 30 I = 1, M
00478             IF( S( I ).GT.THR ) THEN
00479                CALL SRSCL( NRHS, S( I ), B( I, 1 ), LDB )
00480                RANK = RANK + 1
00481             ELSE
00482                CALL SLASET( 'F', 1, NRHS, ZERO, ZERO, B( I, 1 ), LDB )
00483             END IF
00484    30    CONTINUE
00485          IWORK = IE
00486 *
00487 *        Multiply B by right singular vectors of L in WORK(IL)
00488 *        (Workspace: need M*M+2*M, prefer M*M+M+M*NRHS)
00489 *
00490          IF( LWORK.GE.LDB*NRHS+IWORK-1 .AND. NRHS.GT.1 ) THEN
00491             CALL SGEMM( 'T', 'N', M, NRHS, M, ONE, WORK( IL ), LDWORK,
00492      $                  B, LDB, ZERO, WORK( IWORK ), LDB )
00493             CALL SLACPY( 'G', M, NRHS, WORK( IWORK ), LDB, B, LDB )
00494          ELSE IF( NRHS.GT.1 ) THEN
00495             CHUNK = ( LWORK-IWORK+1 ) / M
00496             DO 40 I = 1, NRHS, CHUNK
00497                BL = MIN( NRHS-I+1, CHUNK )
00498                CALL SGEMM( 'T', 'N', M, BL, M, ONE, WORK( IL ), LDWORK,
00499      $                     B( 1, I ), LDB, ZERO, WORK( IWORK ), M )
00500                CALL SLACPY( 'G', M, BL, WORK( IWORK ), M, B( 1, I ),
00501      $                      LDB )
00502    40       CONTINUE
00503          ELSE
00504             CALL SGEMV( 'T', M, M, ONE, WORK( IL ), LDWORK, B( 1, 1 ),
00505      $                  1, ZERO, WORK( IWORK ), 1 )
00506             CALL SCOPY( M, WORK( IWORK ), 1, B( 1, 1 ), 1 )
00507          END IF
00508 *
00509 *        Zero out below first M rows of B
00510 *
00511          CALL SLASET( 'F', N-M, NRHS, ZERO, ZERO, B( M+1, 1 ), LDB )
00512          IWORK = ITAU + M
00513 *
00514 *        Multiply transpose(Q) by B
00515 *        (Workspace: need M+NRHS, prefer M+NRHS*NB)
00516 *
00517          CALL SORMLQ( 'L', 'T', N, NRHS, M, A, LDA, WORK( ITAU ), B,
00518      $                LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
00519 *
00520       ELSE
00521 *
00522 *        Path 2 - remaining underdetermined cases
00523 *
00524          IE = 1
00525          ITAUQ = IE + M
00526          ITAUP = ITAUQ + M
00527          IWORK = ITAUP + M
00528 *
00529 *        Bidiagonalize A
00530 *        (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
00531 *
00532          CALL SGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
00533      $                WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
00534      $                INFO )
00535 *
00536 *        Multiply B by transpose of left bidiagonalizing vectors
00537 *        (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB)
00538 *
00539          CALL SORMBR( 'Q', 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAUQ ),
00540      $                B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
00541 *
00542 *        Generate right bidiagonalizing vectors in A
00543 *        (Workspace: need 4*M, prefer 3*M+M*NB)
00544 *
00545          CALL SORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
00546      $                WORK( IWORK ), LWORK-IWORK+1, INFO )
00547          IWORK = IE + M
00548 *
00549 *        Perform bidiagonal QR iteration,
00550 *           computing right singular vectors of A in A and
00551 *           multiplying B by transpose of left singular vectors
00552 *        (Workspace: need BDSPAC)
00553 *
00554          CALL SBDSQR( 'L', M, N, 0, NRHS, S, WORK( IE ), A, LDA, VDUM,
00555      $                1, B, LDB, WORK( IWORK ), INFO )
00556          IF( INFO.NE.0 )
00557      $      GO TO 70
00558 *
00559 *        Multiply B by reciprocals of singular values
00560 *
00561          THR = MAX( RCOND*S( 1 ), SFMIN )
00562          IF( RCOND.LT.ZERO )
00563      $      THR = MAX( EPS*S( 1 ), SFMIN )
00564          RANK = 0
00565          DO 50 I = 1, M
00566             IF( S( I ).GT.THR ) THEN
00567                CALL SRSCL( NRHS, S( I ), B( I, 1 ), LDB )
00568                RANK = RANK + 1
00569             ELSE
00570                CALL SLASET( 'F', 1, NRHS, ZERO, ZERO, B( I, 1 ), LDB )
00571             END IF
00572    50    CONTINUE
00573 *
00574 *        Multiply B by right singular vectors of A
00575 *        (Workspace: need N, prefer N*NRHS)
00576 *
00577          IF( LWORK.GE.LDB*NRHS .AND. NRHS.GT.1 ) THEN
00578             CALL SGEMM( 'T', 'N', N, NRHS, M, ONE, A, LDA, B, LDB, ZERO,
00579      $                  WORK, LDB )
00580             CALL SLACPY( 'F', N, NRHS, WORK, LDB, B, LDB )
00581          ELSE IF( NRHS.GT.1 ) THEN
00582             CHUNK = LWORK / N
00583             DO 60 I = 1, NRHS, CHUNK
00584                BL = MIN( NRHS-I+1, CHUNK )
00585                CALL SGEMM( 'T', 'N', N, BL, M, ONE, A, LDA, B( 1, I ),
00586      $                     LDB, ZERO, WORK, N )
00587                CALL SLACPY( 'F', N, BL, WORK, N, B( 1, I ), LDB )
00588    60       CONTINUE
00589          ELSE
00590             CALL SGEMV( 'T', M, N, ONE, A, LDA, B, 1, ZERO, WORK, 1 )
00591             CALL SCOPY( N, WORK, 1, B, 1 )
00592          END IF
00593       END IF
00594 *
00595 *     Undo scaling
00596 *
00597       IF( IASCL.EQ.1 ) THEN
00598          CALL SLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )
00599          CALL SLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
00600      $                INFO )
00601       ELSE IF( IASCL.EQ.2 ) THEN
00602          CALL SLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )
00603          CALL SLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
00604      $                INFO )
00605       END IF
00606       IF( IBSCL.EQ.1 ) THEN
00607          CALL SLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
00608       ELSE IF( IBSCL.EQ.2 ) THEN
00609          CALL SLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )
00610       END IF
00611 *
00612    70 CONTINUE
00613       WORK( 1 ) = MAXWRK
00614       RETURN
00615 *
00616 *     End of SGELSS
00617 *
00618       END
 All Files Functions