📄 zlalsd.f
字号:
OPS = OPS + DOPBL3( 'DGEMM ', N, NRHS, N ) CALL DGEMM( '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 ) = DIMAG( B( JROW, JCOL ) ) 130 CONTINUE 140 CONTINUE OPS = OPS + DOPBL3( 'DGEMM ', N, NRHS, N ) CALL DGEMM( '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 ) = DCMPLX( RWORK( JREAL ), $ RWORK( JIMAG ) ) 150 CONTINUE 160 CONTINUE** Unscale.* OPS = OPS + DBLE( N + 6*N*NRHS ) CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO ) CALL DLASRT( 'D', N, D, INFO ) CALL ZLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )* RETURN END IF** Book-keeping and setting up some constants.* NLVL = INT( LOG( DBLE( N ) / DBLE( 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 ZCOPY( 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 ZCOPY( NRHS, B( ST, 1 ), LDB, WORK( BX+ST1 ), N ) ELSE IF( NSIZE.LE.SMLSIZ ) THEN** This is a small subproblem and is solved by DLASDQ.* CALL DLASET( 'A', NSIZE, NSIZE, ZERO, ONE, $ RWORK( VT+ST1 ), N ) CALL DLASET( 'A', NSIZE, NSIZE, ZERO, ONE, $ RWORK( U+ST1 ), N ) CALL DLASDQ( '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 DLASDQ 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 ) = DBLE( B( JROW, JCOL ) ) 180 CONTINUE 190 CONTINUE OPS = OPS + DOPBL3( 'DGEMM ', NSIZE, NRHS, NSIZE ) CALL DGEMM( '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 ) = DIMAG( B( JROW, JCOL ) ) 200 CONTINUE 210 CONTINUE OPS = OPS + DOPBL3( 'DGEMM ', NSIZE, NRHS, NSIZE ) CALL DGEMM( '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 ) = DCMPLX( RWORK( JREAL ), $ RWORK( JIMAG ) ) 220 CONTINUE 230 CONTINUE* CALL ZLACPY( 'A', NSIZE, NRHS, B( ST, 1 ), LDB, $ WORK( BX+ST1 ), N ) ELSE** A large problem. Solve it using divide and conquer.* CALL DLASDA( 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 ZLALSA( 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.* OPS = OPS + DBLE( 1 ) TOL = RCOND*ABS( D( IDAMAX( 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 ZLASET( 'A', 1, NRHS, CZERO, CZERO, WORK( BX+I-1 ), N ) ELSE RANK = RANK + 1 OPS = OPS + DBLE( 6*NRHS ) CALL ZLASCL( '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 ZCOPY( NRHS, WORK( BXST ), N, B( ST, 1 ), LDB ) ELSE IF( NSIZE.LE.SMLSIZ ) THEN** Since B and BX are complex, the following call to DGEMM* is performed in two steps (real and imaginary parts).** CALL DGEMM( '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 ) = DBLE( WORK( J+JROW ) ) 260 CONTINUE 270 CONTINUE OPS = OPS + DOPBL3( 'DGEMM ', NSIZE, NRHS, NSIZE ) CALL DGEMM( '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 ) = DIMAG( WORK( J+JROW ) ) 280 CONTINUE 290 CONTINUE OPS = OPS + DOPBL3( 'DGEMM ', NSIZE, NRHS, NSIZE ) CALL DGEMM( '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 ) = DCMPLX( RWORK( JREAL ), $ RWORK( JIMAG ) ) 300 CONTINUE 310 CONTINUE ELSE CALL ZLALSA( 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.* OPS = OPS + DBLE( N + 6*N*NRHS ) CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO ) CALL DLASRT( 'D', N, D, INFO ) CALL ZLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )* RETURN** End of ZLALSD* END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -