LAPACK 3.3.1 Linear Algebra PACKage

# clalsd.f

Go to the documentation of this file.
```00001       SUBROUTINE CLALSD( UPLO, SMLSIZ, N, NRHS, D, E, B, LDB, RCOND,
00002      \$                   RANK, WORK, RWORK, IWORK, INFO )
00003 *
00004 *  -- LAPACK routine (version 3.3.1) --
00005 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00006 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00007 *  -- April 2011                                                      --
00008 *
00009 *     .. Scalar Arguments ..
00010       CHARACTER          UPLO
00011       INTEGER            INFO, LDB, N, NRHS, RANK, SMLSIZ
00012       REAL               RCOND
00013 *     ..
00014 *     .. Array Arguments ..
00015       INTEGER            IWORK( * )
00016       REAL               D( * ), E( * ), RWORK( * )
00017       COMPLEX            B( LDB, * ), WORK( * )
00018 *     ..
00019 *
00020 *  Purpose
00021 *  =======
00022 *
00023 *  CLALSD uses the singular value decomposition of A to solve the least
00024 *  squares problem of finding X to minimize the Euclidean norm of each
00025 *  column of A*X-B, where A is N-by-N upper bidiagonal, and X and B
00026 *  are N-by-NRHS. The solution X overwrites B.
00027 *
00028 *  The singular values of A smaller than RCOND times the largest
00029 *  singular value are treated as zero in solving the least squares
00030 *  problem; in this case a minimum norm solution is returned.
00031 *  The actual singular values are returned in D in ascending order.
00032 *
00033 *  This code makes very mild assumptions about floating point
00034 *  arithmetic. It will work on machines with a guard digit in
00035 *  add/subtract, or on those binary machines without guard digits
00036 *  which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2.
00037 *  It could conceivably fail on hexadecimal or decimal machines
00038 *  without guard digits, but we know of none.
00039 *
00040 *  Arguments
00041 *  =========
00042 *
00043 *  UPLO   (input) CHARACTER*1
00044 *         = 'U': D and E define an upper bidiagonal matrix.
00045 *         = 'L': D and E define a  lower bidiagonal matrix.
00046 *
00047 *  SMLSIZ (input) INTEGER
00048 *         The maximum size of the subproblems at the bottom of the
00049 *         computation tree.
00050 *
00051 *  N      (input) INTEGER
00052 *         The dimension of the  bidiagonal matrix.  N >= 0.
00053 *
00054 *  NRHS   (input) INTEGER
00055 *         The number of columns of B. NRHS must be at least 1.
00056 *
00057 *  D      (input/output) REAL array, dimension (N)
00058 *         On entry D contains the main diagonal of the bidiagonal
00059 *         matrix. On exit, if INFO = 0, D contains its singular values.
00060 *
00061 *  E      (input/output) REAL array, dimension (N-1)
00062 *         Contains the super-diagonal entries of the bidiagonal matrix.
00063 *         On exit, E has been destroyed.
00064 *
00065 *  B      (input/output) COMPLEX array, dimension (LDB,NRHS)
00066 *         On input, B contains the right hand sides of the least
00067 *         squares problem. On output, B contains the solution X.
00068 *
00069 *  LDB    (input) INTEGER
00070 *         The leading dimension of B in the calling subprogram.
00071 *         LDB must be at least max(1,N).
00072 *
00073 *  RCOND  (input) REAL
00074 *         The singular values of A less than or equal to RCOND times
00075 *         the largest singular value are treated as zero in solving
00076 *         the least squares problem. If RCOND is negative,
00077 *         machine precision is used instead.
00078 *         For example, if diag(S)*X=B were the least squares problem,
00079 *         where diag(S) is a diagonal matrix of singular values, the
00080 *         solution would be X(i) = B(i) / S(i) if S(i) is greater than
00081 *         RCOND*max(S), and X(i) = 0 if S(i) is less than or equal to
00082 *         RCOND*max(S).
00083 *
00084 *  RANK   (output) INTEGER
00085 *         The number of singular values of A greater than RCOND times
00086 *         the largest singular value.
00087 *
00088 *  WORK   (workspace) COMPLEX array, dimension (N * NRHS).
00089 *
00090 *  RWORK  (workspace) REAL array, dimension at least
00091 *         (9*N + 2*N*SMLSIZ + 8*N*NLVL + 3*SMLSIZ*NRHS +
00092 *         MAX( (SMLSIZ+1)**2, N*(1+NRHS) + 2*NRHS ),
00093 *         where
00094 *         NLVL = MAX( 0, INT( LOG_2( MIN( M,N )/(SMLSIZ+1) ) ) + 1 )
00095 *
00096 *  IWORK  (workspace) INTEGER array, dimension (3*N*NLVL + 11*N).
00097 *
00098 *  INFO   (output) INTEGER
00099 *         = 0:  successful exit.
00100 *         < 0:  if INFO = -i, the i-th argument had an illegal value.
00101 *         > 0:  The algorithm failed to compute a singular value while
00102 *               working on the submatrix lying in rows and columns
00103 *               INFO/(N+1) through MOD(INFO,N+1).
00104 *
00105 *  Further Details
00106 *  ===============
00107 *
00108 *  Based on contributions by
00109 *     Ming Gu and Ren-Cang Li, Computer Science Division, University of
00110 *       California at Berkeley, USA
00111 *     Osni Marques, LBNL/NERSC, USA
00112 *
00113 *  =====================================================================
00114 *
00115 *     .. Parameters ..
00116       REAL               ZERO, ONE, TWO
00117       PARAMETER          ( ZERO = 0.0E0, ONE = 1.0E0, TWO = 2.0E0 )
00118       COMPLEX            CZERO
00119       PARAMETER          ( CZERO = ( 0.0E0, 0.0E0 ) )
00120 *     ..
00121 *     .. Local Scalars ..
00122       INTEGER            BX, BXST, C, DIFL, DIFR, GIVCOL, GIVNUM,
00123      \$                   GIVPTR, I, ICMPQ1, ICMPQ2, IRWB, IRWIB, IRWRB,
00124      \$                   IRWU, IRWVT, IRWWRK, IWK, J, JCOL, JIMAG,
00125      \$                   JREAL, JROW, K, NLVL, NM1, NRWORK, NSIZE, NSUB,
00126      \$                   PERM, POLES, S, SIZEI, SMLSZP, SQRE, ST, ST1,
00127      \$                   U, VT, Z
00128       REAL               CS, EPS, ORGNRM, R, RCND, SN, TOL
00129 *     ..
00130 *     .. External Functions ..
00131       INTEGER            ISAMAX
00132       REAL               SLAMCH, SLANST
00133       EXTERNAL           ISAMAX, SLAMCH, SLANST
00134 *     ..
00135 *     .. External Subroutines ..
00136       EXTERNAL           CCOPY, CLACPY, CLALSA, CLASCL, CLASET, CSROT,
00137      \$                   SGEMM, SLARTG, SLASCL, SLASDA, SLASDQ, SLASET,
00138      \$                   SLASRT, XERBLA
00139 *     ..
00140 *     .. Intrinsic Functions ..
00141       INTRINSIC          ABS, AIMAG, CMPLX, INT, LOG, REAL, SIGN
00142 *     ..
00143 *     .. Executable Statements ..
00144 *
00145 *     Test the input parameters.
00146 *
00147       INFO = 0
00148 *
00149       IF( N.LT.0 ) THEN
00150          INFO = -3
00151       ELSE IF( NRHS.LT.1 ) THEN
00152          INFO = -4
00153       ELSE IF( ( LDB.LT.1 ) .OR. ( LDB.LT.N ) ) THEN
00154          INFO = -8
00155       END IF
00156       IF( INFO.NE.0 ) THEN
00157          CALL XERBLA( 'CLALSD', -INFO )
00158          RETURN
00159       END IF
00160 *
00161       EPS = SLAMCH( 'Epsilon' )
00162 *
00163 *     Set up the tolerance.
00164 *
00165       IF( ( RCOND.LE.ZERO ) .OR. ( RCOND.GE.ONE ) ) THEN
00166          RCND = EPS
00167       ELSE
00168          RCND = RCOND
00169       END IF
00170 *
00171       RANK = 0
00172 *
00173 *     Quick return if possible.
00174 *
00175       IF( N.EQ.0 ) THEN
00176          RETURN
00177       ELSE IF( N.EQ.1 ) THEN
00178          IF( D( 1 ).EQ.ZERO ) THEN
00179             CALL CLASET( 'A', 1, NRHS, CZERO, CZERO, B, LDB )
00180          ELSE
00181             RANK = 1
00182             CALL CLASCL( 'G', 0, 0, D( 1 ), ONE, 1, NRHS, B, LDB, INFO )
00183             D( 1 ) = ABS( D( 1 ) )
00184          END IF
00185          RETURN
00186       END IF
00187 *
00188 *     Rotate the matrix if it is lower bidiagonal.
00189 *
00190       IF( UPLO.EQ.'L' ) THEN
00191          DO 10 I = 1, N - 1
00192             CALL SLARTG( D( I ), E( I ), CS, SN, R )
00193             D( I ) = R
00194             E( I ) = SN*D( I+1 )
00195             D( I+1 ) = CS*D( I+1 )
00196             IF( NRHS.EQ.1 ) THEN
00197                CALL CSROT( 1, B( I, 1 ), 1, B( I+1, 1 ), 1, CS, SN )
00198             ELSE
00199                RWORK( I*2-1 ) = CS
00200                RWORK( I*2 ) = SN
00201             END IF
00202    10    CONTINUE
00203          IF( NRHS.GT.1 ) THEN
00204             DO 30 I = 1, NRHS
00205                DO 20 J = 1, N - 1
00206                   CS = RWORK( J*2-1 )
00207                   SN = RWORK( J*2 )
00208                   CALL CSROT( 1, B( J, I ), 1, B( J+1, I ), 1, CS, SN )
00209    20          CONTINUE
00210    30       CONTINUE
00211          END IF
00212       END IF
00213 *
00214 *     Scale.
00215 *
00216       NM1 = N - 1
00217       ORGNRM = SLANST( 'M', N, D, E )
00218       IF( ORGNRM.EQ.ZERO ) THEN
00219          CALL CLASET( 'A', N, NRHS, CZERO, CZERO, B, LDB )
00220          RETURN
00221       END IF
00222 *
00223       CALL SLASCL( 'G', 0, 0, ORGNRM, ONE, N, 1, D, N, INFO )
00224       CALL SLASCL( 'G', 0, 0, ORGNRM, ONE, NM1, 1, E, NM1, INFO )
00225 *
00226 *     If N is smaller than the minimum divide size SMLSIZ, then solve
00227 *     the problem with another solver.
00228 *
00229       IF( N.LE.SMLSIZ ) THEN
00230          IRWU = 1
00231          IRWVT = IRWU + N*N
00232          IRWWRK = IRWVT + N*N
00233          IRWRB = IRWWRK
00234          IRWIB = IRWRB + N*NRHS
00235          IRWB = IRWIB + N*NRHS
00236          CALL SLASET( 'A', N, N, ZERO, ONE, RWORK( IRWU ), N )
00237          CALL SLASET( 'A', N, N, ZERO, ONE, RWORK( IRWVT ), N )
00238          CALL SLASDQ( 'U', 0, N, N, N, 0, D, E, RWORK( IRWVT ), N,
00239      \$                RWORK( IRWU ), N, RWORK( IRWWRK ), 1,
00240      \$                RWORK( IRWWRK ), INFO )
00241          IF( INFO.NE.0 ) THEN
00242             RETURN
00243          END IF
00244 *
00245 *        In the real version, B is passed to SLASDQ and multiplied
00246 *        internally by Q**H. Here B is complex and that product is
00247 *        computed below in two steps (real and imaginary parts).
00248 *
00249          J = IRWB - 1
00250          DO 50 JCOL = 1, NRHS
00251             DO 40 JROW = 1, N
00252                J = J + 1
00253                RWORK( J ) = REAL( B( JROW, JCOL ) )
00254    40       CONTINUE
00255    50    CONTINUE
00256          CALL SGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWU ), N,
00257      \$               RWORK( IRWB ), N, ZERO, RWORK( IRWRB ), N )
00258          J = IRWB - 1
00259          DO 70 JCOL = 1, NRHS
00260             DO 60 JROW = 1, N
00261                J = J + 1
00262                RWORK( J ) = AIMAG( B( JROW, JCOL ) )
00263    60       CONTINUE
00264    70    CONTINUE
00265          CALL SGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWU ), N,
00266      \$               RWORK( IRWB ), N, ZERO, RWORK( IRWIB ), N )
00267          JREAL = IRWRB - 1
00268          JIMAG = IRWIB - 1
00269          DO 90 JCOL = 1, NRHS
00270             DO 80 JROW = 1, N
00271                JREAL = JREAL + 1
00272                JIMAG = JIMAG + 1
00273                B( JROW, JCOL ) = CMPLX( RWORK( JREAL ), RWORK( JIMAG ) )
00274    80       CONTINUE
00275    90    CONTINUE
00276 *
00277          TOL = RCND*ABS( D( ISAMAX( N, D, 1 ) ) )
00278          DO 100 I = 1, N
00279             IF( D( I ).LE.TOL ) THEN
00280                CALL CLASET( 'A', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
00281             ELSE
00282                CALL CLASCL( 'G', 0, 0, D( I ), ONE, 1, NRHS, B( I, 1 ),
00283      \$                      LDB, INFO )
00284                RANK = RANK + 1
00285             END IF
00286   100    CONTINUE
00287 *
00288 *        Since B is complex, the following call to SGEMM is performed
00289 *        in two steps (real and imaginary parts). That is for V * B
00290 *        (in the real version of the code V**H is stored in WORK).
00291 *
00292 *        CALL SGEMM( 'T', 'N', N, NRHS, N, ONE, WORK, N, B, LDB, ZERO,
00293 *    \$               WORK( NWORK ), N )
00294 *
00295          J = IRWB - 1
00296          DO 120 JCOL = 1, NRHS
00297             DO 110 JROW = 1, N
00298                J = J + 1
00299                RWORK( J ) = REAL( B( JROW, JCOL ) )
00300   110       CONTINUE
00301   120    CONTINUE
00302          CALL SGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWVT ), N,
00303      \$               RWORK( IRWB ), N, ZERO, RWORK( IRWRB ), N )
00304          J = IRWB - 1
00305          DO 140 JCOL = 1, NRHS
00306             DO 130 JROW = 1, N
00307                J = J + 1
00308                RWORK( J ) = AIMAG( B( JROW, JCOL ) )
00309   130       CONTINUE
00310   140    CONTINUE
00311          CALL SGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWVT ), N,
00312      \$               RWORK( IRWB ), N, ZERO, RWORK( IRWIB ), N )
00313          JREAL = IRWRB - 1
00314          JIMAG = IRWIB - 1
00315          DO 160 JCOL = 1, NRHS
00316             DO 150 JROW = 1, N
00317                JREAL = JREAL + 1
00318                JIMAG = JIMAG + 1
00319                B( JROW, JCOL ) = CMPLX( RWORK( JREAL ), RWORK( JIMAG ) )
00320   150       CONTINUE
00321   160    CONTINUE
00322 *
00323 *        Unscale.
00324 *
00325          CALL SLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )
00326          CALL SLASRT( 'D', N, D, INFO )
00327          CALL CLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )
00328 *
00329          RETURN
00330       END IF
00331 *
00332 *     Book-keeping and setting up some constants.
00333 *
00334       NLVL = INT( LOG( REAL( N ) / REAL( SMLSIZ+1 ) ) / LOG( TWO ) ) + 1
00335 *
00336       SMLSZP = SMLSIZ + 1
00337 *
00338       U = 1
00339       VT = 1 + SMLSIZ*N
00340       DIFL = VT + SMLSZP*N
00341       DIFR = DIFL + NLVL*N
00342       Z = DIFR + NLVL*N*2
00343       C = Z + NLVL*N
00344       S = C + N
00345       POLES = S + N
00346       GIVNUM = POLES + 2*NLVL*N
00347       NRWORK = GIVNUM + 2*NLVL*N
00348       BX = 1
00349 *
00350       IRWRB = NRWORK
00351       IRWIB = IRWRB + SMLSIZ*NRHS
00352       IRWB = IRWIB + SMLSIZ*NRHS
00353 *
00354       SIZEI = 1 + N
00355       K = SIZEI + N
00356       GIVPTR = K + N
00357       PERM = GIVPTR + N
00358       GIVCOL = PERM + NLVL*N
00359       IWK = GIVCOL + NLVL*N*2
00360 *
00361       ST = 1
00362       SQRE = 0
00363       ICMPQ1 = 1
00364       ICMPQ2 = 0
00365       NSUB = 0
00366 *
00367       DO 170 I = 1, N
00368          IF( ABS( D( I ) ).LT.EPS ) THEN
00369             D( I ) = SIGN( EPS, D( I ) )
00370          END IF
00371   170 CONTINUE
00372 *
00373       DO 240 I = 1, NM1
00374          IF( ( ABS( E( I ) ).LT.EPS ) .OR. ( I.EQ.NM1 ) ) THEN
00375             NSUB = NSUB + 1
00376             IWORK( NSUB ) = ST
00377 *
00378 *           Subproblem found. First determine its size and then
00379 *           apply divide and conquer on it.
00380 *
00381             IF( I.LT.NM1 ) THEN
00382 *
00383 *              A subproblem with E(I) small for I < NM1.
00384 *
00385                NSIZE = I - ST + 1
00386                IWORK( SIZEI+NSUB-1 ) = NSIZE
00387             ELSE IF( ABS( E( I ) ).GE.EPS ) THEN
00388 *
00389 *              A subproblem with E(NM1) not too small but I = NM1.
00390 *
00391                NSIZE = N - ST + 1
00392                IWORK( SIZEI+NSUB-1 ) = NSIZE
00393             ELSE
00394 *
00395 *              A subproblem with E(NM1) small. This implies an
00396 *              1-by-1 subproblem at D(N), which is not solved
00397 *              explicitly.
00398 *
00399                NSIZE = I - ST + 1
00400                IWORK( SIZEI+NSUB-1 ) = NSIZE
00401                NSUB = NSUB + 1
00402                IWORK( NSUB ) = N
00403                IWORK( SIZEI+NSUB-1 ) = 1
00404                CALL CCOPY( NRHS, B( N, 1 ), LDB, WORK( BX+NM1 ), N )
00405             END IF
00406             ST1 = ST - 1
00407             IF( NSIZE.EQ.1 ) THEN
00408 *
00409 *              This is a 1-by-1 subproblem and is not solved
00410 *              explicitly.
00411 *
00412                CALL CCOPY( NRHS, B( ST, 1 ), LDB, WORK( BX+ST1 ), N )
00413             ELSE IF( NSIZE.LE.SMLSIZ ) THEN
00414 *
00415 *              This is a small subproblem and is solved by SLASDQ.
00416 *
00417                CALL SLASET( 'A', NSIZE, NSIZE, ZERO, ONE,
00418      \$                      RWORK( VT+ST1 ), N )
00419                CALL SLASET( 'A', NSIZE, NSIZE, ZERO, ONE,
00420      \$                      RWORK( U+ST1 ), N )
00421                CALL SLASDQ( 'U', 0, NSIZE, NSIZE, NSIZE, 0, D( ST ),
00422      \$                      E( ST ), RWORK( VT+ST1 ), N, RWORK( U+ST1 ),
00423      \$                      N, RWORK( NRWORK ), 1, RWORK( NRWORK ),
00424      \$                      INFO )
00425                IF( INFO.NE.0 ) THEN
00426                   RETURN
00427                END IF
00428 *
00429 *              In the real version, B is passed to SLASDQ and multiplied
00430 *              internally by Q**H. Here B is complex and that product is
00431 *              computed below in two steps (real and imaginary parts).
00432 *
00433                J = IRWB - 1
00434                DO 190 JCOL = 1, NRHS
00435                   DO 180 JROW = ST, ST + NSIZE - 1
00436                      J = J + 1
00437                      RWORK( J ) = REAL( B( JROW, JCOL ) )
00438   180             CONTINUE
00439   190          CONTINUE
00440                CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
00441      \$                     RWORK( U+ST1 ), N, RWORK( IRWB ), NSIZE,
00442      \$                     ZERO, RWORK( IRWRB ), NSIZE )
00443                J = IRWB - 1
00444                DO 210 JCOL = 1, NRHS
00445                   DO 200 JROW = ST, ST + NSIZE - 1
00446                      J = J + 1
00447                      RWORK( J ) = AIMAG( B( JROW, JCOL ) )
00448   200             CONTINUE
00449   210          CONTINUE
00450                CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
00451      \$                     RWORK( U+ST1 ), N, RWORK( IRWB ), NSIZE,
00452      \$                     ZERO, RWORK( IRWIB ), NSIZE )
00453                JREAL = IRWRB - 1
00454                JIMAG = IRWIB - 1
00455                DO 230 JCOL = 1, NRHS
00456                   DO 220 JROW = ST, ST + NSIZE - 1
00457                      JREAL = JREAL + 1
00458                      JIMAG = JIMAG + 1
00459                      B( JROW, JCOL ) = CMPLX( RWORK( JREAL ),
00460      \$                                 RWORK( JIMAG ) )
00461   220             CONTINUE
00462   230          CONTINUE
00463 *
00464                CALL CLACPY( 'A', NSIZE, NRHS, B( ST, 1 ), LDB,
00465      \$                      WORK( BX+ST1 ), N )
00466             ELSE
00467 *
00468 *              A large problem. Solve it using divide and conquer.
00469 *
00470                CALL SLASDA( ICMPQ1, SMLSIZ, NSIZE, SQRE, D( ST ),
00471      \$                      E( ST ), RWORK( U+ST1 ), N, RWORK( VT+ST1 ),
00472      \$                      IWORK( K+ST1 ), RWORK( DIFL+ST1 ),
00473      \$                      RWORK( DIFR+ST1 ), RWORK( Z+ST1 ),
00474      \$                      RWORK( POLES+ST1 ), IWORK( GIVPTR+ST1 ),
00475      \$                      IWORK( GIVCOL+ST1 ), N, IWORK( PERM+ST1 ),
00476      \$                      RWORK( GIVNUM+ST1 ), RWORK( C+ST1 ),
00477      \$                      RWORK( S+ST1 ), RWORK( NRWORK ),
00478      \$                      IWORK( IWK ), INFO )
00479                IF( INFO.NE.0 ) THEN
00480                   RETURN
00481                END IF
00482                BXST = BX + ST1
00483                CALL CLALSA( ICMPQ2, SMLSIZ, NSIZE, NRHS, B( ST, 1 ),
00484      \$                      LDB, WORK( BXST ), N, RWORK( U+ST1 ), N,
00485      \$                      RWORK( VT+ST1 ), IWORK( K+ST1 ),
00486      \$                      RWORK( DIFL+ST1 ), RWORK( DIFR+ST1 ),
00487      \$                      RWORK( Z+ST1 ), RWORK( POLES+ST1 ),
00488      \$                      IWORK( GIVPTR+ST1 ), IWORK( GIVCOL+ST1 ), N,
00489      \$                      IWORK( PERM+ST1 ), RWORK( GIVNUM+ST1 ),
00490      \$                      RWORK( C+ST1 ), RWORK( S+ST1 ),
00491      \$                      RWORK( NRWORK ), IWORK( IWK ), INFO )
00492                IF( INFO.NE.0 ) THEN
00493                   RETURN
00494                END IF
00495             END IF
00496             ST = I + 1
00497          END IF
00498   240 CONTINUE
00499 *
00500 *     Apply the singular values and treat the tiny ones as zero.
00501 *
00502       TOL = RCND*ABS( D( ISAMAX( N, D, 1 ) ) )
00503 *
00504       DO 250 I = 1, N
00505 *
00506 *        Some of the elements in D can be negative because 1-by-1
00507 *        subproblems were not solved explicitly.
00508 *
00509          IF( ABS( D( I ) ).LE.TOL ) THEN
00510             CALL CLASET( 'A', 1, NRHS, CZERO, CZERO, WORK( BX+I-1 ), N )
00511          ELSE
00512             RANK = RANK + 1
00513             CALL CLASCL( 'G', 0, 0, D( I ), ONE, 1, NRHS,
00514      \$                   WORK( BX+I-1 ), N, INFO )
00515          END IF
00516          D( I ) = ABS( D( I ) )
00517   250 CONTINUE
00518 *
00519 *     Now apply back the right singular vectors.
00520 *
00521       ICMPQ2 = 1
00522       DO 320 I = 1, NSUB
00523          ST = IWORK( I )
00524          ST1 = ST - 1
00525          NSIZE = IWORK( SIZEI+I-1 )
00526          BXST = BX + ST1
00527          IF( NSIZE.EQ.1 ) THEN
00528             CALL CCOPY( NRHS, WORK( BXST ), N, B( ST, 1 ), LDB )
00529          ELSE IF( NSIZE.LE.SMLSIZ ) THEN
00530 *
00531 *           Since B and BX are complex, the following call to SGEMM
00532 *           is performed in two steps (real and imaginary parts).
00533 *
00534 *           CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
00535 *    \$                  RWORK( VT+ST1 ), N, RWORK( BXST ), N, ZERO,
00536 *    \$                  B( ST, 1 ), LDB )
00537 *
00538             J = BXST - N - 1
00539             JREAL = IRWB - 1
00540             DO 270 JCOL = 1, NRHS
00541                J = J + N
00542                DO 260 JROW = 1, NSIZE
00543                   JREAL = JREAL + 1
00544                   RWORK( JREAL ) = REAL( WORK( J+JROW ) )
00545   260          CONTINUE
00546   270       CONTINUE
00547             CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
00548      \$                  RWORK( VT+ST1 ), N, RWORK( IRWB ), NSIZE, ZERO,
00549      \$                  RWORK( IRWRB ), NSIZE )
00550             J = BXST - N - 1
00551             JIMAG = IRWB - 1
00552             DO 290 JCOL = 1, NRHS
00553                J = J + N
00554                DO 280 JROW = 1, NSIZE
00555                   JIMAG = JIMAG + 1
00556                   RWORK( JIMAG ) = AIMAG( WORK( J+JROW ) )
00557   280          CONTINUE
00558   290       CONTINUE
00559             CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
00560      \$                  RWORK( VT+ST1 ), N, RWORK( IRWB ), NSIZE, ZERO,
00561      \$                  RWORK( IRWIB ), NSIZE )
00562             JREAL = IRWRB - 1
00563             JIMAG = IRWIB - 1
00564             DO 310 JCOL = 1, NRHS
00565                DO 300 JROW = ST, ST + NSIZE - 1
00566                   JREAL = JREAL + 1
00567                   JIMAG = JIMAG + 1
00568                   B( JROW, JCOL ) = CMPLX( RWORK( JREAL ),
00569      \$                              RWORK( JIMAG ) )
00570   300          CONTINUE
00571   310       CONTINUE
00572          ELSE
00573             CALL CLALSA( ICMPQ2, SMLSIZ, NSIZE, NRHS, WORK( BXST ), N,
00574      \$                   B( ST, 1 ), LDB, RWORK( U+ST1 ), N,
00575      \$                   RWORK( VT+ST1 ), IWORK( K+ST1 ),
00576      \$                   RWORK( DIFL+ST1 ), RWORK( DIFR+ST1 ),
00577      \$                   RWORK( Z+ST1 ), RWORK( POLES+ST1 ),
00578      \$                   IWORK( GIVPTR+ST1 ), IWORK( GIVCOL+ST1 ), N,
00579      \$                   IWORK( PERM+ST1 ), RWORK( GIVNUM+ST1 ),
00580      \$                   RWORK( C+ST1 ), RWORK( S+ST1 ),
00581      \$                   RWORK( NRWORK ), IWORK( IWK ), INFO )
00582             IF( INFO.NE.0 ) THEN
00583                RETURN
00584             END IF
00585          END IF
00586   320 CONTINUE
00587 *
00588 *     Unscale and sort the singular values.
00589 *
00590       CALL SLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )
00591       CALL SLASRT( 'D', N, D, INFO )
00592       CALL CLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )
00593 *
00594       RETURN
00595 *
00596 *     End of CLALSD
00597 *
00598       END
```