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