dlasd3.f.html
来自「famous linear algebra library (LAPACK) p」· HTML 代码 · 共 383 行 · 第 1/2 页
HTML
383 行
ELSE IF( LDQ.LT.K ) THEN
INFO = -7
ELSE IF( LDU.LT.N ) THEN
INFO = -10
ELSE IF( LDU2.LT.N ) THEN
INFO = -12
ELSE IF( LDVT.LT.M ) THEN
INFO = -14
ELSE IF( LDVT2.LT.M ) THEN
INFO = -16
END IF
IF( INFO.NE.0 ) THEN
CALL <a name="XERBLA.186"></a><a href="xerbla.f.html#XERBLA.1">XERBLA</a>( <span class="string">'<a name="DLASD3.186"></a><a href="dlasd3.f.html#DLASD3.1">DLASD3</a>'</span>, -INFO )
RETURN
END IF
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Quick return if possible
</span><span class="comment">*</span><span class="comment">
</span> IF( K.EQ.1 ) THEN
D( 1 ) = ABS( Z( 1 ) )
CALL DCOPY( M, VT2( 1, 1 ), LDVT2, VT( 1, 1 ), LDVT )
IF( Z( 1 ).GT.ZERO ) THEN
CALL DCOPY( N, U2( 1, 1 ), 1, U( 1, 1 ), 1 )
ELSE
DO 10 I = 1, N
U( I, 1 ) = -U2( I, 1 )
10 CONTINUE
END IF
RETURN
END IF
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Modify values DSIGMA(i) to make sure all DSIGMA(i)-DSIGMA(j) can
</span><span class="comment">*</span><span class="comment"> be computed with high relative accuracy (barring over/underflow).
</span><span class="comment">*</span><span class="comment"> This is a problem on machines without a guard digit in
</span><span class="comment">*</span><span class="comment"> add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2).
</span><span class="comment">*</span><span class="comment"> The following code replaces DSIGMA(I) by 2*DSIGMA(I)-DSIGMA(I),
</span><span class="comment">*</span><span class="comment"> which on any of these machines zeros out the bottommost
</span><span class="comment">*</span><span class="comment"> bit of DSIGMA(I) if it is 1; this makes the subsequent
</span><span class="comment">*</span><span class="comment"> subtractions DSIGMA(I)-DSIGMA(J) unproblematic when cancellation
</span><span class="comment">*</span><span class="comment"> occurs. On binary machines with a guard digit (almost all
</span><span class="comment">*</span><span class="comment"> machines) it does not change DSIGMA(I) at all. On hexadecimal
</span><span class="comment">*</span><span class="comment"> and decimal machines with a guard digit, it slightly
</span><span class="comment">*</span><span class="comment"> changes the bottommost bits of DSIGMA(I). It does not account
</span><span class="comment">*</span><span class="comment"> for hexadecimal or decimal machines without guard digits
</span><span class="comment">*</span><span class="comment"> (we know of none). We use a subroutine call to compute
</span><span class="comment">*</span><span class="comment"> 2*DSIGMA(I) to prevent optimizing compilers from eliminating
</span><span class="comment">*</span><span class="comment"> this code.
</span><span class="comment">*</span><span class="comment">
</span> DO 20 I = 1, K
DSIGMA( I ) = <a name="DLAMC3.223"></a><a href="dlamch.f.html#DLAMC3.574">DLAMC3</a>( DSIGMA( I ), DSIGMA( I ) ) - DSIGMA( I )
20 CONTINUE
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Keep a copy of Z.
</span><span class="comment">*</span><span class="comment">
</span> CALL DCOPY( K, Z, 1, Q, 1 )
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Normalize Z.
</span><span class="comment">*</span><span class="comment">
</span> RHO = DNRM2( K, Z, 1 )
CALL <a name="DLASCL.233"></a><a href="dlascl.f.html#DLASCL.1">DLASCL</a>( <span class="string">'G'</span>, 0, 0, RHO, ONE, K, 1, Z, K, INFO )
RHO = RHO*RHO
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Find the new singular values.
</span><span class="comment">*</span><span class="comment">
</span> DO 30 J = 1, K
CALL <a name="DLASD4.239"></a><a href="dlasd4.f.html#DLASD4.1">DLASD4</a>( K, J, DSIGMA, Z, U( 1, J ), RHO, D( J ),
$ VT( 1, J ), INFO )
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> If the zero finder fails, the computation is terminated.
</span><span class="comment">*</span><span class="comment">
</span> IF( INFO.NE.0 ) THEN
RETURN
END IF
30 CONTINUE
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Compute updated Z.
</span><span class="comment">*</span><span class="comment">
</span> DO 60 I = 1, K
Z( I ) = U( I, K )*VT( I, K )
DO 40 J = 1, I - 1
Z( I ) = Z( I )*( U( I, J )*VT( I, J ) /
$ ( DSIGMA( I )-DSIGMA( J ) ) /
$ ( DSIGMA( I )+DSIGMA( J ) ) )
40 CONTINUE
DO 50 J = I, K - 1
Z( I ) = Z( I )*( U( I, J )*VT( I, J ) /
$ ( DSIGMA( I )-DSIGMA( J+1 ) ) /
$ ( DSIGMA( I )+DSIGMA( J+1 ) ) )
50 CONTINUE
Z( I ) = SIGN( SQRT( ABS( Z( I ) ) ), Q( I, 1 ) )
60 CONTINUE
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Compute left singular vectors of the modified diagonal matrix,
</span><span class="comment">*</span><span class="comment"> and store related information for the right singular vectors.
</span><span class="comment">*</span><span class="comment">
</span> DO 90 I = 1, K
VT( 1, I ) = Z( 1 ) / U( 1, I ) / VT( 1, I )
U( 1, I ) = NEGONE
DO 70 J = 2, K
VT( J, I ) = Z( J ) / U( J, I ) / VT( J, I )
U( J, I ) = DSIGMA( J )*VT( J, I )
70 CONTINUE
TEMP = DNRM2( K, U( 1, I ), 1 )
Q( 1, I ) = U( 1, I ) / TEMP
DO 80 J = 2, K
JC = IDXC( J )
Q( J, I ) = U( JC, I ) / TEMP
80 CONTINUE
90 CONTINUE
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Update the left singular vector matrix.
</span><span class="comment">*</span><span class="comment">
</span> IF( K.EQ.2 ) THEN
CALL DGEMM( <span class="string">'N'</span>, <span class="string">'N'</span>, N, K, K, ONE, U2, LDU2, Q, LDQ, ZERO, U,
$ LDU )
GO TO 100
END IF
IF( CTOT( 1 ).GT.0 ) THEN
CALL DGEMM( <span class="string">'N'</span>, <span class="string">'N'</span>, NL, K, CTOT( 1 ), ONE, U2( 1, 2 ), LDU2,
$ Q( 2, 1 ), LDQ, ZERO, U( 1, 1 ), LDU )
IF( CTOT( 3 ).GT.0 ) THEN
KTEMP = 2 + CTOT( 1 ) + CTOT( 2 )
CALL DGEMM( <span class="string">'N'</span>, <span class="string">'N'</span>, NL, K, CTOT( 3 ), ONE, U2( 1, KTEMP ),
$ LDU2, Q( KTEMP, 1 ), LDQ, ONE, U( 1, 1 ), LDU )
END IF
ELSE IF( CTOT( 3 ).GT.0 ) THEN
KTEMP = 2 + CTOT( 1 ) + CTOT( 2 )
CALL DGEMM( <span class="string">'N'</span>, <span class="string">'N'</span>, NL, K, CTOT( 3 ), ONE, U2( 1, KTEMP ),
$ LDU2, Q( KTEMP, 1 ), LDQ, ZERO, U( 1, 1 ), LDU )
ELSE
CALL <a name="DLACPY.304"></a><a href="dlacpy.f.html#DLACPY.1">DLACPY</a>( <span class="string">'F'</span>, NL, K, U2, LDU2, U, LDU )
END IF
CALL DCOPY( K, Q( 1, 1 ), LDQ, U( NLP1, 1 ), LDU )
KTEMP = 2 + CTOT( 1 )
CTEMP = CTOT( 2 ) + CTOT( 3 )
CALL DGEMM( <span class="string">'N'</span>, <span class="string">'N'</span>, NR, K, CTEMP, ONE, U2( NLP2, KTEMP ), LDU2,
$ Q( KTEMP, 1 ), LDQ, ZERO, U( NLP2, 1 ), LDU )
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Generate the right singular vectors.
</span><span class="comment">*</span><span class="comment">
</span> 100 CONTINUE
DO 120 I = 1, K
TEMP = DNRM2( K, VT( 1, I ), 1 )
Q( I, 1 ) = VT( 1, I ) / TEMP
DO 110 J = 2, K
JC = IDXC( J )
Q( I, J ) = VT( JC, I ) / TEMP
110 CONTINUE
120 CONTINUE
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> Update the right singular vector matrix.
</span><span class="comment">*</span><span class="comment">
</span> IF( K.EQ.2 ) THEN
CALL DGEMM( <span class="string">'N'</span>, <span class="string">'N'</span>, K, M, K, ONE, Q, LDQ, VT2, LDVT2, ZERO,
$ VT, LDVT )
RETURN
END IF
KTEMP = 1 + CTOT( 1 )
CALL DGEMM( <span class="string">'N'</span>, <span class="string">'N'</span>, K, NLP1, KTEMP, ONE, Q( 1, 1 ), LDQ,
$ VT2( 1, 1 ), LDVT2, ZERO, VT( 1, 1 ), LDVT )
KTEMP = 2 + CTOT( 1 ) + CTOT( 2 )
IF( KTEMP.LE.LDVT2 )
$ CALL DGEMM( <span class="string">'N'</span>, <span class="string">'N'</span>, K, NLP1, CTOT( 3 ), ONE, Q( 1, KTEMP ),
$ LDQ, VT2( KTEMP, 1 ), LDVT2, ONE, VT( 1, 1 ),
$ LDVT )
<span class="comment">*</span><span class="comment">
</span> KTEMP = CTOT( 1 ) + 1
NRP1 = NR + SQRE
IF( KTEMP.GT.1 ) THEN
DO 130 I = 1, K
Q( I, KTEMP ) = Q( I, 1 )
130 CONTINUE
DO 140 I = NLP2, M
VT2( KTEMP, I ) = VT2( 1, I )
140 CONTINUE
END IF
CTEMP = 1 + CTOT( 2 ) + CTOT( 3 )
CALL DGEMM( <span class="string">'N'</span>, <span class="string">'N'</span>, K, NRP1, CTEMP, ONE, Q( 1, KTEMP ), LDQ,
$ VT2( KTEMP, NLP2 ), LDVT2, ZERO, VT( 1, NLP2 ), LDVT )
<span class="comment">*</span><span class="comment">
</span> RETURN
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment"> End of <a name="DLASD3.356"></a><a href="dlasd3.f.html#DLASD3.1">DLASD3</a>
</span><span class="comment">*</span><span class="comment">
</span> END
</pre>
</body>
</html>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?