171
  172
  173
  174
  175
  176
  177      CHARACTER          UPLO
  178      INTEGER            INFO, LDB, N, NRHS, RANK, SMLSIZ
  179      REAL               RCOND
  180
  181
  182      INTEGER            IWORK( * )
  183      REAL               B( LDB, * ), D( * ), E( * ), WORK( * )
  184
  185
  186
  187
  188
  189      REAL               ZERO, ONE, TWO
  190      parameter( zero = 0.0e0, one = 1.0e0, two = 2.0e0 )
  191
  192
  193      INTEGER            BX, BXST, C, DIFL, DIFR, GIVCOL, GIVNUM,
  194     $                   GIVPTR, I, ICMPQ1, ICMPQ2, IWK, J, K, NLVL,
  195     $                   NM1, NSIZE, NSUB, NWORK, PERM, POLES, S, SIZEI,
  196     $                   SMLSZP, SQRE, ST, ST1, U, VT, Z
  197      REAL               CS, EPS, ORGNRM, R, RCND, SN, TOL
  198
  199
  200      INTEGER            ISAMAX
  201      REAL               SLAMCH, SLANST
  203
  204
  208
  209
  210      INTRINSIC          abs, int, log, real, sign
  211
  212
  213
  214
  215
  216      info = 0
  217
  218      IF( n.LT.0 ) THEN
  219         info = -3
  220      ELSE IF( nrhs.LT.1 ) THEN
  221         info = -4
  222      ELSE IF( ( ldb.LT.1 ) .OR. ( ldb.LT.n ) ) THEN
  223         info = -8
  224      END IF
  225      IF( info.NE.0 ) THEN
  226         CALL xerbla( 
'SLALSD', -info )
 
  227         RETURN
  228      END IF
  229
  231
  232
  233
  234      IF( ( rcond.LE.zero ) .OR. ( rcond.GE.one ) ) THEN
  235         rcnd = eps
  236      ELSE
  237         rcnd = rcond
  238      END IF
  239
  240      rank = 0
  241
  242
  243
  244      IF( n.EQ.0 ) THEN
  245         RETURN
  246      ELSE IF( n.EQ.1 ) THEN
  247         IF( d( 1 ).EQ.zero ) THEN
  248            CALL slaset( 
'A', 1, nrhs, zero, zero, b, ldb )
 
  249         ELSE
  250            rank = 1
  251            CALL slascl( 
'G', 0, 0, d( 1 ), one, 1, nrhs, b, ldb,
 
  252     $                   info )
  253            d( 1 ) = abs( d( 1 ) )
  254         END IF
  255         RETURN
  256      END IF
  257
  258
  259
  260      IF( uplo.EQ.'L' ) THEN
  261         DO 10 i = 1, n - 1
  262            CALL slartg( d( i ), e( i ), cs, sn, r )
 
  263            d( i ) = r
  264            e( i ) = sn*d( i+1 )
  265            d( i+1 ) = cs*d( i+1 )
  266            IF( nrhs.EQ.1 ) THEN
  267               CALL srot( 1, b( i, 1 ), 1, b( i+1, 1 ), 1, cs, sn )
 
  268            ELSE
  269               work( i*2-1 ) = cs
  270               work( i*2 ) = sn
  271            END IF
  272   10    CONTINUE
  273         IF( nrhs.GT.1 ) THEN
  274            DO 30 i = 1, nrhs
  275               DO 20 j = 1, n - 1
  276                  cs = work( j*2-1 )
  277                  sn = work( j*2 )
  278                  CALL srot( 1, b( j, i ), 1, b( j+1, i ), 1, cs,
 
  279     $                       sn )
  280   20          CONTINUE
  281   30       CONTINUE
  282         END IF
  283      END IF
  284
  285
  286
  287      nm1 = n - 1
  288      orgnrm = 
slanst( 
'M', n, d, e )
 
  289      IF( orgnrm.EQ.zero ) THEN
  290         CALL slaset( 
'A', n, nrhs, zero, zero, b, ldb )
 
  291         RETURN
  292      END IF
  293
  294      CALL slascl( 
'G', 0, 0, orgnrm, one, n, 1, d, n, info )
 
  295      CALL slascl( 
'G', 0, 0, orgnrm, one, nm1, 1, e, nm1, info )
 
  296
  297
  298
  299
  300      IF( n.LE.smlsiz ) THEN
  301         nwork = 1 + n*n
  302         CALL slaset( 
'A', n, n, zero, one, work, n )
 
  303         CALL slasdq( 
'U', 0, n, n, 0, nrhs, d, e, work, n, work, n,
 
  304     $                b,
  305     $                ldb, work( nwork ), info )
  306         IF( info.NE.0 ) THEN
  307            RETURN
  308         END IF
  309         tol = rcnd*abs( d( 
isamax( n, d, 1 ) ) )
 
  310         DO 40 i = 1, n
  311            IF( d( i ).LE.tol ) THEN
  312               CALL slaset( 
'A', 1, nrhs, zero, zero, b( i, 1 ),
 
  313     $                      ldb )
  314            ELSE
  315               CALL slascl( 
'G', 0, 0, d( i ), one, 1, nrhs, b( i,
 
  316     $                      1 ),
  317     $                      ldb, info )
  318               rank = rank + 1
  319            END IF
  320   40    CONTINUE
  321         CALL sgemm( 
'T', 
'N', n, nrhs, n, one, work, n, b, ldb,
 
  322     $               zero,
  323     $               work( nwork ), n )
  324         CALL slacpy( 
'A', n, nrhs, work( nwork ), n, b, ldb )
 
  325
  326
  327
  328         CALL slascl( 
'G', 0, 0, one, orgnrm, n, 1, d, n, info )
 
  329         CALL slasrt( 
'D', n, d, info )
 
  330         CALL slascl( 
'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
 
  331
  332         RETURN
  333      END IF
  334
  335
  336
  337      nlvl = int( log( real( n ) / real( smlsiz+1 ) ) / log( two ) ) + 1
  338
  339      smlszp = smlsiz + 1
  340
  341      u = 1
  342      vt = 1 + smlsiz*n
  343      difl = vt + smlszp*n
  344      difr = difl + nlvl*n
  345      z = difr + nlvl*n*2
  346      c = z + nlvl*n
  347      s = c + n
  348      poles = s + n
  349      givnum = poles + 2*nlvl*n
  350      bx = givnum + 2*nlvl*n
  351      nwork = bx + n*nrhs
  352
  353      sizei = 1 + n
  354      k = sizei + n
  355      givptr = k + n
  356      perm = givptr + n
  357      givcol = perm + nlvl*n
  358      iwk = givcol + nlvl*n*2
  359
  360      st = 1
  361      sqre = 0
  362      icmpq1 = 1
  363      icmpq2 = 0
  364      nsub = 0
  365
  366      DO 50 i = 1, n
  367         IF( abs( d( i ) ).LT.eps ) THEN
  368            d( i ) = sign( eps, d( i ) )
  369         END IF
  370   50 CONTINUE
  371
  372      DO 60 i = 1, nm1
  373         IF( ( abs( e( i ) ).LT.eps ) .OR. ( i.EQ.nm1 ) ) THEN
  374            nsub = nsub + 1
  375            iwork( nsub ) = st
  376
  377
  378
  379
  380            IF( i.LT.nm1 ) THEN
  381
  382
  383
  384               nsize = i - st + 1
  385               iwork( sizei+nsub-1 ) = nsize
  386            ELSE IF( abs( e( i ) ).GE.eps ) THEN
  387
  388
  389
  390               nsize = n - st + 1
  391               iwork( sizei+nsub-1 ) = nsize
  392            ELSE
  393
  394
  395
  396
  397
  398               nsize = i - st + 1
  399               iwork( sizei+nsub-1 ) = nsize
  400               nsub = nsub + 1
  401               iwork( nsub ) = n
  402               iwork( sizei+nsub-1 ) = 1
  403               CALL scopy( nrhs, b( n, 1 ), ldb, work( bx+nm1 ), n )
 
  404            END IF
  405            st1 = st - 1
  406            IF( nsize.EQ.1 ) THEN
  407
  408
  409
  410
  411               CALL scopy( nrhs, b( st, 1 ), ldb, work( bx+st1 ), n )
 
  412            ELSE IF( nsize.LE.smlsiz ) THEN
  413
  414
  415
  416               CALL slaset( 
'A', nsize, nsize, zero, one,
 
  417     $                      work( vt+st1 ), n )
  418               CALL slasdq( 
'U', 0, nsize, nsize, 0, nrhs, d( st ),
 
  419     $                      e( st ), work( vt+st1 ), n, work( nwork ),
  420     $                      n, b( st, 1 ), ldb, work( nwork ), info )
  421               IF( info.NE.0 ) THEN
  422                  RETURN
  423               END IF
  424               CALL slacpy( 
'A', nsize, nrhs, b( st, 1 ), ldb,
 
  425     $                      work( bx+st1 ), n )
  426            ELSE
  427
  428
  429
  430               CALL slasda( icmpq1, smlsiz, nsize, sqre, d( st ),
 
  431     $                      e( st ), work( u+st1 ), n, work( vt+st1 ),
  432     $                      iwork( k+st1 ), work( difl+st1 ),
  433     $                      work( difr+st1 ), work( z+st1 ),
  434     $                      work( poles+st1 ), iwork( givptr+st1 ),
  435     $                      iwork( givcol+st1 ), n, iwork( perm+st1 ),
  436     $                      work( givnum+st1 ), work( c+st1 ),
  437     $                      work( s+st1 ), work( nwork ), iwork( iwk ),
  438     $                      info )
  439               IF( info.NE.0 ) THEN
  440                  RETURN
  441               END IF
  442               bxst = bx + st1
  443               CALL slalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1 ),
 
  444     $                      ldb, work( bxst ), n, work( u+st1 ), n,
  445     $                      work( vt+st1 ), iwork( k+st1 ),
  446     $                      work( difl+st1 ), work( difr+st1 ),
  447     $                      work( z+st1 ), work( poles+st1 ),
  448     $                      iwork( givptr+st1 ), iwork( givcol+st1 ), n,
  449     $                      iwork( perm+st1 ), work( givnum+st1 ),
  450     $                      work( c+st1 ), work( s+st1 ), work( nwork ),
  451     $                      iwork( iwk ), info )
  452               IF( info.NE.0 ) THEN
  453                  RETURN
  454               END IF
  455            END IF
  456            st = i + 1
  457         END IF
  458   60 CONTINUE
  459
  460
  461
  462      tol = rcnd*abs( d( 
isamax( n, d, 1 ) ) )
 
  463
  464      DO 70 i = 1, n
  465
  466
  467
  468
  469         IF( abs( d( i ) ).LE.tol ) THEN
  470            CALL slaset( 
'A', 1, nrhs, zero, zero, work( bx+i-1 ),
 
  471     $                   n )
  472         ELSE
  473            rank = rank + 1
  474            CALL slascl( 
'G', 0, 0, d( i ), one, 1, nrhs,
 
  475     $                   work( bx+i-1 ), n, info )
  476         END IF
  477         d( i ) = abs( d( i ) )
  478   70 CONTINUE
  479
  480
  481
  482      icmpq2 = 1
  483      DO 80 i = 1, nsub
  484         st = iwork( i )
  485         st1 = st - 1
  486         nsize = iwork( sizei+i-1 )
  487         bxst = bx + st1
  488         IF( nsize.EQ.1 ) THEN
  489            CALL scopy( nrhs, work( bxst ), n, b( st, 1 ), ldb )
 
  490         ELSE IF( nsize.LE.smlsiz ) THEN
  491            CALL sgemm( 
'T', 
'N', nsize, nrhs, nsize, one,
 
  492     $                  work( vt+st1 ), n, work( bxst ), n, zero,
  493     $                  b( st, 1 ), ldb )
  494         ELSE
  495            CALL slalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ),
 
  496     $                   n,
  497     $                   b( st, 1 ), ldb, work( u+st1 ), n,
  498     $                   work( vt+st1 ), iwork( k+st1 ),
  499     $                   work( difl+st1 ), work( difr+st1 ),
  500     $                   work( z+st1 ), work( poles+st1 ),
  501     $                   iwork( givptr+st1 ), iwork( givcol+st1 ), n,
  502     $                   iwork( perm+st1 ), work( givnum+st1 ),
  503     $                   work( c+st1 ), work( s+st1 ), work( nwork ),
  504     $                   iwork( iwk ), info )
  505            IF( info.NE.0 ) THEN
  506               RETURN
  507            END IF
  508         END IF
  509   80 CONTINUE
  510
  511
  512
  513      CALL slascl( 
'G', 0, 0, one, orgnrm, n, 1, d, n, info )
 
  514      CALL slasrt( 
'D', n, d, info )
 
  515      CALL slascl( 
'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
 
  516
  517      RETURN
  518
  519
  520
subroutine xerbla(srname, info)
 
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
 
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
 
integer function isamax(n, sx, incx)
ISAMAX
 
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
 
subroutine slalsa(icompq, smlsiz, n, nrhs, b, ldb, bx, ldbx, u, ldu, vt, k, difl, difr, z, poles, givptr, givcol, ldgcol, perm, givnum, c, s, work, iwork, info)
SLALSA computes the SVD of the coefficient matrix in compact form. Used by sgelsd.
 
real function slamch(cmach)
SLAMCH
 
real function slanst(norm, n, d, e)
SLANST returns the value of the 1-norm, or the Frobenius norm, or the infinity norm,...
 
subroutine slartg(f, g, c, s, r)
SLARTG generates a plane rotation with real cosine and real sine.
 
subroutine slascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
SLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
 
subroutine slasda(icompq, smlsiz, n, sqre, d, e, u, ldu, vt, k, difl, difr, z, poles, givptr, givcol, ldgcol, perm, givnum, c, s, work, iwork, info)
SLASDA computes the singular value decomposition (SVD) of a real upper bidiagonal matrix with diagona...
 
subroutine slasdq(uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
SLASDQ computes the SVD of a real bidiagonal matrix with diagonal d and off-diagonal e....
 
subroutine slaset(uplo, m, n, alpha, beta, a, lda)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
 
subroutine slasrt(id, n, d, info)
SLASRT sorts numbers in increasing or decreasing order.
 
subroutine srot(n, sx, incx, sy, incy, c, s)
SROT