      SUBROUTINE SG03BD( DICO, FACT, TRANS, N, M, A, LDA, E, LDE, Q,
     $                   LDQ, Z, LDZ, B, LDB, SCALE, ALPHAR, ALPHAI,
     $                   BETA, DWORK, LDWORK, INFO )
C
C     SLICOT RELEASE 5.7.
C
C     Copyright (c) 2002-2020 NICONET e.V.
C
C     PURPOSE
C
C     To compute the Cholesky factor U of the matrix X,
C
C                 T
C        X = op(U)  * op(U),
C
C     which is the solution of either the generalized
C     c-stable continuous-time Lyapunov equation
C
C             T                    T
C        op(A)  * X * op(E) + op(E)  * X * op(A)
C
C                 2        T
C        = - SCALE  * op(B)  * op(B),                                (1)
C
C     or the generalized d-stable discrete-time Lyapunov equation
C
C             T                    T
C        op(A)  * X * op(A) - op(E)  * X * op(E)
C
C                 2        T
C        = - SCALE  * op(B)  * op(B),                                (2)
C
C     without first finding X and without the need to form the matrix
C     op(B)**T * op(B).
C
C     op(K) is either K or K**T for K = A, B, E, U. A and E are N-by-N
C     matrices, op(B) is an M-by-N matrix. The resulting matrix U is an
C     N-by-N upper triangular matrix with non-negative entries on its
C     main diagonal. SCALE is an output scale factor set to avoid
C     overflow in U.
C
C     In the continuous-time case (1) the pencil A - lambda * E must be
C     c-stable (that is, all eigenvalues must have negative real parts).
C     In the discrete-time case (2) the pencil A - lambda * E must be
C     d-stable (that is, the moduli of all eigenvalues must be smaller
C     than one).
C
C     ARGUMENTS
C
C     Mode Parameters
C
C     DICO    CHARACTER*1
C             Specifies which type of the equation is considered:
C             = 'C':  Continuous-time equation (1);
C             = 'D':  Discrete-time equation (2).
C
C     FACT    CHARACTER*1
C             Specifies whether the generalized real Schur
C             factorization of the pencil A - lambda * E is supplied
C             on entry or not:
C             = 'N':  Factorization is not supplied;
C             = 'F':  Factorization is supplied.
C
C     TRANS   CHARACTER*1
C             Specifies whether the transposed equation is to be solved
C             or not:
C             = 'N':  op(A) = A,    op(E) = E;
C             = 'T':  op(A) = A**T, op(E) = E**T.
C
C     Input/Output Parameters
C
C     N       (input) INTEGER
C             The order of the matrix A.  N >= 0.
C
C     M       (input) INTEGER
C             The number of rows in the matrix op(B).  M >= 0.
C
C     A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
C             On entry, if FACT = 'F', then the leading N-by-N upper
C             Hessenberg part of this array must contain the
C             generalized Schur factor A_s of the matrix A (see
C             definition (3) in section METHOD). A_s must be an upper
C             quasitriangular matrix. The elements below the upper
C             Hessenberg part of the array A are not referenced.
C             If FACT = 'N', then the leading N-by-N part of this
C             array must contain the matrix A.
C             On exit, the leading N-by-N part of this array contains
C             the generalized Schur factor A_s of the matrix A. (A_s is
C             an upper quasitriangular matrix.)
C
C     LDA     INTEGER
C             The leading dimension of the array A.  LDA >= MAX(1,N).
C
C     E       (input/output) DOUBLE PRECISION array, dimension (LDE,N)
C             On entry, if FACT = 'F', then the leading N-by-N upper
C             triangular part of this array must contain the
C             generalized Schur factor E_s of the matrix E (see
C             definition (4) in section METHOD). The elements below the
C             upper triangular part of the array E are not referenced.
C             If FACT = 'N', then the leading N-by-N part of this
C             array must contain the coefficient matrix E of the
C             equation.
C             On exit, the leading N-by-N part of this array contains
C             the generalized Schur factor E_s of the matrix E. (E_s is
C             an upper triangular matrix.)
C
C     LDE     INTEGER
C             The leading dimension of the array E.  LDE >= MAX(1,N).
C
C     Q       (input/output) DOUBLE PRECISION array, dimension (LDQ,N)
C             On entry, if FACT = 'F', then the leading N-by-N part of
C             this array must contain the orthogonal matrix Q from
C             the generalized Schur factorization (see definitions (3)
C             and (4) in section METHOD).
C             If FACT = 'N', Q need not be set on entry.
C             On exit, the leading N-by-N part of this array contains
C             the orthogonal matrix Q from the generalized Schur
C             factorization.
C
C     LDQ     INTEGER
C             The leading dimension of the array Q.  LDQ >= MAX(1,N).
C
C     Z       (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
C             On entry, if FACT = 'F', then the leading N-by-N part of
C             this array must contain the orthogonal matrix Z from
C             the generalized Schur factorization (see definitions (3)
C             and (4) in section METHOD).
C             If FACT = 'N', Z need not be set on entry.
C             On exit, the leading N-by-N part of this array contains
C             the orthogonal matrix Z from the generalized Schur
C             factorization.
C
C     LDZ     INTEGER
C             The leading dimension of the array Z.  LDZ >= MAX(1,N).
C
C     B       (input/output) DOUBLE PRECISION array, dimension (LDB,N1)
C             On entry, if TRANS = 'T', the leading N-by-M part of this
C             array must contain the matrix B and N1 >= MAX(M,N).
C             If TRANS = 'N', the leading M-by-N part of this array
C             must contain the matrix B and N1 >= N.
C             On exit, the leading N-by-N part of this array contains
C             the Cholesky factor U of the solution matrix X of the
C             problem, X = op(U)**T * op(U).
C             If M = 0 and N > 0, then U is set to zero.
C
C     LDB     INTEGER
C             The leading dimension of the array B.
C             If TRANS = 'T', LDB >= MAX(1,N).
C             If TRANS = 'N', LDB >= MAX(1,M,N).
C
C     SCALE   (output) DOUBLE PRECISION
C             The scale factor set to avoid overflow in U.
C             0 < SCALE <= 1.
C
C     ALPHAR  (output) DOUBLE PRECISION array, dimension (N)
C     ALPHAI  (output) DOUBLE PRECISION array, dimension (N)
C     BETA    (output) DOUBLE PRECISION array, dimension (N)
C             If INFO = 0, 3, 5, 6, or 7, then
C             (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, are the
C             eigenvalues of the matrix pencil A - lambda * E.
C
C     Workspace
C
C     DWORK   DOUBLE PRECISION array, dimension (LDWORK)
C             On exit, if INFO = 0, DWORK(1) returns the optimal value
C             of LDWORK.
C
C     LDWORK  INTEGER
C             The dimension of the array DWORK.
C             LDWORK >= MAX(1,4*N,6*N-6),  if FACT = 'N';
C             LDWORK >= MAX(1,2*N,6*N-6),  if FACT = 'F'.
C             For good performance, LDWORK should be larger.
C
C             If LDWORK = -1, then a workspace query is assumed; the
C             routine only calculates the optimal size of the DWORK
C             array, returns this value as the first entry of the DWORK
C             array, and no error message related to LDWORK is issued by
C             XERBLA.
C
C     Error indicator
C
C     INFO    INTEGER
C             = 0:  successful exit;
C             < 0:  if INFO = -i, the i-th argument had an illegal
C                   value;
C             = 1:  the pencil A - lambda * E is (nearly) singular;
C                   perturbed values were used to solve the equation
C                   (but the reduced (quasi)triangular matrices A and E
C                   are unchanged);
C             = 2:  FACT = 'F' and the matrix contained in the upper
C                   Hessenberg part of the array A is not in upper
C                   quasitriangular form;
C             = 3:  FACT = 'F' and there is a 2-by-2 block on the main
C                   diagonal of the pencil A_s - lambda * E_s whose
C                   eigenvalues are not conjugate complex;
C             = 4:  FACT = 'N' and the pencil A - lambda * E cannot be
C                   reduced to generalized Schur form: LAPACK routine
C                   DGEGS (or DGGES) has failed to converge;
C             = 5:  DICO = 'C' and the pencil A - lambda * E is not
C                   c-stable;
C             = 6:  DICO = 'D' and the pencil A - lambda * E is not
C                   d-stable;
C             = 7:  the LAPACK routine DSYEVX utilized to factorize M3
C                   failed to converge in the discrete-time case (see
C                   section METHOD for SLICOT Library routine SG03BU).
C                   This error is unlikely to occur.
C
C     METHOD
C
C     An extension [2] of Hammarling's method [1] to generalized
C     Lyapunov equations is utilized to solve (1) or (2).
C
C     First the pencil A - lambda * E is reduced to real generalized
C     Schur form A_s - lambda * E_s by means of orthogonal
C     transformations (QZ-algorithm):
C
C        A_s = Q**T * A * Z   (upper quasitriangular)                (3)
C
C        E_s = Q**T * E * Z   (upper triangular).                    (4)
C
C     If the pencil A - lambda * E has already been factorized prior to
C     calling the routine however, then the factors A_s, E_s, Q and Z
C     may be supplied and the initial factorization omitted.
C
C     Depending on the parameters TRANS and M the N-by-N upper
C     triangular matrix B_s is defined as follows. In any case Q_B is
C     an M-by-M orthogonal matrix, which need not be accumulated.
C
C     1. If TRANS = 'N' and M < N, B_s is the upper triangular matrix
C        from the QR-factorization
C
C           ( Q_B  O )           ( B * Z )
C           (        ) * B_s  =  (       ),
C           (  O   I )           (   O   )
C
C        where the O's are zero matrices of proper size and I is the
C        identity matrix of order N-M.
C
C     2. If TRANS = 'N' and M >= N, B_s is the upper triangular matrix
C        from the (rectangular) QR-factorization
C
C                 ( B_s )
C           Q_B * (     )  =  B * Z,
C                 (  O  )
C
C        where O is the (M-N)-by-N zero matrix.
C
C     3. If TRANS = 'T' and M < N, B_s is the upper triangular matrix
C        from the RQ-factorization
C
C                       ( Q_B  O )
C           (B_s  O ) * (        )  =  ( Q**T * B   O ).
C                       (  O   I )
C
C     4. If TRANS = 'T' and M >= N, B_s is the upper triangular matrix
C        from the (rectangular) RQ-factorization
C
C           ( B_s   O ) * Q_B  =  Q**T * B,
C
C        where O is the N-by-(M-N) zero matrix.
C
C     Assuming SCALE = 1, the transformation of A, E and B described
C     above leads to the reduced continuous-time equation
C
C                 T        T
C          op(A_s)  op(U_s)  op(U_s) op(E_s)
C
C                 T        T
C        + op(E_s)  op(U_s)  op(U_s) op(A_s)
C
C                    T
C        =  - op(B_s)  op(B_s)                                       (5)
C
C     or to the reduced discrete-time equation
C
C                 T        T
C          op(A_s)  op(U_s)  op(U_s) op(A_s)
C
C                 T        T
C        - op(E_s)  op(U_s)  op(U_s) op(E_s)
C
C                    T
C        =  - op(B_s)  op(B_s).                                      (6)
C
C     For brevity we restrict ourself to equation (5) and the case
C     TRANS = 'N'. The other three cases can be treated in a similar
C     fashion.
C
C     We use the following partitioning for the matrices A_s, E_s, B_s
C     and U_s
C
C                 ( A11   A12 )          ( E11   E12 )
C           A_s = (           ),   E_s = (           ),
C                 (   0   A22 )          (   0   E22 )
C
C                 ( B11   B12 )          ( U11   U12 )
C           B_s = (           ),   U_s = (           ).              (7)
C                 (   0   B22 )          (   0   U22 )
C
C     The size of the (1,1)-blocks is 1-by-1 (iff A_s(2,1) = 0.0) or
C     2-by-2.
C
C     We compute U11 and U12**T in three steps.
C
C     Step I:
C
C        From (5) and (7) we get the 1-by-1 or 2-by-2 equation
C
C                T      T                   T      T
C             A11  * U11  * U11 * E11  + E11  * U11  * U11 * A11
C
C                    T
C             = - B11  * B11.
C
C        For brevity, details are omitted here. See [2]. The technique
C        for computing U11 is similar to those applied to standard
C        Lyapunov equations in Hammarling's algorithm ([1], section 6).
C
C        Furthermore, the auxiliary matrices M1 and M2 defined as
C        follows
C
C                               -1      -1
C           M1 = U11 * A11 * E11   * U11
C
C                         -1      -1
C           M2 = B11 * E11   * U11
C
C        are computed in a numerically reliable way.
C
C     Step II:
C
C        The generalized Sylvester equation
C
C              T      T      T      T
C           A22  * U12  + E22  * U12  * M1  =
C
C                T           T      T      T      T
C           - B12  * M2 - A12  * U11  - E12  * U11  * M1
C
C        is solved for U12**T.
C
C     Step III:
C
C        It can be shown that
C
C              T      T                  T      T
C           A22  * U22  * U22 * E22 + E22  * U22  * U22 * A22  =
C
C                T              T
C           - B22  * B22 - y * y                                     (8)
C
C        holds, where y is defined as
C
C                  T        T      T      T      T       T
C           y = B12  - ( E12  * U11  + E22  * U12  ) * M2 .
C
C        If B22_tilde is the square triangular matrix arising from the
C        (rectangular) QR-factorization
C
C                       ( B22_tilde )     ( B22  )
C           Q_B_tilde * (           )  =  (      ),
C                       (     O     )     ( y**T )
C
C        where Q_B_tilde is an orthogonal matrix of order N, then
C
C                T              T                T
C           - B22  * B22 - y * y   =  - B22_tilde  * B22_tilde.
C
C        Replacing the right hand side in (8) by the term
C        - B22_tilde**T * B22_tilde leads to a reduced generalized
C        Lyapunov equation of lower dimension compared to (5).
C
C     The recursive application of the steps I to III yields the
C     solution U_s of the equation (5).
C
C     It remains to compute the solution matrix U of the original
C     problem (1) or (2) from the matrix U_s. To this end we transform
C     the solution back (with respect to the transformation that led
C     from (1) to (5) (from (2) to (6)) and apply the QR-factorization
C     (RQ-factorization). The upper triangular solution matrix U is
C     obtained by
C
C        Q_U * U  =  U_s * Q**T     (if TRANS = 'N')
C
C     or
C
C        U * Q_U  =  Z * U_s        (if TRANS = 'T')
C
C     where Q_U is an N-by-N orthogonal matrix. Again, the orthogonal
C     matrix Q_U need not be accumulated.
C
C     REFERENCES
C
C     [1] Hammarling, S.J.
C         Numerical solution of the stable, non-negative definite
C         Lyapunov equation.
C         IMA J. Num. Anal., 2, pp. 303-323, 1982.
C
C     [2] Penzl, T.
C         Numerical solution of generalized Lyapunov equations.
C         Advances in Comp. Math., vol. 8, pp. 33-48, 1998.
C
C     NUMERICAL ASPECTS
C
C     The number of flops required by the routine is given by the
C     following table. Note that we count a single floating point
C     arithmetic operation as one flop.
C
C                 |           FACT = 'F'                  FACT = 'N'
C        ---------+--------------------------------------------------
C         M <= N  |     (13*N**3+6*M*N**2         (211*N**3+6*M*N**2
C                 |   +6*M**2*N-2*M**3)/3        +6*M**2*N-2*M**3)/3
C                 |
C          M > N  | (11*N**3+12*M*N**2)/3     (209*N**3+12*M*N**2)/3
C
C     FURTHER COMMENTS
C
C     The Lyapunov equation may be very ill-conditioned. In particular,
C     if DICO = 'D' and the pencil A - lambda * E has a pair of almost
C     reciprocal eigenvalues, or DICO = 'C' and the pencil has an almost
C     degenerate pair of eigenvalues, then the Lyapunov equation will be
C     ill-conditioned. Perturbed values were used to solve the equation.
C     A condition estimate can be obtained from the routine SG03AD.
C     When setting the error indicator INFO, the routine does not test
C     for near instability in the equation but only for exact
C     instability.
C
C     CONTRIBUTOR
C
C     T. Penzl, Technical University Chemnitz, Germany, Aug. 1998.
C
C     REVISIONS
C
C     Sep. 1998 (V. Sima).
C     May 1999 (V. Sima).
C     March 2002 (A. Varga).
C     Feb. 2004 (V. Sima).
C     July 2011 (V. Sima).
C
C     KEYWORDS
C
C     Lyapunov equation
C
C     ******************************************************************
C
C     .. Parameters ..
      DOUBLE PRECISION  MONE, ONE, ZERO
      PARAMETER         ( MONE = -1.0D+0, ONE = 1.0D+0, ZERO = 0.0D+0 )
C     .. Scalar Arguments ..
      DOUBLE PRECISION  SCALE
      INTEGER           INFO, LDA, LDB, LDE, LDQ, LDWORK, LDZ, M, N
      CHARACTER         DICO, FACT, TRANS
C     .. Array Arguments ..
      DOUBLE PRECISION  A(LDA,*), ALPHAI(*), ALPHAR(*), B(LDB,*),
     $                  BETA(*), DWORK(*), E(LDE,*), Q(LDQ,*), Z(LDZ,*)
C     .. Local Scalars ..
      DOUBLE PRECISION  S1, S2, SAFMIN, WI, WR1, WR2
      INTEGER           I, INFO1, MAXMN, MINGG, MINMN, MINWRK, OPTWRK
      LOGICAL           ISDISC, ISFACT, ISTRAN, LQUERY
C     .. Local Arrays ..
      DOUBLE PRECISION  E1(2,2)
      LOGICAL           BWORK(1)
C     .. External Functions ..
      DOUBLE PRECISION  DLAMCH, DLAPY2
      LOGICAL           DELCTG, LSAME
      EXTERNAL          DELCTG, DLAMCH, DLAPY2, LSAME
C     .. External Subroutines ..
      EXTERNAL          DCOPY, DGEGS, DGEMM, DGEMV, DGEQRF, DGERQF,
     $                  DGGES, DLACPY, DLAG2, DLASET, DSCAL, DTRMM,
     $                  SG03BU, SG03BV, XERBLA
C     .. Intrinsic Functions ..
      INTRINSIC         ABS, DBLE, INT, MAX, MIN, SIGN
C     .. Executable Statements ..
C
C     Decode input parameters.
C
      ISDISC = LSAME( DICO,  'D' )
      ISFACT = LSAME( FACT,  'F' )
      ISTRAN = LSAME( TRANS, 'T' )
      LQUERY = LDWORK.EQ.-1
C
C     Check the scalar input parameters.
C
      INFO = 0
      IF ( .NOT.( ISDISC .OR. LSAME( DICO, 'C' ) ) ) THEN
         INFO = -1
      ELSEIF ( .NOT.( ISFACT .OR. LSAME( FACT,  'N' ) ) ) THEN
         INFO = -2
      ELSEIF ( .NOT.( ISTRAN .OR. LSAME( TRANS, 'N' ) ) ) THEN
         INFO = -3
      ELSEIF ( N .LT. 0 ) THEN
         INFO = -4
      ELSEIF ( M .LT. 0 ) THEN
         INFO = -5
      ELSEIF ( LDA .LT. MAX( 1, N ) ) THEN
         INFO = -7
      ELSEIF ( LDE .LT. MAX( 1, N ) ) THEN
         INFO = -9
      ELSEIF ( LDQ .LT. MAX( 1, N ) ) THEN
         INFO = -11
      ELSEIF ( LDZ .LT. MAX( 1, N ) ) THEN
         INFO = -13
      ELSEIF ( ( ISTRAN .AND. ( LDB .LT. MAX( 1, N ) ) ) .OR.
     $    ( .NOT.ISTRAN .AND. ( LDB .LT. MAX( 1, M, N ) ) ) ) THEN
         INFO = -15
      ELSE
C
C        Compute minimal and optimal workspace.
C
         IF (ISFACT ) THEN
            MINWRK = MAX( 1, 2*N, 6*N-6 )
         ELSE
            MINWRK = MAX( 1, 4*N, 6*N-6 )
         END IF
         MINGG = MAX( MINWRK, 8*N + 16 )
         IF( LQUERY ) THEN
            CALL DGGES( 'Vectors', 'Vectors', 'Not ordered', DELCTG, N,
     $                  A, LDA, E, LDE, I, ALPHAR, ALPHAI, BETA, Q, LDQ,
     $                  Z, LDZ, DWORK, -1, BWORK, INFO1 )
            MAXMN  = MAX( M, N )
            OPTWRK = MAX( MINGG, INT( DWORK(1) ), N*MAXMN )
            IF ( .NOT.ISTRAN ) THEN
               CALL DGEQRF( MAXMN, N, B, LDB, DWORK, DWORK, -1, INFO1 )
            ELSE
               CALL DGERQF( N, MAXMN, B, LDB, DWORK, DWORK, -1, INFO1 )
            END IF
            OPTWRK = MAX( OPTWRK, INT( DWORK(1) ) + N )
         ELSEIF ( LDWORK .LT. MINWRK ) THEN
            INFO = -21
         END IF
      END IF
C
      IF ( INFO .NE. 0 ) THEN
         CALL XERBLA( 'SG03BD', -INFO )
         RETURN
      ELSE IF( LQUERY ) THEN
         DWORK(1) = OPTWRK
         RETURN
      END IF
C
      SCALE = ONE
C
C     Quick return if possible.
C
      MINMN = MIN( M, N )
      IF ( MINMN .EQ. 0 ) THEN
         IF ( N.GT.0 )
     $      CALL DLASET( 'Full', N, N, ZERO, ZERO, B, LDB )
         DWORK(1) = ONE
         RETURN
      ENDIF
C
      IF ( ISFACT ) THEN
C
C        Make sure the upper Hessenberg part of A is quasitriangular.
C
         DO 20 I = 1, N-2
            IF ( A(I+1,I).NE.ZERO .AND. A(I+2,I+1).NE.ZERO ) THEN
               INFO = 2
               RETURN
            END IF
   20    CONTINUE
      END IF
C
      IF ( .NOT.ISFACT ) THEN
C
C        Reduce the pencil A - lambda * E to generalized Schur form.
C
C           A := Q**T * A * Z   (upper quasitriangular)
C           E := Q**T * E * Z   (upper triangular)
C
         IF ( LDWORK .LT. MINGG ) THEN
C
C           Use DGEGS for backward compatibilty with LDWORK value.
C           ( Workspace: >= MAX(1,4*N) )
C
            CALL DGEGS( 'Vectors', 'Vectors', N, A, LDA, E, LDE, ALPHAR,
     $                  ALPHAI, BETA, Q, LDQ, Z, LDZ, DWORK, LDWORK,
     $                  INFO1 )
         ELSE
C
C           Use DGGES. The workspace is increased to avoid an error
C           return, while it should not really be larger than above.
C           ( Workspace: >= MAX(1,8*N+16) )
C
            CALL DGGES( 'Vectors', 'Vectors', 'Not ordered', DELCTG, N,
     $                  A, LDA, E, LDE, I, ALPHAR, ALPHAI, BETA, Q, LDQ,
     $                  Z, LDZ, DWORK, LDWORK, BWORK, INFO1 )
         END IF
         IF ( INFO1 .NE. 0 ) THEN
            INFO = 4
            RETURN
         END IF
         OPTWRK = INT( DWORK(1) )
      ELSE
         OPTWRK = MINWRK
      END IF
C
      IF ( ISFACT ) THEN
C
C        If the matrix pencil A - lambda * E has been in generalized
C        Schur form on entry, compute its eigenvalues.
C
         SAFMIN = DLAMCH( 'Safe minimum' )
         E1(2,1) = ZERO
         I = 1
C        WHILE ( I .LE. N ) DO
   30    IF ( I .LE. N ) THEN
            IF ( ( I.EQ.N ) .OR. ( A(MIN( I+1, N ),I).EQ.ZERO ) ) THEN
               ALPHAR(I) = A(I,I)
               ALPHAI(I) = ZERO
               BETA(I) = E(I,I)
               I = I+1
            ELSE
               E1(1,1) = E(I,I)
               E1(1,2) = E(I,I+1)
               E1(2,2) = E(I+1,I+1)
               CALL DLAG2( A(I,I), LDA, E1, 2, SAFMIN, S1, S2, WR1, WR2,
     $                     WI )
               IF ( WI .EQ. ZERO ) INFO = 3
               ALPHAR(I) = WR1
               ALPHAI(I) = WI
               BETA(I) = S1
               ALPHAR(I+1) = WR2
               ALPHAI(I+1) = -WI
               BETA(I+1) = S2
               I = I+2
            END IF
         GOTO 30
         END IF
C        END WHILE 30
         IF ( INFO.NE.0 ) RETURN
      END IF
C
C     Check on the stability of the matrix pencil A - lambda * E.
C
      DO 40 I = 1, N
         IF ( ISDISC ) THEN
            IF ( DLAPY2( ALPHAR(I), ALPHAI(I) ) .GE. ABS( BETA(I) ) )
     $         THEN
               INFO = 6
               RETURN
            END IF
         ELSE
            IF ( ( ALPHAR(I).EQ.ZERO ) .OR. ( BETA(I).EQ.ZERO ) .OR.
     $         ( SIGN( ONE,ALPHAR(I) )*SIGN( ONE, BETA(I) ) .GE. ZERO) )
     $         THEN
               INFO = 5
               RETURN
            END IF
         END IF
   40 CONTINUE
C
C     Transformation of the right hand side.
C
C        B := B * Z  or  B := Q**T * B
C
C     Use BLAS 3 if there is enough workspace. Otherwise, use BLAS 2.
C
C     ( Workspace: max(1,N) )
C
      IF ( .NOT.ISTRAN ) THEN
         IF ( LDWORK .GE. N*M ) THEN
            CALL DGEMM(  'NoTranspose', 'NoTranspose', M, N, N, ONE, B,
     $                   LDB, Z, LDZ, ZERO, DWORK, M )
            CALL DLACPY( 'All', M, N, DWORK, M, B, LDB )
         ELSE
            DO 60 I = 1, M
               CALL DCOPY( N, B(I,1), LDB, DWORK, 1 )
               CALL DGEMV( 'Transpose', N, N, ONE, Z, LDZ, DWORK, 1,
     $                     ZERO, B(I,1), LDB )
 60         CONTINUE
         END IF
         IF ( M .LT. N )
     $      CALL DLASET( 'All', N-M, N, ZERO, ZERO, B(M+1,1), LDB )
      ELSE
         IF ( LDWORK .GE. N*M ) THEN
            CALL DLACPY( 'All', N, M, B, LDB, DWORK, N )
            CALL DGEMM(  'Transpose', 'NoTranspose', N, M, N, ONE, Q,
     $                   LDQ, DWORK, N, ZERO, B, LDB )
         ELSE
            DO 80 I = 1, M
               CALL DCOPY( N, B(1,I), 1, DWORK, 1 )
               CALL DGEMV( 'Transpose', N, N, ONE, Q, LDQ, DWORK, 1,
     $                     ZERO, B(1,I), 1 )
 80         CONTINUE
         END IF
         IF ( M .LT. N )
     $      CALL DLASET( 'All', N, N-M, ZERO, ZERO, B(1,M+1), LDB )
      END IF
      OPTWRK = MAX( OPTWRK, N*M )
C
C     Overwrite B with the triangular matrix of its QR-factorization
C     or its RQ-factorization.
C     (The entries on the main diagonal are non-negative.)
C
C     ( Workspace: >= max(1,2*N) )
C
      IF ( .NOT.ISTRAN ) THEN
         IF ( M .GE. 2 ) THEN
            CALL DGEQRF( M, N, B, LDB, DWORK, DWORK(N+1), LDWORK-N,
     $                   INFO1 )
            CALL DLASET( 'Lower', MAX( M, N )-1, MIN( M, N ), ZERO,
     $                   ZERO, B(2,1), LDB )
         END IF
         DO 100 I = 1, MINMN
            IF ( B(I,I) .LT. ZERO )
     $         CALL DSCAL( N+1-I, MONE, B(I,I), LDB )
  100    CONTINUE
      ELSE
         IF ( M .GE. 2 ) THEN
            CALL DGERQF( N, M, B, LDB, DWORK, DWORK(N+1), LDWORK-N,
     $                   INFO1 )
            IF ( N .GE. M ) THEN
               CALL DLASET( 'Lower', M-1, M-1, ZERO, ZERO, B(N-M+2,1),
     $                      LDB )
               IF ( N .GT. M ) THEN
                  DO 120 I = M, 1, -1
                     CALL DCOPY( N, B(1,I), 1, B(1,I+N-M), 1 )
  120             CONTINUE
                  CALL DLASET( 'All', N, N-M, ZERO, ZERO, B(1,1), LDB )
               END IF
            ELSE
               IF ( N .GT. 1 )
     $            CALL DLASET( 'Lower', N-1, N-1, ZERO, ZERO,
     $                         B(2,M-N+1), LDB )
               DO 140 I = 1, N
                  CALL DCOPY( N, B(1,M-N+I), 1, B(1,I), 1 )
  140          CONTINUE
               CALL DLASET( 'All', N, M-N, ZERO, ZERO, B(1,N+1), LDB )
            END IF
         ELSE
            IF ( N .NE. 1 ) THEN
               CALL DCOPY( N, B(1,1), 1, B(1,N), 1 )
               CALL DLASET( 'All', N, 1, ZERO, ZERO, B(1,1), LDB )
            END IF
         END IF
         DO 160 I = N - MINMN + 1, N
            IF ( B(I,I) .LT. ZERO )
     $         CALL DSCAL( I, MONE, B(1,I), 1 )
  160    CONTINUE
      END IF
      OPTWRK = MAX( OPTWRK, INT( DWORK(N+1) ) + N )
C
C     Solve the reduced generalized Lyapunov equation.
C
C     ( Workspace: 6*N-6 )
C
      IF ( ISDISC ) THEN
         CALL SG03BU( TRANS, N, A, LDA, E, LDE, B, LDB, SCALE, DWORK,
     $                INFO1 )
         IF ( INFO1 .NE. 0 ) THEN
            IF ( INFO1 .EQ. 1 ) INFO = 1
            IF ( INFO1 .EQ. 2 ) INFO = 3
            IF ( INFO1 .EQ. 3 ) INFO = 6
            IF ( INFO1 .EQ. 4 ) INFO = 7
            IF ( INFO  .NE. 1 )
     $         RETURN
         END IF
      ELSE
         CALL SG03BV( TRANS, N, A, LDA, E, LDE, B, LDB, SCALE, DWORK,
     $                INFO1 )
         IF ( INFO1 .NE. 0 ) THEN
            IF ( INFO1 .EQ. 1 ) INFO = 1
            IF ( INFO1 .GE. 2 ) INFO = 3
            IF ( INFO1 .EQ. 3 ) INFO = 5
            IF ( INFO  .NE. 1 )
     $         RETURN
         END IF
      END IF
C
C     Transform the solution matrix back.
C
C        U := U * Q**T   or   U := Z * U
C
C     Use BLAS 3 if there is enough workspace. Otherwise, use BLAS 2.
C
C     ( Workspace: max(1,N) )
C
      IF ( .NOT.ISTRAN ) THEN
         IF ( LDWORK .GE. N*N ) THEN
            CALL DLACPY( 'All', N, N, Q, LDQ, DWORK, N )
            CALL DTRMM( 'Right', 'Upper', 'Transpose', 'NonUnit', N, N,
     $                  ONE, B, LDB, DWORK, N)
            DO 170 I = 1, N
               CALL DCOPY( N, DWORK(N*(I-1)+1), 1, B(I,1), LDB )
  170       CONTINUE
         ELSE
            DO 180 I = 1, N
               CALL DCOPY( N-I+1, B(I,I), LDB, DWORK, 1 )
               CALL DGEMV( 'NoTranspose', N, N-I+1, ONE, Q(1,I), LDQ,
     $                     DWORK, 1, ZERO, B(I,1), LDB )
  180       CONTINUE
         END IF
      ELSE
         IF ( LDWORK .GE. N*N ) THEN
            CALL DLACPY( 'All', N, N, Z, LDZ, DWORK, N )
            CALL DTRMM(  'Right', 'Upper', 'NoTranspose', 'NonUnit', N,
     $                   N, ONE, B, LDB, DWORK, N )
            CALL DLACPY( 'All', N, N, DWORK, N, B, LDB )
         ELSE
            DO 200 I = 1, N
               CALL DCOPY( I, B(1,I), 1, DWORK, 1 )
               CALL DGEMV( 'NoTranspose', N, I, ONE, Z, LDZ, DWORK, 1,
     $                     ZERO, B(1,I), 1 )
 200        CONTINUE
         END IF
      END IF
      OPTWRK = MAX( OPTWRK, N*N )
C
C     Overwrite U with the triangular matrix of its QR-factorization
C     or its RQ-factorization.
C     (The entries on the main diagonal are non-negative.)
C
C     ( Workspace: >= max(1,2*N) )
C
      IF ( .NOT.ISTRAN ) THEN
         CALL DGEQRF( N, N, B, LDB, DWORK, DWORK(N+1), LDWORK-N, INFO1 )
         IF ( N .GT. 1 )
     $      CALL DLASET( 'Lower', N-1, N-1, ZERO, ZERO, B(2,1), LDB )
         DO 220 I = 1, N
            IF ( B(I,I) .LT. ZERO )
     $         CALL DSCAL( N+1-I, MONE, B(I,I), LDB )
  220    CONTINUE
      ELSE
         CALL DGERQF( N, N, B, LDB, DWORK, DWORK(N+1), LDWORK-N, INFO1 )
         IF ( N .GT. 1 )
     $      CALL DLASET( 'Lower', N-1, N-1, ZERO, ZERO, B(2,1), LDB )
         DO 240 I = 1, N
            IF ( B(I,I) .LT. ZERO )
     $         CALL DSCAL( I, MONE, B(1,I), 1 )
  240    CONTINUE
      END IF
      OPTWRK = MAX( OPTWRK, INT( DWORK(N+1) ) + N )
C
      DWORK(1) = DBLE( MAX( OPTWRK, MINWRK ) )
      RETURN
C *** Last line of SG03BD ***
      END
