302 RECURSIVE SUBROUTINE dlaqz0( WANTS, WANTQ, WANTZ, N, ILO, IHI, A,
303 $ LDA, B, LDB, ALPHAR, ALPHAI, BETA,
304 $ Q, LDQ, Z, LDZ, WORK, LWORK, REC,
309 CHARACTER,
INTENT( IN ) :: WANTS, WANTQ, WANTZ
310 INTEGER,
INTENT( IN ) :: N, ILO, IHI, LDA, LDB, LDQ, LDZ, LWORK,
313 INTEGER,
INTENT( OUT ) :: INFO
315 DOUBLE PRECISION,
INTENT( INOUT ) :: A( lda, * ), B( ldb, * ),
316 $ q( ldq, * ), z( ldz, * ), alphar( * ),
317 $ alphai( * ), beta( * ), work( * )
320 DOUBLE PRECISION :: ZERO, ONE, HALF
321 parameter( zero = 0.0d0, one = 1.0d0, half = 0.5d0 )
324 DOUBLE PRECISION :: SMLNUM, ULP, ESHIFT, SAFMIN, SAFMAX, C1, S1,
325 $ temp, swap, bnorm, btol
326 INTEGER :: ISTART, ISTOP, IITER, MAXIT, ISTART2, K, LD, NSHIFTS,
327 $ nblock, nw, nmin, nibble, n_undeflated, n_deflated,
328 $ ns, sweep_info, shiftpos, lworkreq, k2, istartm,
329 $ istopm, iwants, iwantq, iwantz, norm_info, aed_info,
330 $ nwr, nbr, nsr, itemp1, itemp2, rcost, i
331 LOGICAL :: ILSCHUR, ILQ, ILZ
332 CHARACTER :: JBCMPZ*3
337 DOUBLE PRECISION,
EXTERNAL :: DLAMCH, DLANHS
338 LOGICAL,
EXTERNAL :: LSAME
339 INTEGER,
EXTERNAL :: ILAENV
344 IF( lsame( wants,
'E' ) )
THEN 347 ELSE IF( lsame( wants,
'S' ) )
THEN 354 IF( lsame( wantq,
'N' ) )
THEN 357 ELSE IF( lsame( wantq,
'V' ) )
THEN 360 ELSE IF( lsame( wantq,
'I' ) )
THEN 367 IF( lsame( wantz,
'N' ) )
THEN 370 ELSE IF( lsame( wantz,
'V' ) )
THEN 373 ELSE IF( lsame( wantz,
'I' ) )
THEN 383 IF( iwants.EQ.0 )
THEN 385 ELSE IF( iwantq.EQ.0 )
THEN 387 ELSE IF( iwantz.EQ.0 )
THEN 389 ELSE IF( n.LT.0 )
THEN 391 ELSE IF( ilo.LT.1 )
THEN 393 ELSE IF( ihi.GT.n .OR. ihi.LT.ilo-1 )
THEN 395 ELSE IF( lda.LT.n )
THEN 397 ELSE IF( ldb.LT.n )
THEN 399 ELSE IF( ldq.LT.1 .OR. ( ilq .AND. ldq.LT.n ) )
THEN 401 ELSE IF( ldz.LT.1 .OR. ( ilz .AND. ldz.LT.n ) )
THEN 405 CALL xerbla(
'DLAQZ0', -info )
413 work( 1 ) = dble( 1 )
420 jbcmpz( 1:1 ) = wants
421 jbcmpz( 2:2 ) = wantq
422 jbcmpz( 3:3 ) = wantz
424 nmin = ilaenv( 12,
'DLAQZ0', jbcmpz, n, ilo, ihi, lwork )
426 nwr = ilaenv( 13,
'DLAQZ0', jbcmpz, n, ilo, ihi, lwork )
428 nwr = min( ihi-ilo+1, ( n-1 ) / 3, nwr )
430 nibble = ilaenv( 14,
'DLAQZ0', jbcmpz, n, ilo, ihi, lwork )
432 nsr = ilaenv( 15,
'DLAQZ0', jbcmpz, n, ilo, ihi, lwork )
433 nsr = min( nsr, ( n+6 ) / 9, ihi-ilo )
434 nsr = max( 2, nsr-mod( nsr, 2 ) )
436 rcost = ilaenv( 17,
'DLAQZ0', jbcmpz, n, ilo, ihi, lwork )
437 itemp1 = int( nsr/sqrt( 1+2*nsr/( dble( rcost )/100*n ) ) )
438 itemp1 = ( ( itemp1-1 )/4 )*4+4
441 IF( n .LT. nmin .OR. rec .GE. 2 )
THEN 442 CALL dhgeqz( wants, wantq, wantz, n, ilo, ihi, a, lda, b, ldb,
443 $ alphar, alphai, beta, q, ldq, z, ldz, work,
453 nw = max( nwr, nmin )
454 CALL dlaqz3( ilschur, ilq, ilz, n, ilo, ihi, nw, a, lda, b, ldb,
455 $ q, ldq, z, ldz, n_undeflated, n_deflated, alphar,
456 $ alphai, beta, work, nw, work, nw, work, -1, rec,
458 itemp1 = int( work( 1 ) )
460 CALL dlaqz4( ilschur, ilq, ilz, n, ilo, ihi, nsr, nbr, alphar,
461 $ alphai, beta, a, lda, b, ldb, q, ldq, z, ldz, work,
462 $ nbr, work, nbr, work, -1, sweep_info )
463 itemp2 = int( work( 1 ) )
465 lworkreq = max( itemp1+2*nw**2, itemp2+2*nbr**2 )
466 IF ( lwork .EQ.-1 )
THEN 467 work( 1 ) = dble( lworkreq )
469 ELSE IF ( lwork .LT. lworkreq )
THEN 473 CALL xerbla(
'DLAQZ0', info )
479 IF( iwantq.EQ.3 )
CALL dlaset(
'FULL', n, n, zero, one, q, ldq )
480 IF( iwantz.EQ.3 )
CALL dlaset(
'FULL', n, n, zero, one, z, ldz )
483 safmin = dlamch(
'SAFE MINIMUM' )
485 CALL dlabad( safmin, safmax )
486 ulp = dlamch(
'PRECISION' )
487 smlnum = safmin*( dble( n )/ulp )
489 bnorm = dlanhs(
'F', ihi-ilo+1, b( ilo, ilo ), ldb, work )
490 btol = max( safmin, ulp*bnorm )
494 maxit = 3*( ihi-ilo+1 )
498 IF( iiter .GE. maxit )
THEN 502 IF ( istart+1 .GE. istop )
THEN 508 IF ( abs( a( istop-1, istop-2 ) ) .LE. max( smlnum,
509 $ ulp*( abs( a( istop-1, istop-1 ) )+abs( a( istop-2,
510 $ istop-2 ) ) ) ) )
THEN 511 a( istop-1, istop-2 ) = zero
515 ELSE IF ( abs( a( istop, istop-1 ) ) .LE. max( smlnum,
516 $ ulp*( abs( a( istop, istop ) )+abs( a( istop-1,
517 $ istop-1 ) ) ) ) )
THEN 518 a( istop, istop-1 ) = zero
524 IF ( abs( a( istart+2, istart+1 ) ) .LE. max( smlnum,
525 $ ulp*( abs( a( istart+1, istart+1 ) )+abs( a( istart+2,
526 $ istart+2 ) ) ) ) )
THEN 527 a( istart+2, istart+1 ) = zero
531 ELSE IF ( abs( a( istart+1, istart ) ) .LE. max( smlnum,
532 $ ulp*( abs( a( istart, istart ) )+abs( a( istart+1,
533 $ istart+1 ) ) ) ) )
THEN 534 a( istart+1, istart ) = zero
540 IF ( istart+1 .GE. istop )
THEN 546 DO k = istop, istart+1, -1
547 IF ( abs( a( k, k-1 ) ) .LE. max( smlnum, ulp*( abs( a( k,
548 $ k ) )+abs( a( k-1, k-1 ) ) ) ) )
THEN 567 DO WHILE ( k.GE.istart2 )
569 IF( abs( b( k, k ) ) .LT. btol )
THEN 573 DO k2 = k, istart2+1, -1
574 CALL dlartg( b( k2-1, k2 ), b( k2-1, k2-1 ), c1, s1,
577 b( k2-1, k2-1 ) = zero
579 CALL drot( k2-2-istartm+1, b( istartm, k2 ), 1,
580 $ b( istartm, k2-1 ), 1, c1, s1 )
581 CALL drot( min( k2+1, istop )-istartm+1, a( istartm,
582 $ k2 ), 1, a( istartm, k2-1 ), 1, c1, s1 )
584 CALL drot( n, z( 1, k2 ), 1, z( 1, k2-1 ), 1, c1,
588 IF( k2.LT.istop )
THEN 589 CALL dlartg( a( k2, k2-1 ), a( k2+1, k2-1 ), c1,
592 a( k2+1, k2-1 ) = zero
594 CALL drot( istopm-k2+1, a( k2, k2 ), lda, a( k2+1,
595 $ k2 ), lda, c1, s1 )
596 CALL drot( istopm-k2+1, b( k2, k2 ), ldb, b( k2+1,
597 $ k2 ), ldb, c1, s1 )
599 CALL drot( n, q( 1, k2 ), 1, q( 1, k2+1 ), 1,
606 IF( istart2.LT.istop )
THEN 607 CALL dlartg( a( istart2, istart2 ), a( istart2+1,
608 $ istart2 ), c1, s1, temp )
609 a( istart2, istart2 ) = temp
610 a( istart2+1, istart2 ) = zero
612 CALL drot( istopm-( istart2+1 )+1, a( istart2,
613 $ istart2+1 ), lda, a( istart2+1,
614 $ istart2+1 ), lda, c1, s1 )
615 CALL drot( istopm-( istart2+1 )+1, b( istart2,
616 $ istart2+1 ), ldb, b( istart2+1,
617 $ istart2+1 ), ldb, c1, s1 )
619 CALL drot( n, q( 1, istart2 ), 1, q( 1,
620 $ istart2+1 ), 1, c1, s1 )
632 IF ( istart2 .GE. istop )
THEN 643 IF ( istop-istart2+1 .LT. nmin )
THEN 647 IF ( istop-istart+1 .LT. nmin )
THEN 658 CALL dlaqz3( ilschur, ilq, ilz, n, istart2, istop, nw, a, lda,
659 $ b, ldb, q, ldq, z, ldz, n_undeflated, n_deflated,
660 $ alphar, alphai, beta, work, nw, work( nw**2+1 ),
661 $ nw, work( 2*nw**2+1 ), lwork-2*nw**2, rec,
664 IF ( n_deflated > 0 )
THEN 665 istop = istop-n_deflated
670 IF ( 100*n_deflated > nibble*( n_deflated+n_undeflated ) .OR.
671 $ istop-istart2+1 .LT. nmin )
THEN 679 ns = min( nshifts, istop-istart2 )
680 ns = min( ns, n_undeflated )
681 shiftpos = istop-n_undeflated+1
686 DO i = shiftpos, shiftpos+n_undeflated-1, 2
687 IF( alphai( i ).NE.-alphai( i+1 ) )
THEN 690 alphar( i ) = alphar( i+1 )
691 alphar( i+1 ) = alphar( i+2 )
695 alphai( i ) = alphai( i+1 )
696 alphai( i+1 ) = alphai( i+2 )
700 beta( i ) = beta( i+1 )
701 beta( i+1 ) = beta( i+2 )
706 IF ( mod( ld, 6 ) .EQ. 0 )
THEN 710 IF( ( dble( maxit )*safmin )*abs( a( istop,
711 $ istop-1 ) ).LT.abs( a( istop-1, istop-1 ) ) )
THEN 712 eshift = a( istop, istop-1 )/b( istop-1, istop-1 )
714 eshift = eshift+one/( safmin*dble( maxit ) )
716 alphar( shiftpos ) = one
717 alphar( shiftpos+1 ) = zero
718 alphai( shiftpos ) = zero
719 alphai( shiftpos+1 ) = zero
720 beta( shiftpos ) = eshift
721 beta( shiftpos+1 ) = eshift
728 CALL dlaqz4( ilschur, ilq, ilz, n, istart2, istop, ns, nblock,
729 $ alphar( shiftpos ), alphai( shiftpos ),
730 $ beta( shiftpos ), a, lda, b, ldb, q, ldq, z, ldz,
731 $ work, nblock, work( nblock**2+1 ), nblock,
732 $ work( 2*nblock**2+1 ), lwork-2*nblock**2,
743 80
CALL dhgeqz( wants, wantq, wantz, n, ilo, ihi, a, lda, b, ldb,
744 $ alphar, alphai, beta, q, ldq, z, ldz, work, lwork,
subroutine xerbla(SRNAME, INFO)
XERBLA
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
recursive subroutine dlaqz3(ILSCHUR, ILQ, ILZ, N, ILO, IHI, NW, A, LDA, B, LDB, Q, LDQ, Z, LDZ, NS, ND, ALPHAR, ALPHAI, BETA, QC, LDQC, ZC, LDZC, WORK, LWORK, REC, INFO)
DLAQZ3
subroutine dhgeqz(JOB, COMPQ, COMPZ, N, ILO, IHI, H, LDH, T, LDT, ALPHAR, ALPHAI, BETA, Q, LDQ, Z, LDZ, WORK, LWORK, INFO)
DHGEQZ
subroutine drot(N, DX, INCX, DY, INCY, C, S)
DROT
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 dlaqz4(ILSCHUR, ILQ, ILZ, N, ILO, IHI, NSHIFTS, NBLOCK_DESIRED, SR, SI, SS, A, LDA, B, LDB, Q, LDQ, Z, LDZ, QC, LDQC, ZC, LDZC, WORK, LWORK, INFO)
DLAQZ4
subroutine dlabad(SMALL, LARGE)
DLABAD