362 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Fortran
		
	
	
	
			
		
		
	
	
			362 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Fortran
		
	
	
	
*> \brief \b SGGHRD
 | 
						|
*
 | 
						|
*  =========== DOCUMENTATION ===========
 | 
						|
*
 | 
						|
* Online html documentation available at 
 | 
						|
*            http://www.netlib.org/lapack/explore-html/ 
 | 
						|
*
 | 
						|
*> \htmlonly
 | 
						|
*> Download SGGHRD + dependencies 
 | 
						|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sgghrd.f"> 
 | 
						|
*> [TGZ]</a> 
 | 
						|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sgghrd.f"> 
 | 
						|
*> [ZIP]</a> 
 | 
						|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgghrd.f"> 
 | 
						|
*> [TXT]</a>
 | 
						|
*> \endhtmlonly 
 | 
						|
*
 | 
						|
*  Definition:
 | 
						|
*  ===========
 | 
						|
*
 | 
						|
*       SUBROUTINE SGGHRD( COMPQ, COMPZ, N, ILO, IHI, A, LDA, B, LDB, Q,
 | 
						|
*                          LDQ, Z, LDZ, INFO )
 | 
						|
* 
 | 
						|
*       .. Scalar Arguments ..
 | 
						|
*       CHARACTER          COMPQ, COMPZ
 | 
						|
*       INTEGER            IHI, ILO, INFO, LDA, LDB, LDQ, LDZ, N
 | 
						|
*       ..
 | 
						|
*       .. Array Arguments ..
 | 
						|
*       REAL               A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
 | 
						|
*      $                   Z( LDZ, * )
 | 
						|
*       ..
 | 
						|
*  
 | 
						|
*
 | 
						|
*> \par Purpose:
 | 
						|
*  =============
 | 
						|
*>
 | 
						|
*> \verbatim
 | 
						|
*>
 | 
						|
*> SGGHRD reduces a pair of real matrices (A,B) to generalized upper
 | 
						|
*> Hessenberg form using orthogonal transformations, where A is a
 | 
						|
*> general matrix and B is upper triangular.  The form of the
 | 
						|
*> generalized eigenvalue problem is
 | 
						|
*>    A*x = lambda*B*x,
 | 
						|
*> and B is typically made upper triangular by computing its QR
 | 
						|
*> factorization and moving the orthogonal matrix Q to the left side
 | 
						|
*> of the equation.
 | 
						|
*>
 | 
						|
*> This subroutine simultaneously reduces A to a Hessenberg matrix H:
 | 
						|
*>    Q**T*A*Z = H
 | 
						|
*> and transforms B to another upper triangular matrix T:
 | 
						|
*>    Q**T*B*Z = T
 | 
						|
*> in order to reduce the problem to its standard form
 | 
						|
*>    H*y = lambda*T*y
 | 
						|
*> where y = Z**T*x.
 | 
						|
*>
 | 
						|
*> The orthogonal matrices Q and Z are determined as products of Givens
 | 
						|
*> rotations.  They may either be formed explicitly, or they may be
 | 
						|
*> postmultiplied into input matrices Q1 and Z1, so that
 | 
						|
*>
 | 
						|
*>      Q1 * A * Z1**T = (Q1*Q) * H * (Z1*Z)**T
 | 
						|
*>
 | 
						|
*>      Q1 * B * Z1**T = (Q1*Q) * T * (Z1*Z)**T
 | 
						|
*>
 | 
						|
*> If Q1 is the orthogonal matrix from the QR factorization of B in the
 | 
						|
*> original equation A*x = lambda*B*x, then SGGHRD reduces the original
 | 
						|
*> problem to generalized Hessenberg form.
 | 
						|
*> \endverbatim
 | 
						|
*
 | 
						|
*  Arguments:
 | 
						|
*  ==========
 | 
						|
*
 | 
						|
*> \param[in] COMPQ
 | 
						|
*> \verbatim
 | 
						|
*>          COMPQ is CHARACTER*1
 | 
						|
*>          = 'N': do not compute Q;
 | 
						|
*>          = 'I': Q is initialized to the unit matrix, and the
 | 
						|
*>                 orthogonal matrix Q is returned;
 | 
						|
*>          = 'V': Q must contain an orthogonal matrix Q1 on entry,
 | 
						|
*>                 and the product Q1*Q is returned.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in] COMPZ
 | 
						|
*> \verbatim
 | 
						|
*>          COMPZ is CHARACTER*1
 | 
						|
*>          = 'N': do not compute Z;
 | 
						|
*>          = 'I': Z is initialized to the unit matrix, and the
 | 
						|
*>                 orthogonal matrix Z is returned;
 | 
						|
*>          = 'V': Z must contain an orthogonal matrix Z1 on entry,
 | 
						|
*>                 and the product Z1*Z is returned.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in] N
 | 
						|
*> \verbatim
 | 
						|
*>          N is INTEGER
 | 
						|
*>          The order of the matrices A and B.  N >= 0.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in] ILO
 | 
						|
*> \verbatim
 | 
						|
*>          ILO is INTEGER
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in] IHI
 | 
						|
*> \verbatim
 | 
						|
*>          IHI is INTEGER
 | 
						|
*>
 | 
						|
*>          ILO and IHI mark the rows and columns of A which are to be
 | 
						|
*>          reduced.  It is assumed that A is already upper triangular
 | 
						|
*>          in rows and columns 1:ILO-1 and IHI+1:N.  ILO and IHI are
 | 
						|
*>          normally set by a previous call to SGGBAL; otherwise they
 | 
						|
*>          should be set to 1 and N respectively.
 | 
						|
*>          1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in,out] A
 | 
						|
*> \verbatim
 | 
						|
*>          A is REAL array, dimension (LDA, N)
 | 
						|
*>          On entry, the N-by-N general matrix to be reduced.
 | 
						|
*>          On exit, the upper triangle and the first subdiagonal of A
 | 
						|
*>          are overwritten with the upper Hessenberg matrix H, and the
 | 
						|
*>          rest is set to zero.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in] LDA
 | 
						|
*> \verbatim
 | 
						|
*>          LDA is INTEGER
 | 
						|
*>          The leading dimension of the array A.  LDA >= max(1,N).
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in,out] B
 | 
						|
*> \verbatim
 | 
						|
*>          B is REAL array, dimension (LDB, N)
 | 
						|
*>          On entry, the N-by-N upper triangular matrix B.
 | 
						|
*>          On exit, the upper triangular matrix T = Q**T B Z.  The
 | 
						|
*>          elements below the diagonal are set to zero.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in] LDB
 | 
						|
*> \verbatim
 | 
						|
*>          LDB is INTEGER
 | 
						|
*>          The leading dimension of the array B.  LDB >= max(1,N).
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in,out] Q
 | 
						|
*> \verbatim
 | 
						|
*>          Q is REAL array, dimension (LDQ, N)
 | 
						|
*>          On entry, if COMPQ = 'V', the orthogonal matrix Q1,
 | 
						|
*>          typically from the QR factorization of B.
 | 
						|
*>          On exit, if COMPQ='I', the orthogonal matrix Q, and if
 | 
						|
*>          COMPQ = 'V', the product Q1*Q.
 | 
						|
*>          Not referenced if COMPQ='N'.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in] LDQ
 | 
						|
*> \verbatim
 | 
						|
*>          LDQ is INTEGER
 | 
						|
*>          The leading dimension of the array Q.
 | 
						|
*>          LDQ >= N if COMPQ='V' or 'I'; LDQ >= 1 otherwise.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in,out] Z
 | 
						|
*> \verbatim
 | 
						|
*>          Z is REAL array, dimension (LDZ, N)
 | 
						|
*>          On entry, if COMPZ = 'V', the orthogonal matrix Z1.
 | 
						|
*>          On exit, if COMPZ='I', the orthogonal matrix Z, and if
 | 
						|
*>          COMPZ = 'V', the product Z1*Z.
 | 
						|
*>          Not referenced if COMPZ='N'.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[in] LDZ
 | 
						|
*> \verbatim
 | 
						|
*>          LDZ is INTEGER
 | 
						|
*>          The leading dimension of the array Z.
 | 
						|
*>          LDZ >= N if COMPZ='V' or 'I'; LDZ >= 1 otherwise.
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*> \param[out] INFO
 | 
						|
*> \verbatim
 | 
						|
*>          INFO is INTEGER
 | 
						|
*>          = 0:  successful exit.
 | 
						|
*>          < 0:  if INFO = -i, the i-th argument had an illegal value.
 | 
						|
*> \endverbatim
 | 
						|
*
 | 
						|
*  Authors:
 | 
						|
*  ========
 | 
						|
*
 | 
						|
*> \author Univ. of Tennessee 
 | 
						|
*> \author Univ. of California Berkeley 
 | 
						|
*> \author Univ. of Colorado Denver 
 | 
						|
*> \author NAG Ltd. 
 | 
						|
*
 | 
						|
*> \date November 2011
 | 
						|
*
 | 
						|
*> \ingroup realOTHERcomputational
 | 
						|
*
 | 
						|
*> \par Further Details:
 | 
						|
*  =====================
 | 
						|
*>
 | 
						|
*> \verbatim
 | 
						|
*>
 | 
						|
*>  This routine reduces A to Hessenberg and B to triangular form by
 | 
						|
*>  an unblocked reduction, as described in _Matrix_Computations_,
 | 
						|
*>  by Golub and Van Loan (Johns Hopkins Press.)
 | 
						|
*> \endverbatim
 | 
						|
*>
 | 
						|
*  =====================================================================
 | 
						|
      SUBROUTINE SGGHRD( COMPQ, COMPZ, N, ILO, IHI, A, LDA, B, LDB, Q,
 | 
						|
     $                   LDQ, Z, LDZ, INFO )
 | 
						|
*
 | 
						|
*  -- LAPACK computational routine (version 3.4.0) --
 | 
						|
*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
 | 
						|
*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
 | 
						|
*     November 2011
 | 
						|
*
 | 
						|
*     .. Scalar Arguments ..
 | 
						|
      CHARACTER          COMPQ, COMPZ
 | 
						|
      INTEGER            IHI, ILO, INFO, LDA, LDB, LDQ, LDZ, N
 | 
						|
*     ..
 | 
						|
*     .. Array Arguments ..
 | 
						|
      REAL               A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
 | 
						|
     $                   Z( LDZ, * )
 | 
						|
*     ..
 | 
						|
*
 | 
						|
*  =====================================================================
 | 
						|
*
 | 
						|
*     .. Parameters ..
 | 
						|
      REAL               ONE, ZERO
 | 
						|
      PARAMETER          ( ONE = 1.0E+0, ZERO = 0.0E+0 )
 | 
						|
*     ..
 | 
						|
*     .. Local Scalars ..
 | 
						|
      LOGICAL            ILQ, ILZ
 | 
						|
      INTEGER            ICOMPQ, ICOMPZ, JCOL, JROW
 | 
						|
      REAL               C, S, TEMP
 | 
						|
*     ..
 | 
						|
*     .. External Functions ..
 | 
						|
      LOGICAL            LSAME
 | 
						|
      EXTERNAL           LSAME
 | 
						|
*     ..
 | 
						|
*     .. External Subroutines ..
 | 
						|
      EXTERNAL           SLARTG, SLASET, SROT, XERBLA
 | 
						|
*     ..
 | 
						|
*     .. Intrinsic Functions ..
 | 
						|
      INTRINSIC          MAX
 | 
						|
*     ..
 | 
						|
*     .. Executable Statements ..
 | 
						|
*
 | 
						|
*     Decode COMPQ
 | 
						|
*
 | 
						|
      IF( LSAME( COMPQ, 'N' ) ) THEN
 | 
						|
         ILQ = .FALSE.
 | 
						|
         ICOMPQ = 1
 | 
						|
      ELSE IF( LSAME( COMPQ, 'V' ) ) THEN
 | 
						|
         ILQ = .TRUE.
 | 
						|
         ICOMPQ = 2
 | 
						|
      ELSE IF( LSAME( COMPQ, 'I' ) ) THEN
 | 
						|
         ILQ = .TRUE.
 | 
						|
         ICOMPQ = 3
 | 
						|
      ELSE
 | 
						|
         ICOMPQ = 0
 | 
						|
      END IF
 | 
						|
*
 | 
						|
*     Decode COMPZ
 | 
						|
*
 | 
						|
      IF( LSAME( COMPZ, 'N' ) ) THEN
 | 
						|
         ILZ = .FALSE.
 | 
						|
         ICOMPZ = 1
 | 
						|
      ELSE IF( LSAME( COMPZ, 'V' ) ) THEN
 | 
						|
         ILZ = .TRUE.
 | 
						|
         ICOMPZ = 2
 | 
						|
      ELSE IF( LSAME( COMPZ, 'I' ) ) THEN
 | 
						|
         ILZ = .TRUE.
 | 
						|
         ICOMPZ = 3
 | 
						|
      ELSE
 | 
						|
         ICOMPZ = 0
 | 
						|
      END IF
 | 
						|
*
 | 
						|
*     Test the input parameters.
 | 
						|
*
 | 
						|
      INFO = 0
 | 
						|
      IF( ICOMPQ.LE.0 ) THEN
 | 
						|
         INFO = -1
 | 
						|
      ELSE IF( ICOMPZ.LE.0 ) THEN
 | 
						|
         INFO = -2
 | 
						|
      ELSE IF( N.LT.0 ) THEN
 | 
						|
         INFO = -3
 | 
						|
      ELSE IF( ILO.LT.1 ) THEN
 | 
						|
         INFO = -4
 | 
						|
      ELSE IF( IHI.GT.N .OR. IHI.LT.ILO-1 ) THEN
 | 
						|
         INFO = -5
 | 
						|
      ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
 | 
						|
         INFO = -7
 | 
						|
      ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
 | 
						|
         INFO = -9
 | 
						|
      ELSE IF( ( ILQ .AND. LDQ.LT.N ) .OR. LDQ.LT.1 ) THEN
 | 
						|
         INFO = -11
 | 
						|
      ELSE IF( ( ILZ .AND. LDZ.LT.N ) .OR. LDZ.LT.1 ) THEN
 | 
						|
         INFO = -13
 | 
						|
      END IF
 | 
						|
      IF( INFO.NE.0 ) THEN
 | 
						|
         CALL XERBLA( 'SGGHRD', -INFO )
 | 
						|
         RETURN
 | 
						|
      END IF
 | 
						|
*
 | 
						|
*     Initialize Q and Z if desired.
 | 
						|
*
 | 
						|
      IF( ICOMPQ.EQ.3 )
 | 
						|
     $   CALL SLASET( 'Full', N, N, ZERO, ONE, Q, LDQ )
 | 
						|
      IF( ICOMPZ.EQ.3 )
 | 
						|
     $   CALL SLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )
 | 
						|
*
 | 
						|
*     Quick return if possible
 | 
						|
*
 | 
						|
      IF( N.LE.1 )
 | 
						|
     $   RETURN
 | 
						|
*
 | 
						|
*     Zero out lower triangle of B
 | 
						|
*
 | 
						|
      DO 20 JCOL = 1, N - 1
 | 
						|
         DO 10 JROW = JCOL + 1, N
 | 
						|
            B( JROW, JCOL ) = ZERO
 | 
						|
   10    CONTINUE
 | 
						|
   20 CONTINUE
 | 
						|
*
 | 
						|
*     Reduce A and B
 | 
						|
*
 | 
						|
      DO 40 JCOL = ILO, IHI - 2
 | 
						|
*
 | 
						|
         DO 30 JROW = IHI, JCOL + 2, -1
 | 
						|
*
 | 
						|
*           Step 1: rotate rows JROW-1, JROW to kill A(JROW,JCOL)
 | 
						|
*
 | 
						|
            TEMP = A( JROW-1, JCOL )
 | 
						|
            CALL SLARTG( TEMP, A( JROW, JCOL ), C, S,
 | 
						|
     $                   A( JROW-1, JCOL ) )
 | 
						|
            A( JROW, JCOL ) = ZERO
 | 
						|
            CALL SROT( N-JCOL, A( JROW-1, JCOL+1 ), LDA,
 | 
						|
     $                 A( JROW, JCOL+1 ), LDA, C, S )
 | 
						|
            CALL SROT( N+2-JROW, B( JROW-1, JROW-1 ), LDB,
 | 
						|
     $                 B( JROW, JROW-1 ), LDB, C, S )
 | 
						|
            IF( ILQ )
 | 
						|
     $         CALL SROT( N, Q( 1, JROW-1 ), 1, Q( 1, JROW ), 1, C, S )
 | 
						|
*
 | 
						|
*           Step 2: rotate columns JROW, JROW-1 to kill B(JROW,JROW-1)
 | 
						|
*
 | 
						|
            TEMP = B( JROW, JROW )
 | 
						|
            CALL SLARTG( TEMP, B( JROW, JROW-1 ), C, S,
 | 
						|
     $                   B( JROW, JROW ) )
 | 
						|
            B( JROW, JROW-1 ) = ZERO
 | 
						|
            CALL SROT( IHI, A( 1, JROW ), 1, A( 1, JROW-1 ), 1, C, S )
 | 
						|
            CALL SROT( JROW-1, B( 1, JROW ), 1, B( 1, JROW-1 ), 1, C,
 | 
						|
     $                 S )
 | 
						|
            IF( ILZ )
 | 
						|
     $         CALL SROT( N, Z( 1, JROW ), 1, Z( 1, JROW-1 ), 1, C, S )
 | 
						|
   30    CONTINUE
 | 
						|
   40 CONTINUE
 | 
						|
*
 | 
						|
      RETURN
 | 
						|
*
 | 
						|
*     End of SGGHRD
 | 
						|
*
 | 
						|
      END
 |