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