Statistiques
| Révision :

root / src / lapack / double / dlasd8.f @ 1

Historique | Voir | Annoter | Télécharger (8,6 ko)

1 1 equemene
      SUBROUTINE DLASD8( ICOMPQ, K, D, Z, VF, VL, DIFL, DIFR, LDDIFR,
2 1 equemene
     $                   DSIGMA, WORK, INFO )
3 1 equemene
*
4 1 equemene
*  -- LAPACK auxiliary routine (version 3.2.2) --
5 1 equemene
*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
6 1 equemene
*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
7 1 equemene
*     June 2010
8 1 equemene
*
9 1 equemene
*     .. Scalar Arguments ..
10 1 equemene
      INTEGER            ICOMPQ, INFO, K, LDDIFR
11 1 equemene
*     ..
12 1 equemene
*     .. Array Arguments ..
13 1 equemene
      DOUBLE PRECISION   D( * ), DIFL( * ), DIFR( LDDIFR, * ),
14 1 equemene
     $                   DSIGMA( * ), VF( * ), VL( * ), WORK( * ),
15 1 equemene
     $                   Z( * )
16 1 equemene
*     ..
17 1 equemene
*
18 1 equemene
*  Purpose
19 1 equemene
*  =======
20 1 equemene
*
21 1 equemene
*  DLASD8 finds the square roots of the roots of the secular equation,
22 1 equemene
*  as defined by the values in DSIGMA and Z. It makes the appropriate
23 1 equemene
*  calls to DLASD4, and stores, for each  element in D, the distance
24 1 equemene
*  to its two nearest poles (elements in DSIGMA). It also updates
25 1 equemene
*  the arrays VF and VL, the first and last components of all the
26 1 equemene
*  right singular vectors of the original bidiagonal matrix.
27 1 equemene
*
28 1 equemene
*  DLASD8 is called from DLASD6.
29 1 equemene
*
30 1 equemene
*  Arguments
31 1 equemene
*  =========
32 1 equemene
*
33 1 equemene
*  ICOMPQ  (input) INTEGER
34 1 equemene
*          Specifies whether singular vectors are to be computed in
35 1 equemene
*          factored form in the calling routine:
36 1 equemene
*          = 0: Compute singular values only.
37 1 equemene
*          = 1: Compute singular vectors in factored form as well.
38 1 equemene
*
39 1 equemene
*  K       (input) INTEGER
40 1 equemene
*          The number of terms in the rational function to be solved
41 1 equemene
*          by DLASD4.  K >= 1.
42 1 equemene
*
43 1 equemene
*  D       (output) DOUBLE PRECISION array, dimension ( K )
44 1 equemene
*          On output, D contains the updated singular values.
45 1 equemene
*
46 1 equemene
*  Z       (input/output) DOUBLE PRECISION array, dimension ( K )
47 1 equemene
*          On entry, the first K elements of this array contain the
48 1 equemene
*          components of the deflation-adjusted updating row vector.
49 1 equemene
*          On exit, Z is updated.
50 1 equemene
*
51 1 equemene
*  VF      (input/output) DOUBLE PRECISION array, dimension ( K )
52 1 equemene
*          On entry, VF contains  information passed through DBEDE8.
53 1 equemene
*          On exit, VF contains the first K components of the first
54 1 equemene
*          components of all right singular vectors of the bidiagonal
55 1 equemene
*          matrix.
56 1 equemene
*
57 1 equemene
*  VL      (input/output) DOUBLE PRECISION array, dimension ( K )
58 1 equemene
*          On entry, VL contains  information passed through DBEDE8.
59 1 equemene
*          On exit, VL contains the first K components of the last
60 1 equemene
*          components of all right singular vectors of the bidiagonal
61 1 equemene
*          matrix.
62 1 equemene
*
63 1 equemene
*  DIFL    (output) DOUBLE PRECISION array, dimension ( K )
64 1 equemene
*          On exit, DIFL(I) = D(I) - DSIGMA(I).
65 1 equemene
*
66 1 equemene
*  DIFR    (output) DOUBLE PRECISION array,
67 1 equemene
*                   dimension ( LDDIFR, 2 ) if ICOMPQ = 1 and
68 1 equemene
*                   dimension ( K ) if ICOMPQ = 0.
69 1 equemene
*          On exit, DIFR(I,1) = D(I) - DSIGMA(I+1), DIFR(K,1) is not
70 1 equemene
*          defined and will not be referenced.
71 1 equemene
*
72 1 equemene
*          If ICOMPQ = 1, DIFR(1:K,2) is an array containing the
73 1 equemene
*          normalizing factors for the right singular vector matrix.
74 1 equemene
*
75 1 equemene
*  LDDIFR  (input) INTEGER
76 1 equemene
*          The leading dimension of DIFR, must be at least K.
77 1 equemene
*
78 1 equemene
*  DSIGMA  (input/output) DOUBLE PRECISION array, dimension ( K )
79 1 equemene
*          On entry, the first K elements of this array contain the old
80 1 equemene
*          roots of the deflated updating problem.  These are the poles
81 1 equemene
*          of the secular equation.
82 1 equemene
*          On exit, the elements of DSIGMA may be very slightly altered
83 1 equemene
*          in value.
84 1 equemene
*
85 1 equemene
*  WORK    (workspace) DOUBLE PRECISION array, dimension at least 3 * K
86 1 equemene
*
87 1 equemene
*  INFO    (output) INTEGER
88 1 equemene
*          = 0:  successful exit.
89 1 equemene
*          < 0:  if INFO = -i, the i-th argument had an illegal value.
90 1 equemene
*          > 0:  if INFO = 1, a singular value did not converge
91 1 equemene
*
92 1 equemene
*  Further Details
93 1 equemene
*  ===============
94 1 equemene
*
95 1 equemene
*  Based on contributions by
96 1 equemene
*     Ming Gu and Huan Ren, Computer Science Division, University of
97 1 equemene
*     California at Berkeley, USA
98 1 equemene
*
99 1 equemene
*  =====================================================================
100 1 equemene
*
101 1 equemene
*     .. Parameters ..
102 1 equemene
      DOUBLE PRECISION   ONE
103 1 equemene
      PARAMETER          ( ONE = 1.0D+0 )
104 1 equemene
*     ..
105 1 equemene
*     .. Local Scalars ..
106 1 equemene
      INTEGER            I, IWK1, IWK2, IWK2I, IWK3, IWK3I, J
107 1 equemene
      DOUBLE PRECISION   DIFLJ, DIFRJ, DJ, DSIGJ, DSIGJP, RHO, TEMP
108 1 equemene
*     ..
109 1 equemene
*     .. External Subroutines ..
110 1 equemene
      EXTERNAL           DCOPY, DLASCL, DLASD4, DLASET, XERBLA
111 1 equemene
*     ..
112 1 equemene
*     .. External Functions ..
113 1 equemene
      DOUBLE PRECISION   DDOT, DLAMC3, DNRM2
114 1 equemene
      EXTERNAL           DDOT, DLAMC3, DNRM2
115 1 equemene
*     ..
116 1 equemene
*     .. Intrinsic Functions ..
117 1 equemene
      INTRINSIC          ABS, SIGN, SQRT
118 1 equemene
*     ..
119 1 equemene
*     .. Executable Statements ..
120 1 equemene
*
121 1 equemene
*     Test the input parameters.
122 1 equemene
*
123 1 equemene
      INFO = 0
124 1 equemene
*
125 1 equemene
      IF( ( ICOMPQ.LT.0 ) .OR. ( ICOMPQ.GT.1 ) ) THEN
126 1 equemene
         INFO = -1
127 1 equemene
      ELSE IF( K.LT.1 ) THEN
128 1 equemene
         INFO = -2
129 1 equemene
      ELSE IF( LDDIFR.LT.K ) THEN
130 1 equemene
         INFO = -9
131 1 equemene
      END IF
132 1 equemene
      IF( INFO.NE.0 ) THEN
133 1 equemene
         CALL XERBLA( 'DLASD8', -INFO )
134 1 equemene
         RETURN
135 1 equemene
      END IF
136 1 equemene
*
137 1 equemene
*     Quick return if possible
138 1 equemene
*
139 1 equemene
      IF( K.EQ.1 ) THEN
140 1 equemene
         D( 1 ) = ABS( Z( 1 ) )
141 1 equemene
         DIFL( 1 ) = D( 1 )
142 1 equemene
         IF( ICOMPQ.EQ.1 ) THEN
143 1 equemene
            DIFL( 2 ) = ONE
144 1 equemene
            DIFR( 1, 2 ) = ONE
145 1 equemene
         END IF
146 1 equemene
         RETURN
147 1 equemene
      END IF
148 1 equemene
*
149 1 equemene
*     Modify values DSIGMA(i) to make sure all DSIGMA(i)-DSIGMA(j) can
150 1 equemene
*     be computed with high relative accuracy (barring over/underflow).
151 1 equemene
*     This is a problem on machines without a guard digit in
152 1 equemene
*     add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2).
153 1 equemene
*     The following code replaces DSIGMA(I) by 2*DSIGMA(I)-DSIGMA(I),
154 1 equemene
*     which on any of these machines zeros out the bottommost
155 1 equemene
*     bit of DSIGMA(I) if it is 1; this makes the subsequent
156 1 equemene
*     subtractions DSIGMA(I)-DSIGMA(J) unproblematic when cancellation
157 1 equemene
*     occurs. On binary machines with a guard digit (almost all
158 1 equemene
*     machines) it does not change DSIGMA(I) at all. On hexadecimal
159 1 equemene
*     and decimal machines with a guard digit, it slightly
160 1 equemene
*     changes the bottommost bits of DSIGMA(I). It does not account
161 1 equemene
*     for hexadecimal or decimal machines without guard digits
162 1 equemene
*     (we know of none). We use a subroutine call to compute
163 1 equemene
*     2*DLAMBDA(I) to prevent optimizing compilers from eliminating
164 1 equemene
*     this code.
165 1 equemene
*
166 1 equemene
      DO 10 I = 1, K
167 1 equemene
         DSIGMA( I ) = DLAMC3( DSIGMA( I ), DSIGMA( I ) ) - DSIGMA( I )
168 1 equemene
   10 CONTINUE
169 1 equemene
*
170 1 equemene
*     Book keeping.
171 1 equemene
*
172 1 equemene
      IWK1 = 1
173 1 equemene
      IWK2 = IWK1 + K
174 1 equemene
      IWK3 = IWK2 + K
175 1 equemene
      IWK2I = IWK2 - 1
176 1 equemene
      IWK3I = IWK3 - 1
177 1 equemene
*
178 1 equemene
*     Normalize Z.
179 1 equemene
*
180 1 equemene
      RHO = DNRM2( K, Z, 1 )
181 1 equemene
      CALL DLASCL( 'G', 0, 0, RHO, ONE, K, 1, Z, K, INFO )
182 1 equemene
      RHO = RHO*RHO
183 1 equemene
*
184 1 equemene
*     Initialize WORK(IWK3).
185 1 equemene
*
186 1 equemene
      CALL DLASET( 'A', K, 1, ONE, ONE, WORK( IWK3 ), K )
187 1 equemene
*
188 1 equemene
*     Compute the updated singular values, the arrays DIFL, DIFR,
189 1 equemene
*     and the updated Z.
190 1 equemene
*
191 1 equemene
      DO 40 J = 1, K
192 1 equemene
         CALL DLASD4( K, J, DSIGMA, Z, WORK( IWK1 ), RHO, D( J ),
193 1 equemene
     $                WORK( IWK2 ), INFO )
194 1 equemene
*
195 1 equemene
*        If the root finder fails, the computation is terminated.
196 1 equemene
*
197 1 equemene
         IF( INFO.NE.0 ) THEN
198 1 equemene
            RETURN
199 1 equemene
         END IF
200 1 equemene
         WORK( IWK3I+J ) = WORK( IWK3I+J )*WORK( J )*WORK( IWK2I+J )
201 1 equemene
         DIFL( J ) = -WORK( J )
202 1 equemene
         DIFR( J, 1 ) = -WORK( J+1 )
203 1 equemene
         DO 20 I = 1, J - 1
204 1 equemene
            WORK( IWK3I+I ) = WORK( IWK3I+I )*WORK( I )*
205 1 equemene
     $                        WORK( IWK2I+I ) / ( DSIGMA( I )-
206 1 equemene
     $                        DSIGMA( J ) ) / ( DSIGMA( I )+
207 1 equemene
     $                        DSIGMA( J ) )
208 1 equemene
   20    CONTINUE
209 1 equemene
         DO 30 I = J + 1, K
210 1 equemene
            WORK( IWK3I+I ) = WORK( IWK3I+I )*WORK( I )*
211 1 equemene
     $                        WORK( IWK2I+I ) / ( DSIGMA( I )-
212 1 equemene
     $                        DSIGMA( J ) ) / ( DSIGMA( I )+
213 1 equemene
     $                        DSIGMA( J ) )
214 1 equemene
   30    CONTINUE
215 1 equemene
   40 CONTINUE
216 1 equemene
*
217 1 equemene
*     Compute updated Z.
218 1 equemene
*
219 1 equemene
      DO 50 I = 1, K
220 1 equemene
         Z( I ) = SIGN( SQRT( ABS( WORK( IWK3I+I ) ) ), Z( I ) )
221 1 equemene
   50 CONTINUE
222 1 equemene
*
223 1 equemene
*     Update VF and VL.
224 1 equemene
*
225 1 equemene
      DO 80 J = 1, K
226 1 equemene
         DIFLJ = DIFL( J )
227 1 equemene
         DJ = D( J )
228 1 equemene
         DSIGJ = -DSIGMA( J )
229 1 equemene
         IF( J.LT.K ) THEN
230 1 equemene
            DIFRJ = -DIFR( J, 1 )
231 1 equemene
            DSIGJP = -DSIGMA( J+1 )
232 1 equemene
         END IF
233 1 equemene
         WORK( J ) = -Z( J ) / DIFLJ / ( DSIGMA( J )+DJ )
234 1 equemene
         DO 60 I = 1, J - 1
235 1 equemene
            WORK( I ) = Z( I ) / ( DLAMC3( DSIGMA( I ), DSIGJ )-DIFLJ )
236 1 equemene
     $                   / ( DSIGMA( I )+DJ )
237 1 equemene
   60    CONTINUE
238 1 equemene
         DO 70 I = J + 1, K
239 1 equemene
            WORK( I ) = Z( I ) / ( DLAMC3( DSIGMA( I ), DSIGJP )+DIFRJ )
240 1 equemene
     $                   / ( DSIGMA( I )+DJ )
241 1 equemene
   70    CONTINUE
242 1 equemene
         TEMP = DNRM2( K, WORK, 1 )
243 1 equemene
         WORK( IWK2I+J ) = DDOT( K, WORK, 1, VF, 1 ) / TEMP
244 1 equemene
         WORK( IWK3I+J ) = DDOT( K, WORK, 1, VL, 1 ) / TEMP
245 1 equemene
         IF( ICOMPQ.EQ.1 ) THEN
246 1 equemene
            DIFR( J, 2 ) = TEMP
247 1 equemene
         END IF
248 1 equemene
   80 CONTINUE
249 1 equemene
*
250 1 equemene
      CALL DCOPY( K, WORK( IWK2 ), 1, VF, 1 )
251 1 equemene
      CALL DCOPY( K, WORK( IWK3 ), 1, VL, 1 )
252 1 equemene
*
253 1 equemene
      RETURN
254 1 equemene
*
255 1 equemene
*     End of DLASD8
256 1 equemene
*
257 1 equemene
      END