root / src / lapack / double / dlasd8.f @ 2
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 |