212      IMPLICIT NONE
  213 
  214
  215      LOGICAL, INTENT( IN ) :: ILSCHUR, ILQ, ILZ
  216      INTEGER, INTENT( IN ) :: N, ILO, IHI, LDA, LDB, LDQ, LDZ, LWORK,
  217     $         NSHIFTS, NBLOCK_DESIRED, LDQC, LDZC
  218 
  219      REAL, INTENT( INOUT ) :: A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
  220     $   Z( LDZ, * ), QC( LDQC, * ), ZC( LDZC, * ), WORK( * ), SR( * ),
  221     $   SI( * ), SS( * )
  222 
  223      INTEGER, INTENT( OUT ) :: INFO
  224 
  225
  226      REAL :: ZERO, ONE, HALF
  227      parameter( zero = 0.0, one = 1.0, half = 0.5 )
  228 
  229
  230      INTEGER :: I, J, NS, ISTARTM, ISTOPM, SHEIGHT, SWIDTH, K, NP,
  231     $           ISTARTB, ISTOPB, ISHIFT, NBLOCK, NPOS
  232      REAL :: TEMP, V( 3 ), C1, S1, C2, S2, SWAP
  233
  234
  237      REAL, EXTERNAL :: SROUNDUP_LWORK
  238 
  239      info = 0
  240      IF ( nblock_desired .LT. nshifts+1 ) THEN
  241         info = -8
  242      END IF
  243      IF ( lwork .EQ.-1 ) THEN
  244
  246         RETURN
  247      ELSE IF ( lwork .LT. n*nblock_desired ) THEN
  248         info = -25
  249      END IF
  250 
  251      IF( info.NE.0 ) THEN
  252         CALL xerbla( 
'SLAQZ4', -info )
 
  253         RETURN
  254      END IF
  255 
  256
  257 
  258      IF ( nshifts .LT. 2 ) THEN
  259         RETURN
  260      END IF
  261 
  262      IF ( ilo .GE. ihi ) THEN
  263         RETURN
  264      END IF
  265 
  266      IF ( ilschur ) THEN
  267         istartm = 1
  268         istopm = n
  269      ELSE
  270         istartm = ilo
  271         istopm = ihi
  272      END IF
  273 
  274
  275
  276
  277
  278 
  279      DO i = 1, nshifts-2, 2
  280         IF( si( i ).NE.-si( i+1 ) ) THEN
  281
  282            swap = sr( i )
  283            sr( i ) = sr( i+1 )
  284            sr( i+1 ) = sr( i+2 )
  285            sr( i+2 ) = swap
  286 
  287            swap = si( i )
  288            si( i ) = si( i+1 )
  289            si( i+1 ) = si( i+2 )
  290            si( i+2 ) = swap
  291            
  292            swap = ss( i )
  293            ss( i ) = ss( i+1 )
  294            ss( i+1 ) = ss( i+2 )
  295            ss( i+2 ) = swap
  296         END IF
  297      END DO
  298 
  299
  300
  301
  302
  303 
  304      ns = nshifts-mod( nshifts, 2 )
  305      npos = max( nblock_desired-ns, 1 )
  306 
  307
  308
  309
  310
  311 
  312      CALL slaset( 
'FULL', ns+1, ns+1, zero, one, qc, ldqc )
 
  313      CALL slaset( 
'FULL', ns, ns, zero, one, zc, ldzc )
 
  314 
  315      DO i = 1, ns, 2
  316
  317         CALL slaqz1( a( ilo, ilo ), lda, b( ilo, ilo ), ldb,
 
  318     $                sr( i ),
  319     $                sr( i+1 ), si( i ), ss( i ), ss( i+1 ), v )
  320 
  321         temp = v( 2 )
  322         CALL slartg( temp, v( 3 ), c1, s1, v( 2 ) )
 
  323         CALL slartg( v( 1 ), v( 2 ), c2, s2, temp )
 
  324 
  325         CALL srot( ns, a( ilo+1, ilo ), lda, a( ilo+2, ilo ), lda,
 
  326     $              c1,
  327     $              s1 )
  328         CALL srot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c2,
 
  329     $              s2 )
  330         CALL srot( ns, b( ilo+1, ilo ), ldb, b( ilo+2, ilo ), ldb,
 
  331     $              c1,
  332     $              s1 )
  333         CALL srot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c2,
 
  334     $              s2 )
  335         CALL srot( ns+1, qc( 1, 2 ), 1, qc( 1, 3 ), 1, c1, s1 )
 
  336         CALL srot( ns+1, qc( 1, 1 ), 1, qc( 1, 2 ), 1, c2, s2 )
 
  337 
  338
  339         DO j = 1, ns-1-i
  340 
  341            CALL slaqz2( .true., .true., j, 1, ns, ihi-ilo+1, a( ilo,
 
  342     $                   ilo ), lda, b( ilo, ilo ), ldb, ns+1, 1, qc,
  343     $                   ldqc, ns, 1, zc, ldzc )
  344 
  345         END DO
  346 
  347      END DO
  348 
  349
  350 
  351
  352
  353      sheight = ns+1
  354      swidth = istopm-( ilo+ns )+1
  355      IF ( swidth > 0 ) THEN
  356         CALL sgemm( 
'T', 
'N', sheight, swidth, sheight, one, qc,
 
  357     $               ldqc,
  358     $               a( ilo, ilo+ns ), lda, zero, work, sheight )
  359         CALL slacpy( 
'ALL', sheight, swidth, work, sheight, a( ilo,
 
  360     $                ilo+ns ), lda )
  361         CALL sgemm( 
'T', 
'N', sheight, swidth, sheight, one, qc,
 
  362     $               ldqc,
  363     $               b( ilo, ilo+ns ), ldb, zero, work, sheight )
  364         CALL slacpy( 
'ALL', sheight, swidth, work, sheight, b( ilo,
 
  365     $                ilo+ns ), ldb )
  366      END IF
  367      IF ( ilq ) THEN
  368         CALL sgemm( 
'N', 
'N', n, sheight, sheight, one, q( 1, ilo ),
 
  369     $               ldq, qc, ldqc, zero, work, n )
  370         CALL slacpy( 
'ALL', n, sheight, work, n, q( 1, ilo ), ldq )
 
  371      END IF
  372 
  373
  374
  375      sheight = ilo-1-istartm+1
  376      swidth = ns
  377      IF ( sheight > 0 ) THEN
  378         CALL sgemm( 
'N', 
'N', sheight, swidth, swidth, one,
 
  379     $               a( istartm,
  380     $               ilo ), lda, zc, ldzc, zero, work, sheight )
  381         CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  382     $                a( istartm,
  383     $                ilo ), lda )
  384         CALL sgemm( 
'N', 
'N', sheight, swidth, swidth, one,
 
  385     $               b( istartm,
  386     $               ilo ), ldb, zc, ldzc, zero, work, sheight )
  387         CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  388     $                b( istartm,
  389     $                ilo ), ldb )
  390      END IF
  391      IF ( ilz ) THEN
  392         CALL sgemm( 
'N', 
'N', n, swidth, swidth, one, z( 1, ilo ),
 
  393     $               ldz,
  394     $               zc, ldzc, zero, work, n )
  395         CALL slacpy( 
'ALL', n, swidth, work, n, z( 1, ilo ), ldz )
 
  396      END IF
  397 
  398
  399
  400
  401 
  402      k = ilo
  403      DO WHILE ( k < ihi-ns )
  404         np = min( ihi-ns-k, npos )
  405
  406         nblock = ns+np
  407
  408         istartb = k+1
  409
  410         istopb = k+nblock-1
  411 
  412         CALL slaset( 
'FULL', ns+np, ns+np, zero, one, qc, ldqc )
 
  413         CALL slaset( 
'FULL', ns+np, ns+np, zero, one, zc, ldzc )
 
  414 
  415
  416         DO i = ns-1, 0, -2
  417            DO j = 0, np-1
  418
  419
  420
  421               CALL slaqz2( .true., .true., k+i+j-1, istartb, istopb,
 
  422     $                      ihi, a, lda, b, ldb, nblock, k+1, qc, ldqc,
  423     $                      nblock, k, zc, ldzc )
  424            END DO
  425         END DO
  426 
  427
  428 
  429
  430
  431
  432         sheight = ns+np
  433         swidth = istopm-( k+ns+np )+1
  434         IF ( swidth > 0 ) THEN
  435            CALL sgemm( 
'T', 
'N', sheight, swidth, sheight, one, qc,
 
  436     $                  ldqc, a( k+1, k+ns+np ), lda, zero, work,
  437     $                  sheight )
  438            CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  439     $                   a( k+1,
  440     $                   k+ns+np ), lda )
  441            CALL sgemm( 
'T', 
'N', sheight, swidth, sheight, one, qc,
 
  442     $                  ldqc, b( k+1, k+ns+np ), ldb, zero, work,
  443     $                  sheight )
  444            CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  445     $                   b( k+1,
  446     $                   k+ns+np ), ldb )
  447         END IF
  448         IF ( ilq ) THEN
  449            CALL sgemm( 
'N', 
'N', n, nblock, nblock, one, q( 1,
 
  450     $                  k+1 ),
  451     $                  ldq, qc, ldqc, zero, work, n )
  452            CALL slacpy( 
'ALL', n, nblock, work, n, q( 1, k+1 ),
 
  453     $                   ldq )
  454         END IF
  455 
  456
  457
  458         sheight = k-istartm+1
  459         swidth = nblock
  460         IF ( sheight > 0 ) THEN
  461            CALL sgemm( 
'N', 
'N', sheight, swidth, swidth, one,
 
  462     $                  a( istartm, k ), lda, zc, ldzc, zero, work,
  463     $                  sheight )
  464            CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  465     $                   a( istartm, k ), lda )
  466            CALL sgemm( 
'N', 
'N', sheight, swidth, swidth, one,
 
  467     $                  b( istartm, k ), ldb, zc, ldzc, zero, work,
  468     $                  sheight )
  469            CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  470     $                   b( istartm, k ), ldb )
  471         END IF
  472         IF ( ilz ) THEN
  473            CALL sgemm( 
'N', 
'N', n, nblock, nblock, one, z( 1, k ),
 
  474     $                  ldz, zc, ldzc, zero, work, n )
  475            CALL slacpy( 
'ALL', n, nblock, work, n, z( 1, k ), ldz )
 
  476         END IF
  477 
  478         k = k+np
  479 
  480      END DO
  481 
  482
  483
  484 
  485      CALL slaset( 
'FULL', ns, ns, zero, one, qc, ldqc )
 
  486      CALL slaset( 
'FULL', ns+1, ns+1, zero, one, zc, ldzc )
 
  487 
  488
  489      istartb = ihi-ns+1
  490
  491      istopb = ihi
  492 
  493      DO i = 1, ns, 2
  494
  495         DO ishift = ihi-i-1, ihi-2
  496            CALL slaqz2( .true., .true., ishift, istartb, istopb,
 
  497     $                   ihi,
  498     $                   a, lda, b, ldb, ns, ihi-ns+1, qc, ldqc, ns+1,
  499     $                   ihi-ns, zc, ldzc )
  500         END DO
  501         
  502      END DO
  503 
  504
  505 
  506
  507
  508      sheight = ns
  509      swidth = istopm-( ihi+1 )+1
  510      IF ( swidth > 0 ) THEN
  511         CALL sgemm( 
'T', 
'N', sheight, swidth, sheight, one, qc,
 
  512     $               ldqc,
  513     $               a( ihi-ns+1, ihi+1 ), lda, zero, work, sheight )
  514         CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  515     $                a( ihi-ns+1, ihi+1 ), lda )
  516         CALL sgemm( 
'T', 
'N', sheight, swidth, sheight, one, qc,
 
  517     $               ldqc,
  518     $               b( ihi-ns+1, ihi+1 ), ldb, zero, work, sheight )
  519         CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  520     $                b( ihi-ns+1, ihi+1 ), ldb )
  521      END IF
  522      IF ( ilq ) THEN
  523         CALL sgemm( 
'N', 
'N', n, ns, ns, one, q( 1, ihi-ns+1 ), ldq,
 
  524     $               qc, ldqc, zero, work, n )
  525         CALL slacpy( 
'ALL', n, ns, work, n, q( 1, ihi-ns+1 ), ldq )
 
  526      END IF
  527 
  528
  529
  530      sheight = ihi-ns-istartm+1
  531      swidth = ns+1
  532      IF ( sheight > 0 ) THEN
  533         CALL sgemm( 
'N', 
'N', sheight, swidth, swidth, one,
 
  534     $               a( istartm,
  535     $               ihi-ns ), lda, zc, ldzc, zero, work, sheight )
  536         CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  537     $                a( istartm,
  538     $                ihi-ns ), lda )
  539         CALL sgemm( 
'N', 
'N', sheight, swidth, swidth, one,
 
  540     $               b( istartm,
  541     $               ihi-ns ), ldb, zc, ldzc, zero, work, sheight )
  542         CALL slacpy( 
'ALL', sheight, swidth, work, sheight,
 
  543     $                b( istartm,
  544     $                ihi-ns ), ldb )
  545      END IF
  546      IF ( ilz ) THEN
  547      CALL sgemm( 
'N', 
'N', n, ns+1, ns+1, one, z( 1, ihi-ns ), ldz,
 
  548     $            zc,
  549     $            ldzc, zero, work, n )
  550         CALL slacpy( 
'ALL', n, ns+1, work, n, z( 1, ihi-ns ), ldz )
 
  551      END IF
  552 
subroutine xerbla(srname, info)
 
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
 
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
 
subroutine slaqz1(a, lda, b, ldb, sr1, sr2, si, beta1, beta2, v)
SLAQZ1
 
subroutine slaqz2(ilq, ilz, k, istartm, istopm, ihi, a, lda, b, ldb, nq, qstart, q, ldq, nz, zstart, z, ldz)
SLAQZ2
 
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 srot(n, sx, incx, sy, incy, c, s)
SROT
 
real function sroundup_lwork(lwork)
SROUNDUP_LWORK