219
  220
  221
  222
  223
  224
  225      LOGICAL            WANTQ, WANTZ
  226      INTEGER            INFO, J1, LDA, LDB, LDQ, LDZ, LWORK, N, N1, N2
  227
  228
  229      DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
  230     $                   WORK( * ), Z( LDZ, * )
  231
  232
  233
  234
  235
  236
  237
  238      DOUBLE PRECISION   ZERO, ONE
  239      parameter( zero = 0.0d+0, one = 1.0d+0 )
  240      DOUBLE PRECISION   TWENTY
  241      parameter( twenty = 2.0d+01 )
  242      INTEGER            LDST
  243      parameter( ldst = 4 )
  244      LOGICAL            WANDS
  245      parameter( wands = .true. )
  246
  247
  248      LOGICAL            STRONG, WEAK
  249      INTEGER            I, IDUM, LINFO, M
  250      DOUBLE PRECISION   BQRA21, BRQA21, DDUM, DNORMA, DNORMB, DSCALE,
  251     $                   DSUM, EPS, F, G, SA, SB, SCALE, SMLNUM,
  252     $                   THRESHA, THRESHB
  253
  254
  255      INTEGER            IWORK( LDST + 2 )
  256      DOUBLE PRECISION   AI( 2 ), AR( 2 ), BE( 2 ), IR( LDST, LDST ),
  257     $                   IRCOP( LDST, LDST ), LI( LDST, LDST ),
  258     $                   LICOP( LDST, LDST ), S( LDST, LDST ),
  259     $                   SCPY( LDST, LDST ), T( LDST, LDST ),
  260     $                   TAUL( LDST ), TAUR( LDST ), TCPY( LDST, LDST )
  261
  262
  263      DOUBLE PRECISION   DLAMCH
  265
  266
  271
  272
  273      INTRINSIC          abs, max, sqrt
  274
  275
  276
  277      info = 0
  278
  279
  280
  281      IF( n.LE.1 .OR. n1.LE.0 .OR. n2.LE.0 )
  282     $   RETURN
  283      IF( n1.GT.n .OR. ( j1+n1 ).GT.n )
  284     $   RETURN
  285      m = n1 + n2
  286      IF( lwork.LT.max( 1, n*m, m*m*2 ) ) THEN
  287         info = -16
  288         work( 1 ) = max( 1, n*m, m*m*2 )
  289         RETURN
  290      END IF
  291
  292      weak = .false.
  293      strong = .false.
  294
  295
  296
  297      CALL dlaset( 
'Full', ldst, ldst, zero, zero, li, ldst )
 
  298      CALL dlaset( 
'Full', ldst, ldst, zero, zero, ir, ldst )
 
  299      CALL dlacpy( 
'Full', m, m, a( j1, j1 ), lda, s, ldst )
 
  300      CALL dlacpy( 
'Full', m, m, b( j1, j1 ), ldb, t, ldst )
 
  301
  302
  303
  305      smlnum = 
dlamch( 
'S' ) / eps
 
  306      dscale = zero
  307      dsum = one
  308      CALL dlacpy( 
'Full', m, m, s, ldst, work, m )
 
  309      CALL dlassq( m*m, work, 1, dscale, dsum )
 
  310      dnorma = dscale*sqrt( dsum )
  311      dscale = zero
  312      dsum = one
  313      CALL dlacpy( 
'Full', m, m, t, ldst, work, m )
 
  314      CALL dlassq( m*m, work, 1, dscale, dsum )
 
  315      dnormb = dscale*sqrt( dsum )
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325      thresha = max( twenty*eps*dnorma, smlnum )
  326      threshb = max( twenty*eps*dnormb, smlnum )
  327
  328      IF( m.EQ.2 ) THEN
  329
  330
  331
  332
  333
  334
  335         f = s( 2, 2 )*t( 1, 1 ) - t( 2, 2 )*s( 1, 1 )
  336         g = s( 2, 2 )*t( 1, 2 ) - t( 2, 2 )*s( 1, 2 )
  337         sa = abs( s( 2, 2 ) ) * abs( t( 1, 1 ) )
  338         sb = abs( s( 1, 1 ) ) * abs( t( 2, 2 ) )
  339         CALL dlartg( f, g, ir( 1, 2 ), ir( 1, 1 ), ddum )
 
  340         ir( 2, 1 ) = -ir( 1, 2 )
  341         ir( 2, 2 ) = ir( 1, 1 )
  342         CALL drot( 2, s( 1, 1 ), 1, s( 1, 2 ), 1, ir( 1, 1 ),
 
  343     $              ir( 2, 1 ) )
  344         CALL drot( 2, t( 1, 1 ), 1, t( 1, 2 ), 1, ir( 1, 1 ),
 
  345     $              ir( 2, 1 ) )
  346         IF( sa.GE.sb ) THEN
  347            CALL dlartg( s( 1, 1 ), s( 2, 1 ), li( 1, 1 ), li( 2,
 
  348     $                   1 ),
  349     $                   ddum )
  350         ELSE
  351            CALL dlartg( t( 1, 1 ), t( 2, 1 ), li( 1, 1 ), li( 2,
 
  352     $                   1 ),
  353     $                   ddum )
  354         END IF
  355         CALL drot( 2, s( 1, 1 ), ldst, s( 2, 1 ), ldst, li( 1, 1 ),
 
  356     $              li( 2, 1 ) )
  357         CALL drot( 2, t( 1, 1 ), ldst, t( 2, 1 ), ldst, li( 1, 1 ),
 
  358     $              li( 2, 1 ) )
  359         li( 2, 2 ) = li( 1, 1 )
  360         li( 1, 2 ) = -li( 2, 1 )
  361
  362
  363
  364
  365         weak = abs( s( 2, 1 ) ) .LE. thresha .AND.
  366     $      abs( t( 2, 1 ) ) .LE. threshb
  367         IF( .NOT.weak )
  368     $      GO TO 70
  369
  370         IF( wands ) THEN
  371
  372
  373
  374
  375
  376
  377            CALL dlacpy( 
'Full', m, m, a( j1, j1 ), lda,
 
  378     $                   work( m*m+1 ),
  379     $                   m )
  380            CALL dgemm( 
'N', 
'N', m, m, m, one, li, ldst, s, ldst,
 
  381     $                  zero,
  382     $                  work, m )
  383            CALL dgemm( 
'N', 
'T', m, m, m, -one, work, m, ir, ldst,
 
  384     $                  one,
  385     $                  work( m*m+1 ), m )
  386            dscale = zero
  387            dsum = one
  388            CALL dlassq( m*m, work( m*m+1 ), 1, dscale, dsum )
 
  389            sa = dscale*sqrt( dsum )
  390
  391            CALL dlacpy( 
'Full', m, m, b( j1, j1 ), ldb,
 
  392     $                   work( m*m+1 ),
  393     $                   m )
  394            CALL dgemm( 
'N', 
'N', m, m, m, one, li, ldst, t, ldst,
 
  395     $                  zero,
  396     $                  work, m )
  397            CALL dgemm( 
'N', 
'T', m, m, m, -one, work, m, ir, ldst,
 
  398     $                  one,
  399     $                  work( m*m+1 ), m )
  400            dscale = zero
  401            dsum = one
  402            CALL dlassq( m*m, work( m*m+1 ), 1, dscale, dsum )
 
  403            sb = dscale*sqrt( dsum )
  404            strong = sa.LE.thresha .AND. sb.LE.threshb
  405            IF( .NOT.strong )
  406     $         GO TO 70
  407         END IF
  408
  409
  410
  411
  412         CALL drot( j1+1, a( 1, j1 ), 1, a( 1, j1+1 ), 1, ir( 1, 1 ),
 
  413     $              ir( 2, 1 ) )
  414         CALL drot( j1+1, b( 1, j1 ), 1, b( 1, j1+1 ), 1, ir( 1, 1 ),
 
  415     $              ir( 2, 1 ) )
  416         CALL drot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda,
 
  417     $              li( 1, 1 ), li( 2, 1 ) )
  418         CALL drot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb,
 
  419     $              li( 1, 1 ), li( 2, 1 ) )
  420
  421
  422
  423         a( j1+1, j1 ) = zero
  424         b( j1+1, j1 ) = zero
  425
  426
  427
  428         IF( wantz )
  429     $      
CALL drot( n, z( 1, j1 ), 1, z( 1, j1+1 ), 1, ir( 1, 1 ),
 
  430     $                 ir( 2, 1 ) )
  431         IF( wantq )
  432     $      
CALL drot( n, q( 1, j1 ), 1, q( 1, j1+1 ), 1, li( 1, 1 ),
 
  433     $                 li( 2, 1 ) )
  434
  435
  436
  437         RETURN
  438
  439      ELSE
  440
  441
  442
  443
  444
  445
  446
  447
  448
  449         CALL dlacpy( 
'Full', n1, n2, t( 1, n1+1 ), ldst, li, ldst )
 
  450         CALL dlacpy( 
'Full', n1, n2, s( 1, n1+1 ), ldst,
 
  451     $                ir( n2+1, n1+1 ), ldst )
  452         CALL dtgsy2( 
'N', 0, n1, n2, s, ldst, s( n1+1, n1+1 ), ldst,
 
  453     $                ir( n2+1, n1+1 ), ldst, t, ldst, t( n1+1, n1+1 ),
  454     $                ldst, li, ldst, scale, dsum, dscale, iwork, idum,
  455     $                linfo )
  456         IF( linfo.NE.0 )
  457     $      GO TO 70
  458
  459
  460
  461
  462
  463
  464
  465
  466
  467         DO 10 i = 1, n2
  468            CALL dscal( n1, -one, li( 1, i ), 1 )
 
  469            li( n1+i, i ) = scale
  470   10    CONTINUE
  471         CALL dgeqr2( m, n2, li, ldst, taul, work, linfo )
 
  472         IF( linfo.NE.0 )
  473     $      GO TO 70
  474         CALL dorg2r( m, m, n2, li, ldst, taul, work, linfo )
 
  475         IF( linfo.NE.0 )
  476     $      GO TO 70
  477
  478
  479
  480
  481
  482
  483
  484         DO 20 i = 1, n1
  485            ir( n2+i, i ) = scale
  486   20    CONTINUE
  487         CALL dgerq2( n1, m, ir( n2+1, 1 ), ldst, taur, work, linfo )
 
  488         IF( linfo.NE.0 )
  489     $      GO TO 70
  490         CALL dorgr2( m, m, n1, ir, ldst, taur, work, linfo )
 
  491         IF( linfo.NE.0 )
  492     $      GO TO 70
  493
  494
  495
  496         CALL dgemm( 
'T', 
'N', m, m, m, one, li, ldst, s, ldst, zero,
 
  497     $               work, m )
  498         CALL dgemm( 
'N', 
'T', m, m, m, one, work, m, ir, ldst, zero,
 
  499     $               s,
  500     $               ldst )
  501         CALL dgemm( 
'T', 
'N', m, m, m, one, li, ldst, t, ldst, zero,
 
  502     $               work, m )
  503         CALL dgemm( 
'N', 
'T', m, m, m, one, work, m, ir, ldst, zero,
 
  504     $               t,
  505     $               ldst )
  506         CALL dlacpy( 
'F', m, m, s, ldst, scpy, ldst )
 
  507         CALL dlacpy( 
'F', m, m, t, ldst, tcpy, ldst )
 
  508         CALL dlacpy( 
'F', m, m, ir, ldst, ircop, ldst )
 
  509         CALL dlacpy( 
'F', m, m, li, ldst, licop, ldst )
 
  510
  511
  512
  513
  514         CALL dgerq2( m, m, t, ldst, taur, work, linfo )
 
  515         IF( linfo.NE.0 )
  516     $      GO TO 70
  517         CALL dormr2( 
'R', 
'T', m, m, m, t, ldst, taur, s, ldst,
 
  518     $                work,
  519     $                linfo )
  520         IF( linfo.NE.0 )
  521     $      GO TO 70
  522         CALL dormr2( 
'L', 
'N', m, m, m, t, ldst, taur, ir, ldst,
 
  523     $                work,
  524     $                linfo )
  525         IF( linfo.NE.0 )
  526     $      GO TO 70
  527
  528
  529
  530         dscale = zero
  531         dsum = one
  532         DO 30 i = 1, n2
  533            CALL dlassq( n1, s( n2+1, i ), 1, dscale, dsum )
 
  534   30    CONTINUE
  535         brqa21 = dscale*sqrt( dsum )
  536
  537
  538
  539
  540         CALL dgeqr2( m, m, tcpy, ldst, taul, work, linfo )
 
  541         IF( linfo.NE.0 )
  542     $      GO TO 70
  543         CALL dorm2r( 
'L', 
'T', m, m, m, tcpy, ldst, taul, scpy,
 
  544     $                ldst,
  545     $                work, info )
  546         CALL dorm2r( 
'R', 
'N', m, m, m, tcpy, ldst, taul, licop,
 
  547     $                ldst,
  548     $                work, info )
  549         IF( linfo.NE.0 )
  550     $      GO TO 70
  551
  552
  553
  554         dscale = zero
  555         dsum = one
  556         DO 40 i = 1, n2
  557            CALL dlassq( n1, scpy( n2+1, i ), 1, dscale, dsum )
 
  558   40    CONTINUE
  559         bqra21 = dscale*sqrt( dsum )
  560
  561
  562
  563
  564
  565         IF( bqra21.LE.brqa21 .AND. bqra21.LE.thresha ) THEN
  566            CALL dlacpy( 
'F', m, m, scpy, ldst, s, ldst )
 
  567            CALL dlacpy( 
'F', m, m, tcpy, ldst, t, ldst )
 
  568            CALL dlacpy( 
'F', m, m, ircop, ldst, ir, ldst )
 
  569            CALL dlacpy( 
'F', m, m, licop, ldst, li, ldst )
 
  570         ELSE IF( brqa21.GE.thresha ) THEN
  571            GO TO 70
  572         END IF
  573
  574
  575
  576         CALL dlaset( 
'Lower', m-1, m-1, zero, zero, t(2,1), ldst )
 
  577
  578         IF( wands ) THEN
  579
  580
  581
  582
  583
  584
  585            CALL dlacpy( 
'Full', m, m, a( j1, j1 ), lda,
 
  586     $                   work( m*m+1 ),
  587     $                   m )
  588            CALL dgemm( 
'N', 
'N', m, m, m, one, li, ldst, s, ldst,
 
  589     $                  zero,
  590     $                  work, m )
  591            CALL dgemm( 
'N', 
'N', m, m, m, -one, work, m, ir, ldst,
 
  592     $                  one,
  593     $                  work( m*m+1 ), m )
  594            dscale = zero
  595            dsum = one
  596            CALL dlassq( m*m, work( m*m+1 ), 1, dscale, dsum )
 
  597            sa = dscale*sqrt( dsum )
  598
  599            CALL dlacpy( 
'Full', m, m, b( j1, j1 ), ldb,
 
  600     $                   work( m*m+1 ),
  601     $                   m )
  602            CALL dgemm( 
'N', 
'N', m, m, m, one, li, ldst, t, ldst,
 
  603     $                  zero,
  604     $                  work, m )
  605            CALL dgemm( 
'N', 
'N', m, m, m, -one, work, m, ir, ldst,
 
  606     $                  one,
  607     $                  work( m*m+1 ), m )
  608            dscale = zero
  609            dsum = one
  610            CALL dlassq( m*m, work( m*m+1 ), 1, dscale, dsum )
 
  611            sb = dscale*sqrt( dsum )
  612            strong = sa.LE.thresha .AND. sb.LE.threshb
  613            IF( .NOT.strong )
  614     $         GO TO 70
  615
  616         END IF
  617
  618
  619
  620
  621         CALL dlaset( 
'Full', n1, n2, zero, zero, s(n2+1,1), ldst )
 
  622
  623
  624
  625         CALL dlacpy( 
'F', m, m, s, ldst, a( j1, j1 ), lda )
 
  626         CALL dlacpy( 
'F', m, m, t, ldst, b( j1, j1 ), ldb )
 
  627         CALL dlaset( 
'Full', ldst, ldst, zero, zero, t, ldst )
 
  628
  629
  630
  631         CALL dlaset( 
'Full', m, m, zero, zero, work, m )
 
  632         work( 1 ) = one
  633         t( 1, 1 ) = one
  634         idum = lwork - m*m - 2
  635         IF( n2.GT.1 ) THEN
  636            CALL dlagv2( a( j1, j1 ), lda, b( j1, j1 ), ldb, ar, ai,
 
  637     $                   be,
  638     $                   work( 1 ), work( 2 ), t( 1, 1 ), t( 2, 1 ) )
  639            work( m+1 ) = -work( 2 )
  640            work( m+2 ) = work( 1 )
  641            t( n2, n2 ) = t( 1, 1 )
  642            t( 1, 2 ) = -t( 2, 1 )
  643         END IF
  644         work( m*m ) = one
  645         t( m, m ) = one
  646
  647         IF( n1.GT.1 ) THEN
  648            CALL dlagv2( a( j1+n2, j1+n2 ), lda, b( j1+n2, j1+n2 ),
 
  649     $                   ldb,
  650     $                   taur, taul, work( m*m+1 ), work( n2*m+n2+1 ),
  651     $                   work( n2*m+n2+2 ), t( n2+1, n2+1 ),
  652     $                   t( m, m-1 ) )
  653            work( m*m ) = work( n2*m+n2+1 )
  654            work( m*m-1 ) = -work( n2*m+n2+2 )
  655            t( m, m ) = t( n2+1, n2+1 )
  656            t( m-1, m ) = -t( m, m-1 )
  657         END IF
  658         CALL dgemm( 
'T', 
'N', n2, n1, n2, one, work, m, a( j1,
 
  659     $               j1+n2 ),
  660     $               lda, zero, work( m*m+1 ), n2 )
  661         CALL dlacpy( 
'Full', n2, n1, work( m*m+1 ), n2, a( j1,
 
  662     $                j1+n2 ),
  663     $                lda )
  664         CALL dgemm( 
'T', 
'N', n2, n1, n2, one, work, m, b( j1,
 
  665     $               j1+n2 ),
  666     $               ldb, zero, work( m*m+1 ), n2 )
  667         CALL dlacpy( 
'Full', n2, n1, work( m*m+1 ), n2, b( j1,
 
  668     $                j1+n2 ),
  669     $                ldb )
  670         CALL dgemm( 
'N', 
'N', m, m, m, one, li, ldst, work, m, zero,
 
  671     $               work( m*m+1 ), m )
  672         CALL dlacpy( 
'Full', m, m, work( m*m+1 ), m, li, ldst )
 
  673         CALL dgemm( 
'N', 
'N', n2, n1, n1, one, a( j1, j1+n2 ), lda,
 
  674     $               t( n2+1, n2+1 ), ldst, zero, work, n2 )
  675         CALL dlacpy( 
'Full', n2, n1, work, n2, a( j1, j1+n2 ), lda )
 
  676         CALL dgemm( 
'N', 
'N', n2, n1, n1, one, b( j1, j1+n2 ), ldb,
 
  677     $               t( n2+1, n2+1 ), ldst, zero, work, n2 )
  678         CALL dlacpy( 
'Full', n2, n1, work, n2, b( j1, j1+n2 ), ldb )
 
  679         CALL dgemm( 
'T', 
'N', m, m, m, one, ir, ldst, t, ldst, zero,
 
  680     $               work, m )
  681         CALL dlacpy( 
'Full', m, m, work, m, ir, ldst )
 
  682
  683
  684
  685         IF( wantq ) THEN
  686            CALL dgemm( 
'N', 
'N', n, m, m, one, q( 1, j1 ), ldq, li,
 
  687     $                  ldst, zero, work, n )
  688            CALL dlacpy( 
'Full', n, m, work, n, q( 1, j1 ), ldq )
 
  689
  690         END IF
  691
  692         IF( wantz ) THEN
  693            CALL dgemm( 
'N', 
'N', n, m, m, one, z( 1, j1 ), ldz, ir,
 
  694     $                  ldst, zero, work, n )
  695            CALL dlacpy( 
'Full', n, m, work, n, z( 1, j1 ), ldz )
 
  696
  697         END IF
  698
  699
  700
  701
  702         i = j1 + m
  703         IF( i.LE.n ) THEN
  704            CALL dgemm( 
'T', 
'N', m, n-i+1, m, one, li, ldst,
 
  705     $                  a( j1, i ), lda, zero, work, m )
  706            CALL dlacpy( 
'Full', m, n-i+1, work, m, a( j1, i ), lda )
 
  707            CALL dgemm( 
'T', 
'N', m, n-i+1, m, one, li, ldst,
 
  708     $                  b( j1, i ), ldb, zero, work, m )
  709            CALL dlacpy( 
'Full', m, n-i+1, work, m, b( j1, i ), ldb )
 
  710         END IF
  711         i = j1 - 1
  712         IF( i.GT.0 ) THEN
  713            CALL dgemm( 
'N', 
'N', i, m, m, one, a( 1, j1 ), lda, ir,
 
  714     $                  ldst, zero, work, i )
  715            CALL dlacpy( 
'Full', i, m, work, i, a( 1, j1 ), lda )
 
  716            CALL dgemm( 
'N', 
'N', i, m, m, one, b( 1, j1 ), ldb, ir,
 
  717     $                  ldst, zero, work, i )
  718            CALL dlacpy( 
'Full', i, m, work, i, b( 1, j1 ), ldb )
 
  719         END IF
  720
  721
  722
  723         RETURN
  724
  725      END IF
  726
  727
  728
  729   70 CONTINUE
  730
  731      info = 1
  732      RETURN
  733
  734
  735
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dgeqr2(m, n, a, lda, tau, work, info)
DGEQR2 computes the QR factorization of a general rectangular matrix using an unblocked algorithm.
subroutine dgerq2(m, n, a, lda, tau, work, info)
DGERQ2 computes the RQ factorization of a general rectangular matrix using an unblocked algorithm.
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dlagv2(a, lda, b, ldb, alphar, alphai, beta, csl, snl, csr, snr)
DLAGV2 computes the Generalized Schur factorization of a real 2-by-2 matrix pencil (A,...
double precision function dlamch(cmach)
DLAMCH
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 dlassq(n, x, incx, scale, sumsq)
DLASSQ updates a sum of squares represented in scaled form.
subroutine drot(n, dx, incx, dy, incy, c, s)
DROT
subroutine dscal(n, da, dx, incx)
DSCAL
subroutine dtgsy2(trans, ijob, m, n, a, lda, b, ldb, c, ldc, d, ldd, e, lde, f, ldf, scale, rdsum, rdscal, iwork, pq, info)
DTGSY2 solves the generalized Sylvester equation (unblocked algorithm).
subroutine dorg2r(m, n, k, a, lda, tau, work, info)
DORG2R generates all or part of the orthogonal matrix Q from a QR factorization determined by sgeqrf ...
subroutine dorgr2(m, n, k, a, lda, tau, work, info)
DORGR2 generates all or part of the orthogonal matrix Q from an RQ factorization determined by sgerqf...
subroutine dorm2r(side, trans, m, n, k, a, lda, tau, c, ldc, work, info)
DORM2R multiplies a general matrix by the orthogonal matrix from a QR factorization determined by sge...
subroutine dormr2(side, trans, m, n, k, a, lda, tau, c, ldc, work, info)
DORMR2 multiplies a general matrix by the orthogonal matrix from a RQ factorization determined by sge...