230 SUBROUTINE dgghd3( COMPQ, COMPZ, N, ILO, IHI, A, LDA, B, LDB, Q,
231 $ LDQ, Z, LDZ, WORK, LWORK, INFO )
241 CHARACTER COMPQ, COMPZ
242 INTEGER IHI, ILO, INFO, LDA, LDB, LDQ, LDZ, N, LWORK
245 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
246 $ z( ldz, * ), work( * )
252 DOUBLE PRECISION ZERO, ONE
253 parameter( zero = 0.0d+0, one = 1.0d+0 )
256 LOGICAL BLK22, INITQ, INITZ, LQUERY, WANTQ, WANTZ
257 CHARACTER*1 COMPQ2, COMPZ2
258 INTEGER COLA, I, IERR, J, J0, JCOL, JJ, JROW, K,
259 $ kacc22, len, lwkopt, n2nb, nb, nblst, nbmin,
260 $ nh, nnb, nx, ppw, ppwo, pw, top, topq
261 DOUBLE PRECISION C, C1, C2, S, S1, S2, TEMP, TEMP1, TEMP2, TEMP3
266 EXTERNAL ilaenv, lsame
280 nb = ilaenv( 1,
'DGGHD3',
' ', n, ilo, ihi, -1 )
281 lwkopt = max( 6*n*nb, 1 )
282 work( 1 ) = dble( lwkopt )
283 initq = lsame( compq,
'I' )
284 wantq = initq .OR. lsame( compq,
'V' )
285 initz = lsame( compz,
'I' )
286 wantz = initz .OR. lsame( compz,
'V' )
287 lquery = ( lwork.EQ.-1 )
289 IF( .NOT.lsame( compq,
'N' ) .AND. .NOT.wantq )
THEN
291 ELSE IF( .NOT.lsame( compz,
'N' ) .AND. .NOT.wantz )
THEN
293 ELSE IF( n.LT.0 )
THEN
295 ELSE IF( ilo.LT.1 )
THEN
297 ELSE IF( ihi.GT.n .OR. ihi.LT.ilo-1 )
THEN
299 ELSE IF( lda.LT.max( 1, n ) )
THEN
301 ELSE IF( ldb.LT.max( 1, n ) )
THEN
303 ELSE IF( ( wantq .AND. ldq.LT.n ) .OR. ldq.LT.1 )
THEN
305 ELSE IF( ( wantz .AND. ldz.LT.n ) .OR. ldz.LT.1 )
THEN
307 ELSE IF( lwork.LT.1 .AND. .NOT.lquery )
THEN
311 CALL xerbla(
'DGGHD3', -info )
313 ELSE IF( lquery )
THEN
320 $
CALL dlaset(
'All', n, n, zero, one, q, ldq )
322 $
CALL dlaset(
'All', n, n, zero, one, z, ldz )
327 $
CALL dlaset(
'Lower', n-1, n-1, zero, zero, b(2, 1), ldb )
339 nbmin = ilaenv( 2,
'DGGHD3',
' ', n, ilo, ihi, -1 )
340 IF( nb.GT.1 .AND. nb.LT.nh )
THEN
344 nx = max( nb, ilaenv( 3,
'DGGHD3',
' ', n, ilo, ihi, -1 ) )
349 IF( lwork.LT.lwkopt )
THEN
355 nbmin = max( 2, ilaenv( 2,
'DGGHD3',
' ', n, ilo, ihi,
357 IF( lwork.GE.6*n*nbmin )
THEN
366 IF( nb.LT.nbmin .OR. nb.GE.nh )
THEN
376 kacc22 = ilaenv( 16,
'DGGHD3',
' ', n, ilo, ihi, -1 )
378 DO jcol = ilo, ihi-2, nb
379 nnb = min( nb, ihi-jcol-1 )
387 n2nb = ( ihi-jcol-1 ) / nnb - 1
388 nblst = ihi - jcol - n2nb*nnb
389 CALL dlaset(
'All', nblst, nblst, zero, one, work, nblst )
390 pw = nblst * nblst + 1
392 CALL dlaset(
'All', 2*nnb, 2*nnb, zero, one,
393 $ work( pw ), 2*nnb )
399 DO j = jcol, jcol+nnb-1
406 CALL dlartg( temp, a( i, j ), c, s, a( i-1, j ) )
413 ppw = ( nblst + 1 )*( nblst - 2 ) - j + jcol + 1
415 jrow = j + n2nb*nnb + 2
419 DO jj = ppw, ppw+len-1
420 temp = work( jj + nblst )
421 work( jj + nblst ) = c*temp - s*work( jj )
422 work( jj ) = s*temp + c*work( jj )
425 ppw = ppw - nblst - 1
428 ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2*nnb + nnb
430 DO jrow = j0, j+2, -nnb
433 DO i = jrow+nnb-1, jrow, -1
436 DO jj = ppw, ppw+len-1
437 temp = work( jj + 2*nnb )
438 work( jj + 2*nnb ) = c*temp - s*work( jj )
439 work( jj ) = s*temp + c*work( jj )
442 ppw = ppw - 2*nnb - 1
444 ppwo = ppwo + 4*nnb*nnb
463 DO i = min( jj+1, ihi ), j+2, -1
467 b( i, jj ) = c*temp - s*b( i-1, jj )
468 b( i-1, jj ) = s*temp + c*b( i-1, jj )
474 temp = b( jj+1, jj+1 )
475 CALL dlartg( temp, b( jj+1, jj ), c, s,
478 CALL drot( jj-top, b( top+1, jj+1 ), 1,
479 $ b( top+1, jj ), 1, c, s )
492 jj = mod( ihi-j-1, 3 )
493 DO i = ihi-j-3, jj+1, -3
503 temp1 = a( k, j+i+1 )
504 temp2 = a( k, j+i+2 )
505 temp3 = a( k, j+i+3 )
506 a( k, j+i+3 ) = c2*temp3 + s2*temp2
507 temp2 = -s2*temp3 + c2*temp2
508 a( k, j+i+2 ) = c1*temp2 + s1*temp1
509 temp1 = -s1*temp2 + c1*temp1
510 a( k, j+i+1 ) = c*temp1 + s*temp
511 a( k, j+i ) = -s*temp1 + c*temp
517 CALL drot( ihi-top, a( top+1, j+i+1 ), 1,
518 $ a( top+1, j+i ), 1, a( j+1+i, j ),
525 IF ( j .LT. jcol + nnb - 1 )
THEN
538 jrow = ihi - nblst + 1
539 CALL dgemv(
'Transpose', nblst, len, one, work,
540 $ nblst, a( jrow, j+1 ), 1, zero,
543 DO i = jrow, jrow+nblst-len-1
544 work( ppw ) = a( i, j+1 )
547 CALL dtrmv(
'Lower',
'Transpose',
'Non-unit',
548 $ nblst-len, work( len*nblst + 1 ), nblst,
549 $ work( pw+len ), 1 )
550 CALL dgemv(
'Transpose', len, nblst-len, one,
551 $ work( (len+1)*nblst - len + 1 ), nblst,
552 $ a( jrow+nblst-len, j+1 ), 1, one,
553 $ work( pw+len ), 1 )
555 DO i = jrow, jrow+nblst-1
556 a( i, j+1 ) = work( ppw )
573 ppwo = 1 + nblst*nblst
575 DO jrow = j0, jcol+1, -nnb
577 DO i = jrow, jrow+nnb-1
578 work( ppw ) = a( i, j+1 )
582 DO i = jrow+nnb, jrow+nnb+len-1
583 work( ppw ) = a( i, j+1 )
586 CALL dtrmv(
'Upper',
'Transpose',
'Non-unit', len,
587 $ work( ppwo + nnb ), 2*nnb, work( pw ),
589 CALL dtrmv(
'Lower',
'Transpose',
'Non-unit', nnb,
590 $ work( ppwo + 2*len*nnb ),
591 $ 2*nnb, work( pw + len ), 1 )
592 CALL dgemv(
'Transpose', nnb, len, one,
593 $ work( ppwo ), 2*nnb, a( jrow, j+1 ), 1,
594 $ one, work( pw ), 1 )
595 CALL dgemv(
'Transpose', len, nnb, one,
596 $ work( ppwo + 2*len*nnb + nnb ), 2*nnb,
597 $ a( jrow+nnb, j+1 ), 1, one,
598 $ work( pw+len ), 1 )
600 DO i = jrow, jrow+len+nnb-1
601 a( i, j+1 ) = work( ppw )
604 ppwo = ppwo + 4*nnb*nnb
611 cola = n - jcol - nnb + 1
613 CALL dgemm(
'Transpose',
'No Transpose', nblst,
614 $ cola, nblst, one, work, nblst,
615 $ a( j, jcol+nnb ), lda, zero, work( pw ),
617 CALL dlacpy(
'All', nblst, cola, work( pw ), nblst,
618 $ a( j, jcol+nnb ), lda )
619 ppwo = nblst*nblst + 1
621 DO j = j0, jcol+1, -nnb
633 CALL dorm22(
'Left',
'Transpose', 2*nnb, cola, nnb,
634 $ nnb, work( ppwo ), 2*nnb,
635 $ a( j, jcol+nnb ), lda, work( pw ),
641 CALL dgemm(
'Transpose',
'No Transpose', 2*nnb,
642 $ cola, 2*nnb, one, work( ppwo ), 2*nnb,
643 $ a( j, jcol+nnb ), lda, zero, work( pw ),
645 CALL dlacpy(
'All', 2*nnb, cola, work( pw ), 2*nnb,
646 $ a( j, jcol+nnb ), lda )
648 ppwo = ppwo + 4*nnb*nnb
656 topq = max( 2, j - jcol + 1 )
662 CALL dgemm(
'No Transpose',
'No Transpose', nh,
663 $ nblst, nblst, one, q( topq, j ), ldq,
664 $ work, nblst, zero, work( pw ), nh )
665 CALL dlacpy(
'All', nh, nblst, work( pw ), nh,
666 $ q( topq, j ), ldq )
667 ppwo = nblst*nblst + 1
669 DO j = j0, jcol+1, -nnb
671 topq = max( 2, j - jcol + 1 )
678 CALL dorm22(
'Right',
'No Transpose', nh, 2*nnb,
679 $ nnb, nnb, work( ppwo ), 2*nnb,
680 $ q( topq, j ), ldq, work( pw ),
686 CALL dgemm(
'No Transpose',
'No Transpose', nh,
687 $ 2*nnb, 2*nnb, one, q( topq, j ), ldq,
688 $ work( ppwo ), 2*nnb, zero, work( pw ),
690 CALL dlacpy(
'All', nh, 2*nnb, work( pw ), nh,
691 $ q( topq, j ), ldq )
693 ppwo = ppwo + 4*nnb*nnb
699 IF ( wantz .OR. top.GT.0 )
THEN
704 CALL dlaset(
'All', nblst, nblst, zero, one, work,
706 pw = nblst * nblst + 1
708 CALL dlaset(
'All', 2*nnb, 2*nnb, zero, one,
709 $ work( pw ), 2*nnb )
715 DO j = jcol, jcol+nnb-1
716 ppw = ( nblst + 1 )*( nblst - 2 ) - j + jcol + 1
718 jrow = j + n2nb*nnb + 2
724 DO jj = ppw, ppw+len-1
725 temp = work( jj + nblst )
726 work( jj + nblst ) = c*temp - s*work( jj )
727 work( jj ) = s*temp + c*work( jj )
730 ppw = ppw - nblst - 1
733 ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2*nnb + nnb
735 DO jrow = j0, j+2, -nnb
738 DO i = jrow+nnb-1, jrow, -1
743 DO jj = ppw, ppw+len-1
744 temp = work( jj + 2*nnb )
745 work( jj + 2*nnb ) = c*temp - s*work( jj )
746 work( jj ) = s*temp + c*work( jj )
749 ppw = ppw - 2*nnb - 1
751 ppwo = ppwo + 4*nnb*nnb
756 CALL dlaset(
'Lower', ihi - jcol - 1, nnb, zero, zero,
757 $ a( jcol + 2, jcol ), lda )
758 CALL dlaset(
'Lower', ihi - jcol - 1, nnb, zero, zero,
759 $ b( jcol + 2, jcol ), ldb )
766 CALL dgemm(
'No Transpose',
'No Transpose', top,
767 $ nblst, nblst, one, a( 1, j ), lda,
768 $ work, nblst, zero, work( pw ), top )
769 CALL dlacpy(
'All', top, nblst, work( pw ), top,
771 ppwo = nblst*nblst + 1
773 DO j = j0, jcol+1, -nnb
778 CALL dorm22(
'Right',
'No Transpose', top, 2*nnb,
779 $ nnb, nnb, work( ppwo ), 2*nnb,
780 $ a( 1, j ), lda, work( pw ),
786 CALL dgemm(
'No Transpose',
'No Transpose', top,
787 $ 2*nnb, 2*nnb, one, a( 1, j ), lda,
788 $ work( ppwo ), 2*nnb, zero,
790 CALL dlacpy(
'All', top, 2*nnb, work( pw ), top,
793 ppwo = ppwo + 4*nnb*nnb
797 CALL dgemm(
'No Transpose',
'No Transpose', top,
798 $ nblst, nblst, one, b( 1, j ), ldb,
799 $ work, nblst, zero, work( pw ), top )
800 CALL dlacpy(
'All', top, nblst, work( pw ), top,
802 ppwo = nblst*nblst + 1
804 DO j = j0, jcol+1, -nnb
809 CALL dorm22(
'Right',
'No Transpose', top, 2*nnb,
810 $ nnb, nnb, work( ppwo ), 2*nnb,
811 $ b( 1, j ), ldb, work( pw ),
817 CALL dgemm(
'No Transpose',
'No Transpose', top,
818 $ 2*nnb, 2*nnb, one, b( 1, j ), ldb,
819 $ work( ppwo ), 2*nnb, zero,
821 CALL dlacpy(
'All', top, 2*nnb, work( pw ), top,
824 ppwo = ppwo + 4*nnb*nnb
833 topq = max( 2, j - jcol + 1 )
839 CALL dgemm(
'No Transpose',
'No Transpose', nh,
840 $ nblst, nblst, one, z( topq, j ), ldz,
841 $ work, nblst, zero, work( pw ), nh )
842 CALL dlacpy(
'All', nh, nblst, work( pw ), nh,
843 $ z( topq, j ), ldz )
844 ppwo = nblst*nblst + 1
846 DO j = j0, jcol+1, -nnb
848 topq = max( 2, j - jcol + 1 )
855 CALL dorm22(
'Right',
'No Transpose', nh, 2*nnb,
856 $ nnb, nnb, work( ppwo ), 2*nnb,
857 $ z( topq, j ), ldz, work( pw ),
863 CALL dgemm(
'No Transpose',
'No Transpose', nh,
864 $ 2*nnb, 2*nnb, one, z( topq, j ), ldz,
865 $ work( ppwo ), 2*nnb, zero, work( pw ),
867 CALL dlacpy(
'All', nh, 2*nnb, work( pw ), nh,
868 $ z( topq, j ), ldz )
870 ppwo = ppwo + 4*nnb*nnb
881 IF ( jcol.NE.ilo )
THEN
889 $
CALL dgghrd( compq2, compz2, n, jcol, ihi, a, lda, b, ldb, q,
890 $ ldq, z, ldz, ierr )
891 work( 1 ) = dble( lwkopt )