root / src / lapack / double / dlaed6.f @ 1
Historique | Voir | Annoter | Télécharger (9,39 ko)
1 | 1 | equemene | SUBROUTINE DLAED6( KNITER, ORGATI, RHO, D, Z, FINIT, TAU, INFO ) |
---|---|---|---|
2 | 1 | equemene | * |
3 | 1 | equemene | * -- LAPACK routine (version 3.2) -- |
4 | 1 | equemene | * -- LAPACK is a software package provided by Univ. of Tennessee, -- |
5 | 1 | equemene | * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- |
6 | 1 | equemene | * February 2007 |
7 | 1 | equemene | * |
8 | 1 | equemene | * .. Scalar Arguments .. |
9 | 1 | equemene | LOGICAL ORGATI |
10 | 1 | equemene | INTEGER INFO, KNITER |
11 | 1 | equemene | DOUBLE PRECISION FINIT, RHO, TAU |
12 | 1 | equemene | * .. |
13 | 1 | equemene | * .. Array Arguments .. |
14 | 1 | equemene | DOUBLE PRECISION D( 3 ), Z( 3 ) |
15 | 1 | equemene | * .. |
16 | 1 | equemene | * |
17 | 1 | equemene | * Purpose |
18 | 1 | equemene | * ======= |
19 | 1 | equemene | * |
20 | 1 | equemene | * DLAED6 computes the positive or negative root (closest to the origin) |
21 | 1 | equemene | * of |
22 | 1 | equemene | * z(1) z(2) z(3) |
23 | 1 | equemene | * f(x) = rho + --------- + ---------- + --------- |
24 | 1 | equemene | * d(1)-x d(2)-x d(3)-x |
25 | 1 | equemene | * |
26 | 1 | equemene | * It is assumed that |
27 | 1 | equemene | * |
28 | 1 | equemene | * if ORGATI = .true. the root is between d(2) and d(3); |
29 | 1 | equemene | * otherwise it is between d(1) and d(2) |
30 | 1 | equemene | * |
31 | 1 | equemene | * This routine will be called by DLAED4 when necessary. In most cases, |
32 | 1 | equemene | * the root sought is the smallest in magnitude, though it might not be |
33 | 1 | equemene | * in some extremely rare situations. |
34 | 1 | equemene | * |
35 | 1 | equemene | * Arguments |
36 | 1 | equemene | * ========= |
37 | 1 | equemene | * |
38 | 1 | equemene | * KNITER (input) INTEGER |
39 | 1 | equemene | * Refer to DLAED4 for its significance. |
40 | 1 | equemene | * |
41 | 1 | equemene | * ORGATI (input) LOGICAL |
42 | 1 | equemene | * If ORGATI is true, the needed root is between d(2) and |
43 | 1 | equemene | * d(3); otherwise it is between d(1) and d(2). See |
44 | 1 | equemene | * DLAED4 for further details. |
45 | 1 | equemene | * |
46 | 1 | equemene | * RHO (input) DOUBLE PRECISION |
47 | 1 | equemene | * Refer to the equation f(x) above. |
48 | 1 | equemene | * |
49 | 1 | equemene | * D (input) DOUBLE PRECISION array, dimension (3) |
50 | 1 | equemene | * D satisfies d(1) < d(2) < d(3). |
51 | 1 | equemene | * |
52 | 1 | equemene | * Z (input) DOUBLE PRECISION array, dimension (3) |
53 | 1 | equemene | * Each of the elements in z must be positive. |
54 | 1 | equemene | * |
55 | 1 | equemene | * FINIT (input) DOUBLE PRECISION |
56 | 1 | equemene | * The value of f at 0. It is more accurate than the one |
57 | 1 | equemene | * evaluated inside this routine (if someone wants to do |
58 | 1 | equemene | * so). |
59 | 1 | equemene | * |
60 | 1 | equemene | * TAU (output) DOUBLE PRECISION |
61 | 1 | equemene | * The root of the equation f(x). |
62 | 1 | equemene | * |
63 | 1 | equemene | * INFO (output) INTEGER |
64 | 1 | equemene | * = 0: successful exit |
65 | 1 | equemene | * > 0: if INFO = 1, failure to converge |
66 | 1 | equemene | * |
67 | 1 | equemene | * Further Details |
68 | 1 | equemene | * =============== |
69 | 1 | equemene | * |
70 | 1 | equemene | * 30/06/99: Based on contributions by |
71 | 1 | equemene | * Ren-Cang Li, Computer Science Division, University of California |
72 | 1 | equemene | * at Berkeley, USA |
73 | 1 | equemene | * |
74 | 1 | equemene | * 10/02/03: This version has a few statements commented out for thread |
75 | 1 | equemene | * safety (machine parameters are computed on each entry). SJH. |
76 | 1 | equemene | * |
77 | 1 | equemene | * 05/10/06: Modified from a new version of Ren-Cang Li, use |
78 | 1 | equemene | * Gragg-Thornton-Warner cubic convergent scheme for better stability. |
79 | 1 | equemene | * |
80 | 1 | equemene | * ===================================================================== |
81 | 1 | equemene | * |
82 | 1 | equemene | * .. Parameters .. |
83 | 1 | equemene | INTEGER MAXIT |
84 | 1 | equemene | PARAMETER ( MAXIT = 40 ) |
85 | 1 | equemene | DOUBLE PRECISION ZERO, ONE, TWO, THREE, FOUR, EIGHT |
86 | 1 | equemene | PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0, |
87 | 1 | equemene | $ THREE = 3.0D0, FOUR = 4.0D0, EIGHT = 8.0D0 ) |
88 | 1 | equemene | * .. |
89 | 1 | equemene | * .. External Functions .. |
90 | 1 | equemene | DOUBLE PRECISION DLAMCH |
91 | 1 | equemene | EXTERNAL DLAMCH |
92 | 1 | equemene | * .. |
93 | 1 | equemene | * .. Local Arrays .. |
94 | 1 | equemene | DOUBLE PRECISION DSCALE( 3 ), ZSCALE( 3 ) |
95 | 1 | equemene | * .. |
96 | 1 | equemene | * .. Local Scalars .. |
97 | 1 | equemene | LOGICAL SCALE |
98 | 1 | equemene | INTEGER I, ITER, NITER |
99 | 1 | equemene | DOUBLE PRECISION A, B, BASE, C, DDF, DF, EPS, ERRETM, ETA, F, |
100 | 1 | equemene | $ FC, SCLFAC, SCLINV, SMALL1, SMALL2, SMINV1, |
101 | 1 | equemene | $ SMINV2, TEMP, TEMP1, TEMP2, TEMP3, TEMP4, |
102 | 1 | equemene | $ LBD, UBD |
103 | 1 | equemene | * .. |
104 | 1 | equemene | * .. Intrinsic Functions .. |
105 | 1 | equemene | INTRINSIC ABS, INT, LOG, MAX, MIN, SQRT |
106 | 1 | equemene | * .. |
107 | 1 | equemene | * .. Executable Statements .. |
108 | 1 | equemene | * |
109 | 1 | equemene | INFO = 0 |
110 | 1 | equemene | * |
111 | 1 | equemene | IF( ORGATI ) THEN |
112 | 1 | equemene | LBD = D(2) |
113 | 1 | equemene | UBD = D(3) |
114 | 1 | equemene | ELSE |
115 | 1 | equemene | LBD = D(1) |
116 | 1 | equemene | UBD = D(2) |
117 | 1 | equemene | END IF |
118 | 1 | equemene | IF( FINIT .LT. ZERO )THEN |
119 | 1 | equemene | LBD = ZERO |
120 | 1 | equemene | ELSE |
121 | 1 | equemene | UBD = ZERO |
122 | 1 | equemene | END IF |
123 | 1 | equemene | * |
124 | 1 | equemene | NITER = 1 |
125 | 1 | equemene | TAU = ZERO |
126 | 1 | equemene | IF( KNITER.EQ.2 ) THEN |
127 | 1 | equemene | IF( ORGATI ) THEN |
128 | 1 | equemene | TEMP = ( D( 3 )-D( 2 ) ) / TWO |
129 | 1 | equemene | C = RHO + Z( 1 ) / ( ( D( 1 )-D( 2 ) )-TEMP ) |
130 | 1 | equemene | A = C*( D( 2 )+D( 3 ) ) + Z( 2 ) + Z( 3 ) |
131 | 1 | equemene | B = C*D( 2 )*D( 3 ) + Z( 2 )*D( 3 ) + Z( 3 )*D( 2 ) |
132 | 1 | equemene | ELSE |
133 | 1 | equemene | TEMP = ( D( 1 )-D( 2 ) ) / TWO |
134 | 1 | equemene | C = RHO + Z( 3 ) / ( ( D( 3 )-D( 2 ) )-TEMP ) |
135 | 1 | equemene | A = C*( D( 1 )+D( 2 ) ) + Z( 1 ) + Z( 2 ) |
136 | 1 | equemene | B = C*D( 1 )*D( 2 ) + Z( 1 )*D( 2 ) + Z( 2 )*D( 1 ) |
137 | 1 | equemene | END IF |
138 | 1 | equemene | TEMP = MAX( ABS( A ), ABS( B ), ABS( C ) ) |
139 | 1 | equemene | A = A / TEMP |
140 | 1 | equemene | B = B / TEMP |
141 | 1 | equemene | C = C / TEMP |
142 | 1 | equemene | IF( C.EQ.ZERO ) THEN |
143 | 1 | equemene | TAU = B / A |
144 | 1 | equemene | ELSE IF( A.LE.ZERO ) THEN |
145 | 1 | equemene | TAU = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C ) |
146 | 1 | equemene | ELSE |
147 | 1 | equemene | TAU = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) ) |
148 | 1 | equemene | END IF |
149 | 1 | equemene | IF( TAU .LT. LBD .OR. TAU .GT. UBD ) |
150 | 1 | equemene | $ TAU = ( LBD+UBD )/TWO |
151 | 1 | equemene | IF( D(1).EQ.TAU .OR. D(2).EQ.TAU .OR. D(3).EQ.TAU ) THEN |
152 | 1 | equemene | TAU = ZERO |
153 | 1 | equemene | ELSE |
154 | 1 | equemene | TEMP = FINIT + TAU*Z(1)/( D(1)*( D( 1 )-TAU ) ) + |
155 | 1 | equemene | $ TAU*Z(2)/( D(2)*( D( 2 )-TAU ) ) + |
156 | 1 | equemene | $ TAU*Z(3)/( D(3)*( D( 3 )-TAU ) ) |
157 | 1 | equemene | IF( TEMP .LE. ZERO )THEN |
158 | 1 | equemene | LBD = TAU |
159 | 1 | equemene | ELSE |
160 | 1 | equemene | UBD = TAU |
161 | 1 | equemene | END IF |
162 | 1 | equemene | IF( ABS( FINIT ).LE.ABS( TEMP ) ) |
163 | 1 | equemene | $ TAU = ZERO |
164 | 1 | equemene | END IF |
165 | 1 | equemene | END IF |
166 | 1 | equemene | * |
167 | 1 | equemene | * get machine parameters for possible scaling to avoid overflow |
168 | 1 | equemene | * |
169 | 1 | equemene | * modified by Sven: parameters SMALL1, SMINV1, SMALL2, |
170 | 1 | equemene | * SMINV2, EPS are not SAVEd anymore between one call to the |
171 | 1 | equemene | * others but recomputed at each call |
172 | 1 | equemene | * |
173 | 1 | equemene | EPS = DLAMCH( 'Epsilon' ) |
174 | 1 | equemene | BASE = DLAMCH( 'Base' ) |
175 | 1 | equemene | SMALL1 = BASE**( INT( LOG( DLAMCH( 'SafMin' ) ) / LOG( BASE ) / |
176 | 1 | equemene | $ THREE ) ) |
177 | 1 | equemene | SMINV1 = ONE / SMALL1 |
178 | 1 | equemene | SMALL2 = SMALL1*SMALL1 |
179 | 1 | equemene | SMINV2 = SMINV1*SMINV1 |
180 | 1 | equemene | * |
181 | 1 | equemene | * Determine if scaling of inputs necessary to avoid overflow |
182 | 1 | equemene | * when computing 1/TEMP**3 |
183 | 1 | equemene | * |
184 | 1 | equemene | IF( ORGATI ) THEN |
185 | 1 | equemene | TEMP = MIN( ABS( D( 2 )-TAU ), ABS( D( 3 )-TAU ) ) |
186 | 1 | equemene | ELSE |
187 | 1 | equemene | TEMP = MIN( ABS( D( 1 )-TAU ), ABS( D( 2 )-TAU ) ) |
188 | 1 | equemene | END IF |
189 | 1 | equemene | SCALE = .FALSE. |
190 | 1 | equemene | IF( TEMP.LE.SMALL1 ) THEN |
191 | 1 | equemene | SCALE = .TRUE. |
192 | 1 | equemene | IF( TEMP.LE.SMALL2 ) THEN |
193 | 1 | equemene | * |
194 | 1 | equemene | * Scale up by power of radix nearest 1/SAFMIN**(2/3) |
195 | 1 | equemene | * |
196 | 1 | equemene | SCLFAC = SMINV2 |
197 | 1 | equemene | SCLINV = SMALL2 |
198 | 1 | equemene | ELSE |
199 | 1 | equemene | * |
200 | 1 | equemene | * Scale up by power of radix nearest 1/SAFMIN**(1/3) |
201 | 1 | equemene | * |
202 | 1 | equemene | SCLFAC = SMINV1 |
203 | 1 | equemene | SCLINV = SMALL1 |
204 | 1 | equemene | END IF |
205 | 1 | equemene | * |
206 | 1 | equemene | * Scaling up safe because D, Z, TAU scaled elsewhere to be O(1) |
207 | 1 | equemene | * |
208 | 1 | equemene | DO 10 I = 1, 3 |
209 | 1 | equemene | DSCALE( I ) = D( I )*SCLFAC |
210 | 1 | equemene | ZSCALE( I ) = Z( I )*SCLFAC |
211 | 1 | equemene | 10 CONTINUE |
212 | 1 | equemene | TAU = TAU*SCLFAC |
213 | 1 | equemene | LBD = LBD*SCLFAC |
214 | 1 | equemene | UBD = UBD*SCLFAC |
215 | 1 | equemene | ELSE |
216 | 1 | equemene | * |
217 | 1 | equemene | * Copy D and Z to DSCALE and ZSCALE |
218 | 1 | equemene | * |
219 | 1 | equemene | DO 20 I = 1, 3 |
220 | 1 | equemene | DSCALE( I ) = D( I ) |
221 | 1 | equemene | ZSCALE( I ) = Z( I ) |
222 | 1 | equemene | 20 CONTINUE |
223 | 1 | equemene | END IF |
224 | 1 | equemene | * |
225 | 1 | equemene | FC = ZERO |
226 | 1 | equemene | DF = ZERO |
227 | 1 | equemene | DDF = ZERO |
228 | 1 | equemene | DO 30 I = 1, 3 |
229 | 1 | equemene | TEMP = ONE / ( DSCALE( I )-TAU ) |
230 | 1 | equemene | TEMP1 = ZSCALE( I )*TEMP |
231 | 1 | equemene | TEMP2 = TEMP1*TEMP |
232 | 1 | equemene | TEMP3 = TEMP2*TEMP |
233 | 1 | equemene | FC = FC + TEMP1 / DSCALE( I ) |
234 | 1 | equemene | DF = DF + TEMP2 |
235 | 1 | equemene | DDF = DDF + TEMP3 |
236 | 1 | equemene | 30 CONTINUE |
237 | 1 | equemene | F = FINIT + TAU*FC |
238 | 1 | equemene | * |
239 | 1 | equemene | IF( ABS( F ).LE.ZERO ) |
240 | 1 | equemene | $ GO TO 60 |
241 | 1 | equemene | IF( F .LE. ZERO )THEN |
242 | 1 | equemene | LBD = TAU |
243 | 1 | equemene | ELSE |
244 | 1 | equemene | UBD = TAU |
245 | 1 | equemene | END IF |
246 | 1 | equemene | * |
247 | 1 | equemene | * Iteration begins -- Use Gragg-Thornton-Warner cubic convergent |
248 | 1 | equemene | * scheme |
249 | 1 | equemene | * |
250 | 1 | equemene | * It is not hard to see that |
251 | 1 | equemene | * |
252 | 1 | equemene | * 1) Iterations will go up monotonically |
253 | 1 | equemene | * if FINIT < 0; |
254 | 1 | equemene | * |
255 | 1 | equemene | * 2) Iterations will go down monotonically |
256 | 1 | equemene | * if FINIT > 0. |
257 | 1 | equemene | * |
258 | 1 | equemene | ITER = NITER + 1 |
259 | 1 | equemene | * |
260 | 1 | equemene | DO 50 NITER = ITER, MAXIT |
261 | 1 | equemene | * |
262 | 1 | equemene | IF( ORGATI ) THEN |
263 | 1 | equemene | TEMP1 = DSCALE( 2 ) - TAU |
264 | 1 | equemene | TEMP2 = DSCALE( 3 ) - TAU |
265 | 1 | equemene | ELSE |
266 | 1 | equemene | TEMP1 = DSCALE( 1 ) - TAU |
267 | 1 | equemene | TEMP2 = DSCALE( 2 ) - TAU |
268 | 1 | equemene | END IF |
269 | 1 | equemene | A = ( TEMP1+TEMP2 )*F - TEMP1*TEMP2*DF |
270 | 1 | equemene | B = TEMP1*TEMP2*F |
271 | 1 | equemene | C = F - ( TEMP1+TEMP2 )*DF + TEMP1*TEMP2*DDF |
272 | 1 | equemene | TEMP = MAX( ABS( A ), ABS( B ), ABS( C ) ) |
273 | 1 | equemene | A = A / TEMP |
274 | 1 | equemene | B = B / TEMP |
275 | 1 | equemene | C = C / TEMP |
276 | 1 | equemene | IF( C.EQ.ZERO ) THEN |
277 | 1 | equemene | ETA = B / A |
278 | 1 | equemene | ELSE IF( A.LE.ZERO ) THEN |
279 | 1 | equemene | ETA = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C ) |
280 | 1 | equemene | ELSE |
281 | 1 | equemene | ETA = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) ) |
282 | 1 | equemene | END IF |
283 | 1 | equemene | IF( F*ETA.GE.ZERO ) THEN |
284 | 1 | equemene | ETA = -F / DF |
285 | 1 | equemene | END IF |
286 | 1 | equemene | * |
287 | 1 | equemene | TAU = TAU + ETA |
288 | 1 | equemene | IF( TAU .LT. LBD .OR. TAU .GT. UBD ) |
289 | 1 | equemene | $ TAU = ( LBD + UBD )/TWO |
290 | 1 | equemene | * |
291 | 1 | equemene | FC = ZERO |
292 | 1 | equemene | ERRETM = ZERO |
293 | 1 | equemene | DF = ZERO |
294 | 1 | equemene | DDF = ZERO |
295 | 1 | equemene | DO 40 I = 1, 3 |
296 | 1 | equemene | TEMP = ONE / ( DSCALE( I )-TAU ) |
297 | 1 | equemene | TEMP1 = ZSCALE( I )*TEMP |
298 | 1 | equemene | TEMP2 = TEMP1*TEMP |
299 | 1 | equemene | TEMP3 = TEMP2*TEMP |
300 | 1 | equemene | TEMP4 = TEMP1 / DSCALE( I ) |
301 | 1 | equemene | FC = FC + TEMP4 |
302 | 1 | equemene | ERRETM = ERRETM + ABS( TEMP4 ) |
303 | 1 | equemene | DF = DF + TEMP2 |
304 | 1 | equemene | DDF = DDF + TEMP3 |
305 | 1 | equemene | 40 CONTINUE |
306 | 1 | equemene | F = FINIT + TAU*FC |
307 | 1 | equemene | ERRETM = EIGHT*( ABS( FINIT )+ABS( TAU )*ERRETM ) + |
308 | 1 | equemene | $ ABS( TAU )*DF |
309 | 1 | equemene | IF( ABS( F ).LE.EPS*ERRETM ) |
310 | 1 | equemene | $ GO TO 60 |
311 | 1 | equemene | IF( F .LE. ZERO )THEN |
312 | 1 | equemene | LBD = TAU |
313 | 1 | equemene | ELSE |
314 | 1 | equemene | UBD = TAU |
315 | 1 | equemene | END IF |
316 | 1 | equemene | 50 CONTINUE |
317 | 1 | equemene | INFO = 1 |
318 | 1 | equemene | 60 CONTINUE |
319 | 1 | equemene | * |
320 | 1 | equemene | * Undo scaling |
321 | 1 | equemene | * |
322 | 1 | equemene | IF( SCALE ) |
323 | 1 | equemene | $ TAU = TAU*SCLINV |
324 | 1 | equemene | RETURN |
325 | 1 | equemene | * |
326 | 1 | equemene | * End of DLAED6 |
327 | 1 | equemene | * |
328 | 1 | equemene | END |