238 IMPLICIT NONE
239
240
241 LOGICAL, INTENT( IN ) :: ILSCHUR, ILQ, ILZ
242 INTEGER, INTENT( IN ) :: N, ILO, IHI, NW, LDA, LDB, LDQ, LDZ,
243 $ LDQC, LDZC, LWORK, REC
244
245 DOUBLE PRECISION, INTENT( INOUT ) :: A( LDA, * ), B( LDB, * ),
246 $ Q( LDQ, * ), Z( LDZ, * ), ALPHAR( * ),
247 $ ALPHAI( * ), BETA( * )
248 INTEGER, INTENT( OUT ) :: NS, ND, INFO
249 DOUBLE PRECISION :: QC( LDQC, * ), ZC( LDZC, * ), WORK( * )
250
251
252 DOUBLE PRECISION :: ZERO, ONE, HALF
253 parameter( zero = 0.0d0, one = 1.0d0, half = 0.5d0 )
254
255
256 LOGICAL :: BULGE
257 INTEGER :: JW, KWTOP, KWBOT, ISTOPM, ISTARTM, K, K2, DTGEXC_INFO,
258 $ IFST, ILST, LWORKREQ, QZ_SMALL_INFO
259 DOUBLE PRECISION :: S, SMLNUM, ULP, SAFMIN, SAFMAX, C1, S1, TEMP
260
261
264 DOUBLE PRECISION, EXTERNAL :: DLAMCH
265
266 info = 0
267
268
269 jw = min( nw, ihi-ilo+1 )
270 kwtop = ihi-jw+1
271 IF ( kwtop .EQ. ilo ) THEN
272 s = zero
273 ELSE
274 s = a( kwtop, kwtop-1 )
275 END IF
276
277
278 ifst = 1
279 ilst = jw
280 CALL dtgexc( .true., .true., jw, a, lda, b, ldb, qc, ldqc, zc,
281 $ ldzc, ifst, ilst, work, -1, dtgexc_info )
282 lworkreq = int( work( 1 ) )
283 CALL dlaqz0(
'S',
'V',
'V', jw, 1, jw, a( kwtop, kwtop ), lda,
284 $ b( kwtop, kwtop ), ldb, alphar, alphai, beta, qc,
285 $ ldqc, zc, ldzc, work, -1, rec+1, qz_small_info )
286 lworkreq = max( lworkreq, int( work( 1 ) )+2*jw**2 )
287 lworkreq = max( lworkreq, n*nw, 2*nw**2+n )
288 IF ( lwork .EQ.-1 ) THEN
289
290 work( 1 ) = lworkreq
291 RETURN
292 ELSE IF ( lwork .LT. lworkreq ) THEN
293 info = -26
294 END IF
295
296 IF( info.NE.0 ) THEN
297 CALL xerbla(
'DLAQZ3', -info )
298 RETURN
299 END IF
300
301
302 safmin =
dlamch(
'SAFE MINIMUM' )
303 safmax = one/safmin
304 ulp =
dlamch(
'PRECISION' )
305 smlnum = safmin*( dble( n )/ulp )
306
307 IF ( ihi .EQ. kwtop ) THEN
308
309 alphar( kwtop ) = a( kwtop, kwtop )
310 alphai( kwtop ) = zero
311 beta( kwtop ) = b( kwtop, kwtop )
312 ns = 1
313 nd = 0
314 IF ( abs( s ) .LE. max( smlnum, ulp*abs( a( kwtop,
315 $ kwtop ) ) ) ) THEN
316 ns = 0
317 nd = 1
318 IF ( kwtop .GT. ilo ) THEN
319 a( kwtop, kwtop-1 ) = zero
320 END IF
321 END IF
322 END IF
323
324
325
326 CALL dlacpy(
'ALL', jw, jw, a( kwtop, kwtop ), lda, work, jw )
327 CALL dlacpy(
'ALL', jw, jw, b( kwtop, kwtop ), ldb,
328 $ work( jw**2+
329 $ 1 ), jw )
330
331
332 CALL dlaset(
'FULL', jw, jw, zero, one, qc, ldqc )
333 CALL dlaset(
'FULL', jw, jw, zero, one, zc, ldzc )
334 CALL dlaqz0(
'S',
'V',
'V', jw, 1, jw, a( kwtop, kwtop ), lda,
335 $ b( kwtop, kwtop ), ldb, alphar, alphai, beta, qc,
336 $ ldqc, zc, ldzc, work( 2*jw**2+1 ), lwork-2*jw**2,
337 $ rec+1, qz_small_info )
338
339 IF( qz_small_info .NE. 0 ) THEN
340
341 nd = 0
342 ns = jw-qz_small_info
343 CALL dlacpy(
'ALL', jw, jw, work, jw, a( kwtop, kwtop ),
344 $ lda )
345 CALL dlacpy(
'ALL', jw, jw, work( jw**2+1 ), jw, b( kwtop,
346 $ kwtop ), ldb )
347 RETURN
348 END IF
349
350
351 IF ( kwtop .EQ. ilo .OR. s .EQ. zero ) THEN
352 kwbot = kwtop-1
353 ELSE
354 kwbot = ihi
355 k = 1
356 k2 = 1
357 DO WHILE ( k .LE. jw )
358 bulge = .false.
359 IF ( kwbot-kwtop+1 .GE. 2 ) THEN
360 bulge = a( kwbot, kwbot-1 ) .NE. zero
361 END IF
362 IF ( bulge ) THEN
363
364
365 temp = abs( a( kwbot, kwbot ) )+sqrt( abs( a( kwbot,
366 $ kwbot-1 ) ) )*sqrt( abs( a( kwbot-1, kwbot ) ) )
367 IF( temp .EQ. zero )THEN
368 temp = abs( s )
369 END IF
370 IF ( max( abs( s*qc( 1, kwbot-kwtop ) ), abs( s*qc( 1,
371 $ kwbot-kwtop+1 ) ) ) .LE. max( smlnum,
372 $ ulp*temp ) ) THEN
373
374 kwbot = kwbot-2
375 ELSE
376
377 ifst = kwbot-kwtop+1
378 ilst = k2
379 CALL dtgexc( .true., .true., jw, a( kwtop, kwtop ),
380 $ lda, b( kwtop, kwtop ), ldb, qc, ldqc,
381 $ zc, ldzc, ifst, ilst, work, lwork,
382 $ dtgexc_info )
383 k2 = k2+2
384 END IF
385 k = k+2
386 ELSE
387
388
389 temp = abs( a( kwbot, kwbot ) )
390 IF( temp .EQ. zero ) THEN
391 temp = abs( s )
392 END IF
393 IF ( ( abs( s*qc( 1, kwbot-kwtop+1 ) ) ) .LE. max( ulp*
394 $ temp, smlnum ) ) THEN
395
396 kwbot = kwbot-1
397 ELSE
398
399 ifst = kwbot-kwtop+1
400 ilst = k2
401 CALL dtgexc( .true., .true., jw, a( kwtop, kwtop ),
402 $ lda, b( kwtop, kwtop ), ldb, qc, ldqc,
403 $ zc, ldzc, ifst, ilst, work, lwork,
404 $ dtgexc_info )
405 k2 = k2+1
406 END IF
407
408 k = k+1
409
410 END IF
411 END DO
412 END IF
413
414
415 nd = ihi-kwbot
416 ns = jw-nd
417 k = kwtop
418 DO WHILE ( k .LE. ihi )
419 bulge = .false.
420 IF ( k .LT. ihi ) THEN
421 IF ( a( k+1, k ) .NE. zero ) THEN
422 bulge = .true.
423 END IF
424 END IF
425 IF ( bulge ) THEN
426
427 CALL dlag2( a( k, k ), lda, b( k, k ), ldb, safmin,
428 $ beta( k ), beta( k+1 ), alphar( k ),
429 $ alphar( k+1 ), alphai( k ) )
430 alphai( k+1 ) = -alphai( k )
431 k = k+2
432 ELSE
433
434 alphar( k ) = a( k, k )
435 alphai( k ) = zero
436 beta( k ) = b( k, k )
437 k = k+1
438 END IF
439 END DO
440
441 IF ( kwtop .NE. ilo .AND. s .NE. zero ) THEN
442
443 a( kwtop:kwbot, kwtop-1 ) = a( kwtop, kwtop-1 )*qc( 1,
444 $ 1:jw-nd )
445 DO k = kwbot-1, kwtop, -1
446 CALL dlartg( a( k, kwtop-1 ), a( k+1, kwtop-1 ), c1, s1,
447 $ temp )
448 a( k, kwtop-1 ) = temp
449 a( k+1, kwtop-1 ) = zero
450 k2 = max( kwtop, k-1 )
451 CALL drot( ihi-k2+1, a( k, k2 ), lda, a( k+1, k2 ), lda,
452 $ c1,
453 $ s1 )
454 CALL drot( ihi-( k-1 )+1, b( k, k-1 ), ldb, b( k+1,
455 $ k-1 ),
456 $ ldb, c1, s1 )
457 CALL drot( jw, qc( 1, k-kwtop+1 ), 1, qc( 1,
458 $ k+1-kwtop+1 ),
459 $ 1, c1, s1 )
460 END DO
461
462
463 istartm = kwtop
464 istopm = ihi
465 k = kwbot-1
466 DO WHILE ( k .GE. kwtop )
467 IF ( ( k .GE. kwtop+1 ) .AND. a( k+1, k-1 ) .NE. zero ) THEN
468
469
470 DO k2 = k-1, kwbot-2
471 CALL dlaqz2( .true., .true., k2, kwtop, kwtop+jw-1,
472 $ kwbot, a, lda, b, ldb, jw, kwtop, qc,
473 $ ldqc, jw, kwtop, zc, ldzc )
474 END DO
475
476 k = k-2
477 ELSE
478
479
480 DO k2 = k, kwbot-2
481
482
483 CALL dlartg( b( k2+1, k2+1 ), b( k2+1, k2 ), c1,
484 $ s1,
485 $ temp )
486 b( k2+1, k2+1 ) = temp
487 b( k2+1, k2 ) = zero
488 CALL drot( k2+2-istartm+1, a( istartm, k2+1 ), 1,
489 $ a( istartm, k2 ), 1, c1, s1 )
490 CALL drot( k2-istartm+1, b( istartm, k2+1 ), 1,
491 $ b( istartm, k2 ), 1, c1, s1 )
492 CALL drot( jw, zc( 1, k2+1-kwtop+1 ), 1, zc( 1,
493 $ k2-kwtop+1 ), 1, c1, s1 )
494
495 CALL dlartg( a( k2+1, k2 ), a( k2+2, k2 ), c1, s1,
496 $ temp )
497 a( k2+1, k2 ) = temp
498 a( k2+2, k2 ) = zero
499 CALL drot( istopm-k2, a( k2+1, k2+1 ), lda,
500 $ a( k2+2,
501 $ k2+1 ), lda, c1, s1 )
502 CALL drot( istopm-k2, b( k2+1, k2+1 ), ldb,
503 $ b( k2+2,
504 $ k2+1 ), ldb, c1, s1 )
505 CALL drot( jw, qc( 1, k2+1-kwtop+1 ), 1, qc( 1,
506 $ k2+2-kwtop+1 ), 1, c1, s1 )
507
508 END DO
509
510
511 CALL dlartg( b( kwbot, kwbot ), b( kwbot, kwbot-1 ),
512 $ c1,
513 $ s1, temp )
514 b( kwbot, kwbot ) = temp
515 b( kwbot, kwbot-1 ) = zero
516 CALL drot( kwbot-istartm, b( istartm, kwbot ), 1,
517 $ b( istartm, kwbot-1 ), 1, c1, s1 )
518 CALL drot( kwbot-istartm+1, a( istartm, kwbot ), 1,
519 $ a( istartm, kwbot-1 ), 1, c1, s1 )
520 CALL drot( jw, zc( 1, kwbot-kwtop+1 ), 1, zc( 1,
521 $ kwbot-1-kwtop+1 ), 1, c1, s1 )
522
523 k = k-1
524 END IF
525 END DO
526
527 END IF
528
529
530 IF ( ilschur ) THEN
531 istartm = 1
532 istopm = n
533 ELSE
534 istartm = ilo
535 istopm = ihi
536 END IF
537
538 IF ( istopm-ihi > 0 ) THEN
539 CALL dgemm(
'T',
'N', jw, istopm-ihi, jw, one, qc, ldqc,
540 $ a( kwtop, ihi+1 ), lda, zero, work, jw )
541 CALL dlacpy(
'ALL', jw, istopm-ihi, work, jw, a( kwtop,
542 $ ihi+1 ), lda )
543 CALL dgemm(
'T',
'N', jw, istopm-ihi, jw, one, qc, ldqc,
544 $ b( kwtop, ihi+1 ), ldb, zero, work, jw )
545 CALL dlacpy(
'ALL', jw, istopm-ihi, work, jw, b( kwtop,
546 $ ihi+1 ), ldb )
547 END IF
548 IF ( ilq ) THEN
549 CALL dgemm(
'N',
'N', n, jw, jw, one, q( 1, kwtop ), ldq,
550 $ qc,
551 $ ldqc, zero, work, n )
552 CALL dlacpy(
'ALL', n, jw, work, n, q( 1, kwtop ), ldq )
553 END IF
554
555 IF ( kwtop-1-istartm+1 > 0 ) THEN
556 CALL dgemm(
'N',
'N', kwtop-istartm, jw, jw, one,
557 $ a( istartm,
558 $ kwtop ), lda, zc, ldzc, zero, work,
559 $ kwtop-istartm )
560 CALL dlacpy(
'ALL', kwtop-istartm, jw, work, kwtop-istartm,
561 $ a( istartm, kwtop ), lda )
562 CALL dgemm(
'N',
'N', kwtop-istartm, jw, jw, one,
563 $ b( istartm,
564 $ kwtop ), ldb, zc, ldzc, zero, work,
565 $ kwtop-istartm )
566 CALL dlacpy(
'ALL', kwtop-istartm, jw, work, kwtop-istartm,
567 $ b( istartm, kwtop ), ldb )
568 END IF
569 IF ( ilz ) THEN
570 CALL dgemm(
'N',
'N', n, jw, jw, one, z( 1, kwtop ), ldz,
571 $ zc,
572 $ ldzc, zero, work, n )
573 CALL dlacpy(
'ALL', n, jw, work, n, z( 1, kwtop ), ldz )
574 END IF
575
subroutine xerbla(srname, info)
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dlag2(a, lda, b, ldb, safmin, scale1, scale2, wr1, wr2, wi)
DLAG2 computes the eigenvalues of a 2-by-2 generalized eigenvalue problem, with scaling as necessary ...
double precision function dlamch(cmach)
DLAMCH
recursive subroutine dlaqz0(wants, wantq, wantz, n, ilo, ihi, a, lda, b, ldb, alphar, alphai, beta, q, ldq, z, ldz, work, lwork, rec, info)
DLAQZ0
subroutine dlaqz2(ilq, ilz, k, istartm, istopm, ihi, a, lda, b, ldb, nq, qstart, q, ldq, nz, zstart, z, ldz)
DLAQZ2
subroutine dlartg(f, g, c, s, r)
DLARTG generates a plane rotation with real cosine and real sine.
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine drot(n, dx, incx, dy, incy, c, s)
DROT
subroutine dtgexc(wantq, wantz, n, a, lda, b, ldb, q, ldq, z, ldz, ifst, ilst, work, lwork, info)
DTGEXC