91
92
93
94
95
96
97 INTEGER KNT, NIN
98
99
100 INTEGER LMAX( 3 ), NINFO( 3 )
101 DOUBLE PRECISION RMAX( 3 )
102
103
104
105
106
107 INTEGER LDT, LWORK
108 parameter( ldt = 20, lwork = 2*ldt*( 10+ldt ) )
109 DOUBLE PRECISION ZERO, ONE, TWO
110 parameter( zero = 0.0d+0, one = 1.0d+0, two = 2.0d+0 )
111 DOUBLE PRECISION EPSIN
112 parameter( epsin = 5.9605d-8 )
113 COMPLEX*16 CZERO
114 parameter( czero = ( 0.0d+0, 0.0d+0 ) )
115
116
117 INTEGER I, INFO, ISCL, ISRT, ITMP, J, KMIN, M, N, NDIM
118 DOUBLE PRECISION BIGNUM, EPS, S, SEP, SEPIN, SEPTMP, SIN,
119 $ SMLNUM, STMP, TNRM, TOL, TOLIN, V, VMAX, VMIN,
120 $ VMUL
121
122
123 LOGICAL SELECT( LDT )
124 INTEGER IPNT( LDT ), ISELEC( LDT )
125 DOUBLE PRECISION RESULT( 2 ), RWORK( LDT ), VAL( 3 ),
126 $ WSRT( LDT )
127 COMPLEX*16 Q( LDT, LDT ), QSAV( LDT, LDT ),
128 $ QTMP( LDT, LDT ), T( LDT, LDT ),
129 $ TMP( LDT, LDT ), TSAV( LDT, LDT ),
130 $ TSAV1( LDT, LDT ), TTMP( LDT, LDT ), W( LDT ),
131 $ WORK( LWORK ), WTMP( LDT )
132
133
134 DOUBLE PRECISION DLAMCH, ZLANGE
136
137
140
141
142 INTRINSIC dble, dimag, max, sqrt
143
144
145
147 smlnum =
dlamch(
'S' ) / eps
148 bignum = one / smlnum
149
150
151
152 eps = max( eps, epsin )
153 rmax( 1 ) = zero
154 rmax( 2 ) = zero
155 rmax( 3 ) = zero
156 lmax( 1 ) = 0
157 lmax( 2 ) = 0
158 lmax( 3 ) = 0
159 knt = 0
160 ninfo( 1 ) = 0
161 ninfo( 2 ) = 0
162 ninfo( 3 ) = 0
163 val( 1 ) = sqrt( smlnum )
164 val( 2 ) = one
165 val( 3 ) = sqrt( sqrt( bignum ) )
166
167
168
169
170
171 10 CONTINUE
172 READ( nin, fmt = * )n, ndim, isrt
173 IF( n.EQ.0 )
174 $ RETURN
175 READ( nin, fmt = * )( iselec( i ), i = 1, ndim )
176 DO 20 i = 1, n
177 READ( nin, fmt = * )( tmp( i, j ), j = 1, n )
178 20 CONTINUE
179 READ( nin, fmt = * )sin, sepin
180
181 tnrm =
zlange(
'M', n, n, tmp, ldt, rwork )
182 DO 200 iscl = 1, 3
183
184
185
186 knt = knt + 1
187 CALL zlacpy(
'F', n, n, tmp, ldt, t, ldt )
188 vmul = val( iscl )
189 DO 30 i = 1, n
190 CALL zdscal( n, vmul, t( 1, i ), 1 )
191 30 CONTINUE
192 IF( tnrm.EQ.zero )
193 $ vmul = one
194 CALL zlacpy(
'F', n, n, t, ldt, tsav, ldt )
195
196
197
198 CALL zgehrd( n, 1, n, t, ldt, work( 1 ), work( n+1 ), lwork-n,
199 $ info )
200 IF( info.NE.0 ) THEN
201 lmax( 1 ) = knt
202 ninfo( 1 ) = ninfo( 1 ) + 1
203 GO TO 200
204 END IF
205
206
207
208 CALL zlacpy(
'L', n, n, t, ldt, q, ldt )
209 CALL zunghr( n, 1, n, q, ldt, work( 1 ), work( n+1 ), lwork-n,
210 $ info )
211
212
213
214 DO 50 j = 1, n - 2
215 DO 40 i = j + 2, n
216 t( i, j ) = czero
217 40 CONTINUE
218 50 CONTINUE
219 CALL zhseqr(
'S',
'V', n, 1, n, t, ldt, w, q, ldt, work, lwork,
220 $ info )
221 IF( info.NE.0 ) THEN
222 lmax( 2 ) = knt
223 ninfo( 2 ) = ninfo( 2 ) + 1
224 GO TO 200
225 END IF
226
227
228
229 DO 60 i = 1, n
230 ipnt( i ) = i
231 SELECT( i ) = .false.
232 60 CONTINUE
233 IF( isrt.EQ.0 ) THEN
234 DO 70 i = 1, n
235 wsrt( i ) = dble( w( i ) )
236 70 CONTINUE
237 ELSE
238 DO 80 i = 1, n
239 wsrt( i ) = dimag( w( i ) )
240 80 CONTINUE
241 END IF
242 DO 100 i = 1, n - 1
243 kmin = i
244 vmin = wsrt( i )
245 DO 90 j = i + 1, n
246 IF( wsrt( j ).LT.vmin ) THEN
247 kmin = j
248 vmin = wsrt( j )
249 END IF
250 90 CONTINUE
251 wsrt( kmin ) = wsrt( i )
252 wsrt( i ) = vmin
253 itmp = ipnt( i )
254 ipnt( i ) = ipnt( kmin )
255 ipnt( kmin ) = itmp
256 100 CONTINUE
257 DO 110 i = 1, ndim
258 SELECT( ipnt( iselec( i ) ) ) = .true.
259 110 CONTINUE
260
261
262
263 CALL zlacpy(
'F', n, n, q, ldt, qsav, ldt )
264 CALL zlacpy(
'F', n, n, t, ldt, tsav1, ldt )
265 CALL ztrsen(
'B',
'V',
SELECT, n, t, ldt, q, ldt, wtmp, m, s,
266 $ sep, work, lwork, info )
267 IF( info.NE.0 ) THEN
268 lmax( 3 ) = knt
269 ninfo( 3 ) = ninfo( 3 ) + 1
270 GO TO 200
271 END IF
272 septmp = sep / vmul
273 stmp = s
274
275
276
277 CALL zhst01( n, 1, n, tsav, ldt, t, ldt, q, ldt, work, lwork,
278 $ rwork, result )
279 vmax = max( result( 1 ), result( 2 ) )
280 IF( vmax.GT.rmax( 1 ) ) THEN
281 rmax( 1 ) = vmax
282 IF( ninfo( 1 ).EQ.0 )
283 $ lmax( 1 ) = knt
284 END IF
285
286
287
288
289 v = max( two*dble( n )*eps*tnrm, smlnum )
290 IF( tnrm.EQ.zero )
291 $ v = one
292 IF( v.GT.septmp ) THEN
293 tol = one
294 ELSE
295 tol = v / septmp
296 END IF
297 IF( v.GT.sepin ) THEN
298 tolin = one
299 ELSE
300 tolin = v / sepin
301 END IF
302 tol = max( tol, smlnum / eps )
303 tolin = max( tolin, smlnum / eps )
304 IF( eps*( sin-tolin ).GT.stmp+tol ) THEN
305 vmax = one / eps
306 ELSE IF( sin-tolin.GT.stmp+tol ) THEN
307 vmax = ( sin-tolin ) / ( stmp+tol )
308 ELSE IF( sin+tolin.LT.eps*( stmp-tol ) ) THEN
309 vmax = one / eps
310 ELSE IF( sin+tolin.LT.stmp-tol ) THEN
311 vmax = ( stmp-tol ) / ( sin+tolin )
312 ELSE
313 vmax = one
314 END IF
315 IF( vmax.GT.rmax( 2 ) ) THEN
316 rmax( 2 ) = vmax
317 IF( ninfo( 2 ).EQ.0 )
318 $ lmax( 2 ) = knt
319 END IF
320
321
322
323
324 IF( v.GT.septmp*stmp ) THEN
325 tol = septmp
326 ELSE
327 tol = v / stmp
328 END IF
329 IF( v.GT.sepin*sin ) THEN
330 tolin = sepin
331 ELSE
332 tolin = v / sin
333 END IF
334 tol = max( tol, smlnum / eps )
335 tolin = max( tolin, smlnum / eps )
336 IF( eps*( sepin-tolin ).GT.septmp+tol ) THEN
337 vmax = one / eps
338 ELSE IF( sepin-tolin.GT.septmp+tol ) THEN
339 vmax = ( sepin-tolin ) / ( septmp+tol )
340 ELSE IF( sepin+tolin.LT.eps*( septmp-tol ) ) THEN
341 vmax = one / eps
342 ELSE IF( sepin+tolin.LT.septmp-tol ) THEN
343 vmax = ( septmp-tol ) / ( sepin+tolin )
344 ELSE
345 vmax = one
346 END IF
347 IF( vmax.GT.rmax( 2 ) ) THEN
348 rmax( 2 ) = vmax
349 IF( ninfo( 2 ).EQ.0 )
350 $ lmax( 2 ) = knt
351 END IF
352
353
354
355
356 IF( sin.LE.dble( 2*n )*eps .AND. stmp.LE.dble( 2*n )*eps ) THEN
357 vmax = one
358 ELSE IF( eps*sin.GT.stmp ) THEN
359 vmax = one / eps
360 ELSE IF( sin.GT.stmp ) THEN
361 vmax = sin / stmp
362 ELSE IF( sin.LT.eps*stmp ) THEN
363 vmax = one / eps
364 ELSE IF( sin.LT.stmp ) THEN
365 vmax = stmp / sin
366 ELSE
367 vmax = one
368 END IF
369 IF( vmax.GT.rmax( 3 ) ) THEN
370 rmax( 3 ) = vmax
371 IF( ninfo( 3 ).EQ.0 )
372 $ lmax( 3 ) = knt
373 END IF
374
375
376
377
378 IF( sepin.LE.v .AND. septmp.LE.v ) THEN
379 vmax = one
380 ELSE IF( eps*sepin.GT.septmp ) THEN
381 vmax = one / eps
382 ELSE IF( sepin.GT.septmp ) THEN
383 vmax = sepin / septmp
384 ELSE IF( sepin.LT.eps*septmp ) THEN
385 vmax = one / eps
386 ELSE IF( sepin.LT.septmp ) THEN
387 vmax = septmp / sepin
388 ELSE
389 vmax = one
390 END IF
391 IF( vmax.GT.rmax( 3 ) ) THEN
392 rmax( 3 ) = vmax
393 IF( ninfo( 3 ).EQ.0 )
394 $ lmax( 3 ) = knt
395 END IF
396
397
398
399
400 vmax = zero
401 CALL zlacpy(
'F', n, n, tsav1, ldt, ttmp, ldt )
402 CALL zlacpy(
'F', n, n, qsav, ldt, qtmp, ldt )
403 septmp = -one
404 stmp = -one
405 CALL ztrsen(
'E',
'V',
SELECT, n, ttmp, ldt, qtmp, ldt, wtmp,
406 $ m, stmp, septmp, work, lwork, info )
407 IF( info.NE.0 ) THEN
408 lmax( 3 ) = knt
409 ninfo( 3 ) = ninfo( 3 ) + 1
410 GO TO 200
411 END IF
412 IF( s.NE.stmp )
413 $ vmax = one / eps
414 IF( -one.NE.septmp )
415 $ vmax = one / eps
416 DO 130 i = 1, n
417 DO 120 j = 1, n
418 IF( ttmp( i, j ).NE.t( i, j ) )
419 $ vmax = one / eps
420 IF( qtmp( i, j ).NE.q( i, j ) )
421 $ vmax = one / eps
422 120 CONTINUE
423 130 CONTINUE
424
425
426
427
428 CALL zlacpy(
'F', n, n, tsav1, ldt, ttmp, ldt )
429 CALL zlacpy(
'F', n, n, qsav, ldt, qtmp, ldt )
430 septmp = -one
431 stmp = -one
432 CALL ztrsen(
'V',
'V',
SELECT, n, ttmp, ldt, qtmp, ldt, wtmp,
433 $ m, stmp, septmp, work, lwork, info )
434 IF( info.NE.0 ) THEN
435 lmax( 3 ) = knt
436 ninfo( 3 ) = ninfo( 3 ) + 1
437 GO TO 200
438 END IF
439 IF( -one.NE.stmp )
440 $ vmax = one / eps
441 IF( sep.NE.septmp )
442 $ vmax = one / eps
443 DO 150 i = 1, n
444 DO 140 j = 1, n
445 IF( ttmp( i, j ).NE.t( i, j ) )
446 $ vmax = one / eps
447 IF( qtmp( i, j ).NE.q( i, j ) )
448 $ vmax = one / eps
449 140 CONTINUE
450 150 CONTINUE
451
452
453
454
455 CALL zlacpy(
'F', n, n, tsav1, ldt, ttmp, ldt )
456 CALL zlacpy(
'F', n, n, qsav, ldt, qtmp, ldt )
457 septmp = -one
458 stmp = -one
459 CALL ztrsen(
'E',
'N',
SELECT, n, ttmp, ldt, qtmp, ldt, wtmp,
460 $ m, stmp, septmp, work, lwork, info )
461 IF( info.NE.0 ) THEN
462 lmax( 3 ) = knt
463 ninfo( 3 ) = ninfo( 3 ) + 1
464 GO TO 200
465 END IF
466 IF( s.NE.stmp )
467 $ vmax = one / eps
468 IF( -one.NE.septmp )
469 $ vmax = one / eps
470 DO 170 i = 1, n
471 DO 160 j = 1, n
472 IF( ttmp( i, j ).NE.t( i, j ) )
473 $ vmax = one / eps
474 IF( qtmp( i, j ).NE.qsav( i, j ) )
475 $ vmax = one / eps
476 160 CONTINUE
477 170 CONTINUE
478
479
480
481
482 CALL zlacpy(
'F', n, n, tsav1, ldt, ttmp, ldt )
483 CALL zlacpy(
'F', n, n, qsav, ldt, qtmp, ldt )
484 septmp = -one
485 stmp = -one
486 CALL ztrsen(
'V',
'N',
SELECT, n, ttmp, ldt, qtmp, ldt, wtmp,
487 $ m, stmp, septmp, work, lwork, info )
488 IF( info.NE.0 ) THEN
489 lmax( 3 ) = knt
490 ninfo( 3 ) = ninfo( 3 ) + 1
491 GO TO 200
492 END IF
493 IF( -one.NE.stmp )
494 $ vmax = one / eps
495 IF( sep.NE.septmp )
496 $ vmax = one / eps
497 DO 190 i = 1, n
498 DO 180 j = 1, n
499 IF( ttmp( i, j ).NE.t( i, j ) )
500 $ vmax = one / eps
501 IF( qtmp( i, j ).NE.qsav( i, j ) )
502 $ vmax = one / eps
503 180 CONTINUE
504 190 CONTINUE
505 IF( vmax.GT.rmax( 1 ) ) THEN
506 rmax( 1 ) = vmax
507 IF( ninfo( 1 ).EQ.0 )
508 $ lmax( 1 ) = knt
509 END IF
510 200 CONTINUE
511 GO TO 10
512
513
514
subroutine zgehrd(n, ilo, ihi, a, lda, tau, work, lwork, info)
ZGEHRD
subroutine zhseqr(job, compz, n, ilo, ihi, h, ldh, w, z, ldz, work, lwork, info)
ZHSEQR
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
double precision function dlamch(cmach)
DLAMCH
double precision function zlange(norm, m, n, a, lda, work)
ZLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
subroutine zdscal(n, da, zx, incx)
ZDSCAL
subroutine ztrsen(job, compq, select, n, t, ldt, q, ldq, w, m, s, sep, work, lwork, info)
ZTRSEN
subroutine zunghr(n, ilo, ihi, a, lda, tau, work, lwork, info)
ZUNGHR
subroutine zhst01(n, ilo, ihi, a, lda, h, ldh, q, ldq, work, lwork, rwork, result)
ZHST01