clalsd.f
来自「famous linear algebra library (LAPACK) p」· F 代码 · 共 597 行 · 第 1/2 页
F
597 行
CALL SGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWVT ), N,
$ RWORK( IRWB ), N, ZERO, RWORK( IRWRB ), N )
J = IRWB - 1
DO 140 JCOL = 1, NRHS
DO 130 JROW = 1, N
J = J + 1
RWORK( J ) = AIMAG( B( JROW, JCOL ) )
130 CONTINUE
140 CONTINUE
CALL SGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWVT ), N,
$ RWORK( IRWB ), N, ZERO, RWORK( IRWIB ), N )
JREAL = IRWRB - 1
JIMAG = IRWIB - 1
DO 160 JCOL = 1, NRHS
DO 150 JROW = 1, N
JREAL = JREAL + 1
JIMAG = JIMAG + 1
B( JROW, JCOL ) = CMPLX( RWORK( JREAL ), RWORK( JIMAG ) )
150 CONTINUE
160 CONTINUE
*
* Unscale.
*
CALL SLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )
CALL SLASRT( 'D', N, D, INFO )
CALL CLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )
*
RETURN
END IF
*
* Book-keeping and setting up some constants.
*
NLVL = INT( LOG( REAL( N ) / REAL( SMLSIZ+1 ) ) / LOG( TWO ) ) + 1
*
SMLSZP = SMLSIZ + 1
*
U = 1
VT = 1 + SMLSIZ*N
DIFL = VT + SMLSZP*N
DIFR = DIFL + NLVL*N
Z = DIFR + NLVL*N*2
C = Z + NLVL*N
S = C + N
POLES = S + N
GIVNUM = POLES + 2*NLVL*N
NRWORK = GIVNUM + 2*NLVL*N
BX = 1
*
IRWRB = NRWORK
IRWIB = IRWRB + SMLSIZ*NRHS
IRWB = IRWIB + SMLSIZ*NRHS
*
SIZEI = 1 + N
K = SIZEI + N
GIVPTR = K + N
PERM = GIVPTR + N
GIVCOL = PERM + NLVL*N
IWK = GIVCOL + NLVL*N*2
*
ST = 1
SQRE = 0
ICMPQ1 = 1
ICMPQ2 = 0
NSUB = 0
*
DO 170 I = 1, N
IF( ABS( D( I ) ).LT.EPS ) THEN
D( I ) = SIGN( EPS, D( I ) )
END IF
170 CONTINUE
*
DO 240 I = 1, NM1
IF( ( ABS( E( I ) ).LT.EPS ) .OR. ( I.EQ.NM1 ) ) THEN
NSUB = NSUB + 1
IWORK( NSUB ) = ST
*
* Subproblem found. First determine its size and then
* apply divide and conquer on it.
*
IF( I.LT.NM1 ) THEN
*
* A subproblem with E(I) small for I < NM1.
*
NSIZE = I - ST + 1
IWORK( SIZEI+NSUB-1 ) = NSIZE
ELSE IF( ABS( E( I ) ).GE.EPS ) THEN
*
* A subproblem with E(NM1) not too small but I = NM1.
*
NSIZE = N - ST + 1
IWORK( SIZEI+NSUB-1 ) = NSIZE
ELSE
*
* A subproblem with E(NM1) small. This implies an
* 1-by-1 subproblem at D(N), which is not solved
* explicitly.
*
NSIZE = I - ST + 1
IWORK( SIZEI+NSUB-1 ) = NSIZE
NSUB = NSUB + 1
IWORK( NSUB ) = N
IWORK( SIZEI+NSUB-1 ) = 1
CALL CCOPY( NRHS, B( N, 1 ), LDB, WORK( BX+NM1 ), N )
END IF
ST1 = ST - 1
IF( NSIZE.EQ.1 ) THEN
*
* This is a 1-by-1 subproblem and is not solved
* explicitly.
*
CALL CCOPY( NRHS, B( ST, 1 ), LDB, WORK( BX+ST1 ), N )
ELSE IF( NSIZE.LE.SMLSIZ ) THEN
*
* This is a small subproblem and is solved by SLASDQ.
*
CALL SLASET( 'A', NSIZE, NSIZE, ZERO, ONE,
$ RWORK( VT+ST1 ), N )
CALL SLASET( 'A', NSIZE, NSIZE, ZERO, ONE,
$ RWORK( U+ST1 ), N )
CALL SLASDQ( 'U', 0, NSIZE, NSIZE, NSIZE, 0, D( ST ),
$ E( ST ), RWORK( VT+ST1 ), N, RWORK( U+ST1 ),
$ N, RWORK( NRWORK ), 1, RWORK( NRWORK ),
$ INFO )
IF( INFO.NE.0 ) THEN
RETURN
END IF
*
* In the real version, B is passed to SLASDQ and multiplied
* internally by Q'. Here B is complex and that product is
* computed below in two steps (real and imaginary parts).
*
J = IRWB - 1
DO 190 JCOL = 1, NRHS
DO 180 JROW = ST, ST + NSIZE - 1
J = J + 1
RWORK( J ) = REAL( B( JROW, JCOL ) )
180 CONTINUE
190 CONTINUE
CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
$ RWORK( U+ST1 ), N, RWORK( IRWB ), NSIZE,
$ ZERO, RWORK( IRWRB ), NSIZE )
J = IRWB - 1
DO 210 JCOL = 1, NRHS
DO 200 JROW = ST, ST + NSIZE - 1
J = J + 1
RWORK( J ) = AIMAG( B( JROW, JCOL ) )
200 CONTINUE
210 CONTINUE
CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
$ RWORK( U+ST1 ), N, RWORK( IRWB ), NSIZE,
$ ZERO, RWORK( IRWIB ), NSIZE )
JREAL = IRWRB - 1
JIMAG = IRWIB - 1
DO 230 JCOL = 1, NRHS
DO 220 JROW = ST, ST + NSIZE - 1
JREAL = JREAL + 1
JIMAG = JIMAG + 1
B( JROW, JCOL ) = CMPLX( RWORK( JREAL ),
$ RWORK( JIMAG ) )
220 CONTINUE
230 CONTINUE
*
CALL CLACPY( 'A', NSIZE, NRHS, B( ST, 1 ), LDB,
$ WORK( BX+ST1 ), N )
ELSE
*
* A large problem. Solve it using divide and conquer.
*
CALL SLASDA( ICMPQ1, SMLSIZ, NSIZE, SQRE, D( ST ),
$ E( ST ), RWORK( U+ST1 ), N, RWORK( VT+ST1 ),
$ IWORK( K+ST1 ), RWORK( DIFL+ST1 ),
$ RWORK( DIFR+ST1 ), RWORK( Z+ST1 ),
$ RWORK( POLES+ST1 ), IWORK( GIVPTR+ST1 ),
$ IWORK( GIVCOL+ST1 ), N, IWORK( PERM+ST1 ),
$ RWORK( GIVNUM+ST1 ), RWORK( C+ST1 ),
$ RWORK( S+ST1 ), RWORK( NRWORK ),
$ IWORK( IWK ), INFO )
IF( INFO.NE.0 ) THEN
RETURN
END IF
BXST = BX + ST1
CALL CLALSA( ICMPQ2, SMLSIZ, NSIZE, NRHS, B( ST, 1 ),
$ LDB, WORK( BXST ), N, RWORK( U+ST1 ), N,
$ RWORK( VT+ST1 ), IWORK( K+ST1 ),
$ RWORK( DIFL+ST1 ), RWORK( DIFR+ST1 ),
$ RWORK( Z+ST1 ), RWORK( POLES+ST1 ),
$ IWORK( GIVPTR+ST1 ), IWORK( GIVCOL+ST1 ), N,
$ IWORK( PERM+ST1 ), RWORK( GIVNUM+ST1 ),
$ RWORK( C+ST1 ), RWORK( S+ST1 ),
$ RWORK( NRWORK ), IWORK( IWK ), INFO )
IF( INFO.NE.0 ) THEN
RETURN
END IF
END IF
ST = I + 1
END IF
240 CONTINUE
*
* Apply the singular values and treat the tiny ones as zero.
*
TOL = RCND*ABS( D( ISAMAX( N, D, 1 ) ) )
*
DO 250 I = 1, N
*
* Some of the elements in D can be negative because 1-by-1
* subproblems were not solved explicitly.
*
IF( ABS( D( I ) ).LE.TOL ) THEN
CALL CLASET( 'A', 1, NRHS, CZERO, CZERO, WORK( BX+I-1 ), N )
ELSE
RANK = RANK + 1
CALL CLASCL( 'G', 0, 0, D( I ), ONE, 1, NRHS,
$ WORK( BX+I-1 ), N, INFO )
END IF
D( I ) = ABS( D( I ) )
250 CONTINUE
*
* Now apply back the right singular vectors.
*
ICMPQ2 = 1
DO 320 I = 1, NSUB
ST = IWORK( I )
ST1 = ST - 1
NSIZE = IWORK( SIZEI+I-1 )
BXST = BX + ST1
IF( NSIZE.EQ.1 ) THEN
CALL CCOPY( NRHS, WORK( BXST ), N, B( ST, 1 ), LDB )
ELSE IF( NSIZE.LE.SMLSIZ ) THEN
*
* Since B and BX are complex, the following call to SGEMM
* is performed in two steps (real and imaginary parts).
*
* CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
* $ RWORK( VT+ST1 ), N, RWORK( BXST ), N, ZERO,
* $ B( ST, 1 ), LDB )
*
J = BXST - N - 1
JREAL = IRWB - 1
DO 270 JCOL = 1, NRHS
J = J + N
DO 260 JROW = 1, NSIZE
JREAL = JREAL + 1
RWORK( JREAL ) = REAL( WORK( J+JROW ) )
260 CONTINUE
270 CONTINUE
CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
$ RWORK( VT+ST1 ), N, RWORK( IRWB ), NSIZE, ZERO,
$ RWORK( IRWRB ), NSIZE )
J = BXST - N - 1
JIMAG = IRWB - 1
DO 290 JCOL = 1, NRHS
J = J + N
DO 280 JROW = 1, NSIZE
JIMAG = JIMAG + 1
RWORK( JIMAG ) = AIMAG( WORK( J+JROW ) )
280 CONTINUE
290 CONTINUE
CALL SGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
$ RWORK( VT+ST1 ), N, RWORK( IRWB ), NSIZE, ZERO,
$ RWORK( IRWIB ), NSIZE )
JREAL = IRWRB - 1
JIMAG = IRWIB - 1
DO 310 JCOL = 1, NRHS
DO 300 JROW = ST, ST + NSIZE - 1
JREAL = JREAL + 1
JIMAG = JIMAG + 1
B( JROW, JCOL ) = CMPLX( RWORK( JREAL ),
$ RWORK( JIMAG ) )
300 CONTINUE
310 CONTINUE
ELSE
CALL CLALSA( ICMPQ2, SMLSIZ, NSIZE, NRHS, WORK( BXST ), N,
$ B( ST, 1 ), LDB, RWORK( U+ST1 ), N,
$ RWORK( VT+ST1 ), IWORK( K+ST1 ),
$ RWORK( DIFL+ST1 ), RWORK( DIFR+ST1 ),
$ RWORK( Z+ST1 ), RWORK( POLES+ST1 ),
$ IWORK( GIVPTR+ST1 ), IWORK( GIVCOL+ST1 ), N,
$ IWORK( PERM+ST1 ), RWORK( GIVNUM+ST1 ),
$ RWORK( C+ST1 ), RWORK( S+ST1 ),
$ RWORK( NRWORK ), IWORK( IWK ), INFO )
IF( INFO.NE.0 ) THEN
RETURN
END IF
END IF
320 CONTINUE
*
* Unscale and sort the singular values.
*
CALL SLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )
CALL SLASRT( 'D', N, D, INFO )
CALL CLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )
*
RETURN
*
* End of CLALSD
*
END
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?