434 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Fortran
		
	
	
	
			
		
		
	
	
			434 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Fortran
		
	
	
	
| *> \brief \b DLAEXC swaps adjacent diagonal blocks of a real upper quasi-triangular matrix in Schur canonical form, by an orthogonal similarity transformation.
 | |
| *
 | |
| *  =========== DOCUMENTATION ===========
 | |
| *
 | |
| * Online html documentation available at
 | |
| *            http://www.netlib.org/lapack/explore-html/
 | |
| *
 | |
| *> \htmlonly
 | |
| *> Download DLAEXC + dependencies
 | |
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlaexc.f">
 | |
| *> [TGZ]</a>
 | |
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlaexc.f">
 | |
| *> [ZIP]</a>
 | |
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlaexc.f">
 | |
| *> [TXT]</a>
 | |
| *> \endhtmlonly
 | |
| *
 | |
| *  Definition:
 | |
| *  ===========
 | |
| *
 | |
| *       SUBROUTINE DLAEXC( WANTQ, N, T, LDT, Q, LDQ, J1, N1, N2, WORK,
 | |
| *                          INFO )
 | |
| *
 | |
| *       .. Scalar Arguments ..
 | |
| *       LOGICAL            WANTQ
 | |
| *       INTEGER            INFO, J1, LDQ, LDT, N, N1, N2
 | |
| *       ..
 | |
| *       .. Array Arguments ..
 | |
| *       DOUBLE PRECISION   Q( LDQ, * ), T( LDT, * ), WORK( * )
 | |
| *       ..
 | |
| *
 | |
| *
 | |
| *> \par Purpose:
 | |
| *  =============
 | |
| *>
 | |
| *> \verbatim
 | |
| *>
 | |
| *> DLAEXC swaps adjacent diagonal blocks T11 and T22 of order 1 or 2 in
 | |
| *> an upper quasi-triangular matrix T by an orthogonal similarity
 | |
| *> transformation.
 | |
| *>
 | |
| *> T must be in Schur canonical form, that is, block upper triangular
 | |
| *> with 1-by-1 and 2-by-2 diagonal blocks; each 2-by-2 diagonal block
 | |
| *> has its diagonal elements equal and its off-diagonal elements of
 | |
| *> opposite sign.
 | |
| *> \endverbatim
 | |
| *
 | |
| *  Arguments:
 | |
| *  ==========
 | |
| *
 | |
| *> \param[in] WANTQ
 | |
| *> \verbatim
 | |
| *>          WANTQ is LOGICAL
 | |
| *>          = .TRUE. : accumulate the transformation in the matrix Q;
 | |
| *>          = .FALSE.: do not accumulate the transformation.
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[in] N
 | |
| *> \verbatim
 | |
| *>          N is INTEGER
 | |
| *>          The order of the matrix T. N >= 0.
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[in,out] T
 | |
| *> \verbatim
 | |
| *>          T is DOUBLE PRECISION array, dimension (LDT,N)
 | |
| *>          On entry, the upper quasi-triangular matrix T, in Schur
 | |
| *>          canonical form.
 | |
| *>          On exit, the updated matrix T, again in Schur canonical form.
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[in] LDT
 | |
| *> \verbatim
 | |
| *>          LDT is INTEGER
 | |
| *>          The leading dimension of the array T. LDT >= max(1,N).
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[in,out] Q
 | |
| *> \verbatim
 | |
| *>          Q is DOUBLE PRECISION array, dimension (LDQ,N)
 | |
| *>          On entry, if WANTQ is .TRUE., the orthogonal matrix Q.
 | |
| *>          On exit, if WANTQ is .TRUE., the updated matrix Q.
 | |
| *>          If WANTQ is .FALSE., Q is not referenced.
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[in] LDQ
 | |
| *> \verbatim
 | |
| *>          LDQ is INTEGER
 | |
| *>          The leading dimension of the array Q.
 | |
| *>          LDQ >= 1; and if WANTQ is .TRUE., LDQ >= N.
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[in] J1
 | |
| *> \verbatim
 | |
| *>          J1 is INTEGER
 | |
| *>          The index of the first row of the first block T11.
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[in] N1
 | |
| *> \verbatim
 | |
| *>          N1 is INTEGER
 | |
| *>          The order of the first block T11. N1 = 0, 1 or 2.
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[in] N2
 | |
| *> \verbatim
 | |
| *>          N2 is INTEGER
 | |
| *>          The order of the second block T22. N2 = 0, 1 or 2.
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[out] WORK
 | |
| *> \verbatim
 | |
| *>          WORK is DOUBLE PRECISION array, dimension (N)
 | |
| *> \endverbatim
 | |
| *>
 | |
| *> \param[out] INFO
 | |
| *> \verbatim
 | |
| *>          INFO is INTEGER
 | |
| *>          = 0: successful exit
 | |
| *>          = 1: the transformed matrix T would be too far from Schur
 | |
| *>               form; the blocks are not swapped and T and Q are
 | |
| *>               unchanged.
 | |
| *> \endverbatim
 | |
| *
 | |
| *  Authors:
 | |
| *  ========
 | |
| *
 | |
| *> \author Univ. of Tennessee
 | |
| *> \author Univ. of California Berkeley
 | |
| *> \author Univ. of Colorado Denver
 | |
| *> \author NAG Ltd.
 | |
| *
 | |
| *> \ingroup doubleOTHERauxiliary
 | |
| *
 | |
| *  =====================================================================
 | |
|       SUBROUTINE DLAEXC( WANTQ, N, T, LDT, Q, LDQ, J1, N1, N2, WORK,
 | |
|      $                   INFO )
 | |
| *
 | |
| *  -- LAPACK auxiliary routine --
 | |
| *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
 | |
| *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
 | |
| *
 | |
| *     .. Scalar Arguments ..
 | |
|       LOGICAL            WANTQ
 | |
|       INTEGER            INFO, J1, LDQ, LDT, N, N1, N2
 | |
| *     ..
 | |
| *     .. Array Arguments ..
 | |
|       DOUBLE PRECISION   Q( LDQ, * ), T( LDT, * ), WORK( * )
 | |
| *     ..
 | |
| *
 | |
| *  =====================================================================
 | |
| *
 | |
| *     .. Parameters ..
 | |
|       DOUBLE PRECISION   ZERO, ONE
 | |
|       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
 | |
|       DOUBLE PRECISION   TEN
 | |
|       PARAMETER          ( TEN = 1.0D+1 )
 | |
|       INTEGER            LDD, LDX
 | |
|       PARAMETER          ( LDD = 4, LDX = 2 )
 | |
| *     ..
 | |
| *     .. Local Scalars ..
 | |
|       INTEGER            IERR, J2, J3, J4, K, ND
 | |
|       DOUBLE PRECISION   CS, DNORM, EPS, SCALE, SMLNUM, SN, T11, T22,
 | |
|      $                   T33, TAU, TAU1, TAU2, TEMP, THRESH, WI1, WI2,
 | |
|      $                   WR1, WR2, XNORM
 | |
| *     ..
 | |
| *     .. Local Arrays ..
 | |
|       DOUBLE PRECISION   D( LDD, 4 ), U( 3 ), U1( 3 ), U2( 3 ),
 | |
|      $                   X( LDX, 2 )
 | |
| *     ..
 | |
| *     .. External Functions ..
 | |
|       DOUBLE PRECISION   DLAMCH, DLANGE
 | |
|       EXTERNAL           DLAMCH, DLANGE
 | |
| *     ..
 | |
| *     .. External Subroutines ..
 | |
|       EXTERNAL           DLACPY, DLANV2, DLARFG, DLARFX, DLARTG, DLASY2,
 | |
|      $                   DROT
 | |
| *     ..
 | |
| *     .. Intrinsic Functions ..
 | |
|       INTRINSIC          ABS, MAX
 | |
| *     ..
 | |
| *     .. Executable Statements ..
 | |
| *
 | |
|       INFO = 0
 | |
| *
 | |
| *     Quick return if possible
 | |
| *
 | |
|       IF( N.EQ.0 .OR. N1.EQ.0 .OR. N2.EQ.0 )
 | |
|      $   RETURN
 | |
|       IF( J1+N1.GT.N )
 | |
|      $   RETURN
 | |
| *
 | |
|       J2 = J1 + 1
 | |
|       J3 = J1 + 2
 | |
|       J4 = J1 + 3
 | |
| *
 | |
|       IF( N1.EQ.1 .AND. N2.EQ.1 ) THEN
 | |
| *
 | |
| *        Swap two 1-by-1 blocks.
 | |
| *
 | |
|          T11 = T( J1, J1 )
 | |
|          T22 = T( J2, J2 )
 | |
| *
 | |
| *        Determine the transformation to perform the interchange.
 | |
| *
 | |
|          CALL DLARTG( T( J1, J2 ), T22-T11, CS, SN, TEMP )
 | |
| *
 | |
| *        Apply transformation to the matrix T.
 | |
| *
 | |
|          IF( J3.LE.N )
 | |
|      $      CALL DROT( N-J1-1, T( J1, J3 ), LDT, T( J2, J3 ), LDT, CS,
 | |
|      $                 SN )
 | |
|          CALL DROT( J1-1, T( 1, J1 ), 1, T( 1, J2 ), 1, CS, SN )
 | |
| *
 | |
|          T( J1, J1 ) = T22
 | |
|          T( J2, J2 ) = T11
 | |
| *
 | |
|          IF( WANTQ ) THEN
 | |
| *
 | |
| *           Accumulate transformation in the matrix Q.
 | |
| *
 | |
|             CALL DROT( N, Q( 1, J1 ), 1, Q( 1, J2 ), 1, CS, SN )
 | |
|          END IF
 | |
| *
 | |
|       ELSE
 | |
| *
 | |
| *        Swapping involves at least one 2-by-2 block.
 | |
| *
 | |
| *        Copy the diagonal block of order N1+N2 to the local array D
 | |
| *        and compute its norm.
 | |
| *
 | |
|          ND = N1 + N2
 | |
|          CALL DLACPY( 'Full', ND, ND, T( J1, J1 ), LDT, D, LDD )
 | |
|          DNORM = DLANGE( 'Max', ND, ND, D, LDD, WORK )
 | |
| *
 | |
| *        Compute machine-dependent threshold for test for accepting
 | |
| *        swap.
 | |
| *
 | |
|          EPS = DLAMCH( 'P' )
 | |
|          SMLNUM = DLAMCH( 'S' ) / EPS
 | |
|          THRESH = MAX( TEN*EPS*DNORM, SMLNUM )
 | |
| *
 | |
| *        Solve T11*X - X*T22 = scale*T12 for X.
 | |
| *
 | |
|          CALL DLASY2( .FALSE., .FALSE., -1, N1, N2, D, LDD,
 | |
|      $                D( N1+1, N1+1 ), LDD, D( 1, N1+1 ), LDD, SCALE, X,
 | |
|      $                LDX, XNORM, IERR )
 | |
| *
 | |
| *        Swap the adjacent diagonal blocks.
 | |
| *
 | |
|          K = N1 + N1 + N2 - 3
 | |
|          GO TO ( 10, 20, 30 )K
 | |
| *
 | |
|    10    CONTINUE
 | |
| *
 | |
| *        N1 = 1, N2 = 2: generate elementary reflector H so that:
 | |
| *
 | |
| *        ( scale, X11, X12 ) H = ( 0, 0, * )
 | |
| *
 | |
|          U( 1 ) = SCALE
 | |
|          U( 2 ) = X( 1, 1 )
 | |
|          U( 3 ) = X( 1, 2 )
 | |
|          CALL DLARFG( 3, U( 3 ), U, 1, TAU )
 | |
|          U( 3 ) = ONE
 | |
|          T11 = T( J1, J1 )
 | |
| *
 | |
| *        Perform swap provisionally on diagonal block in D.
 | |
| *
 | |
|          CALL DLARFX( 'L', 3, 3, U, TAU, D, LDD, WORK )
 | |
|          CALL DLARFX( 'R', 3, 3, U, TAU, D, LDD, WORK )
 | |
| *
 | |
| *        Test whether to reject swap.
 | |
| *
 | |
|          IF( MAX( ABS( D( 3, 1 ) ), ABS( D( 3, 2 ) ), ABS( D( 3,
 | |
|      $       3 )-T11 ) ).GT.THRESH )GO TO 50
 | |
| *
 | |
| *        Accept swap: apply transformation to the entire matrix T.
 | |
| *
 | |
|          CALL DLARFX( 'L', 3, N-J1+1, U, TAU, T( J1, J1 ), LDT, WORK )
 | |
|          CALL DLARFX( 'R', J2, 3, U, TAU, T( 1, J1 ), LDT, WORK )
 | |
| *
 | |
|          T( J3, J1 ) = ZERO
 | |
|          T( J3, J2 ) = ZERO
 | |
|          T( J3, J3 ) = T11
 | |
| *
 | |
|          IF( WANTQ ) THEN
 | |
| *
 | |
| *           Accumulate transformation in the matrix Q.
 | |
| *
 | |
|             CALL DLARFX( 'R', N, 3, U, TAU, Q( 1, J1 ), LDQ, WORK )
 | |
|          END IF
 | |
|          GO TO 40
 | |
| *
 | |
|    20    CONTINUE
 | |
| *
 | |
| *        N1 = 2, N2 = 1: generate elementary reflector H so that:
 | |
| *
 | |
| *        H (  -X11 ) = ( * )
 | |
| *          (  -X21 ) = ( 0 )
 | |
| *          ( scale ) = ( 0 )
 | |
| *
 | |
|          U( 1 ) = -X( 1, 1 )
 | |
|          U( 2 ) = -X( 2, 1 )
 | |
|          U( 3 ) = SCALE
 | |
|          CALL DLARFG( 3, U( 1 ), U( 2 ), 1, TAU )
 | |
|          U( 1 ) = ONE
 | |
|          T33 = T( J3, J3 )
 | |
| *
 | |
| *        Perform swap provisionally on diagonal block in D.
 | |
| *
 | |
|          CALL DLARFX( 'L', 3, 3, U, TAU, D, LDD, WORK )
 | |
|          CALL DLARFX( 'R', 3, 3, U, TAU, D, LDD, WORK )
 | |
| *
 | |
| *        Test whether to reject swap.
 | |
| *
 | |
|          IF( MAX( ABS( D( 2, 1 ) ), ABS( D( 3, 1 ) ), ABS( D( 1,
 | |
|      $       1 )-T33 ) ).GT.THRESH )GO TO 50
 | |
| *
 | |
| *        Accept swap: apply transformation to the entire matrix T.
 | |
| *
 | |
|          CALL DLARFX( 'R', J3, 3, U, TAU, T( 1, J1 ), LDT, WORK )
 | |
|          CALL DLARFX( 'L', 3, N-J1, U, TAU, T( J1, J2 ), LDT, WORK )
 | |
| *
 | |
|          T( J1, J1 ) = T33
 | |
|          T( J2, J1 ) = ZERO
 | |
|          T( J3, J1 ) = ZERO
 | |
| *
 | |
|          IF( WANTQ ) THEN
 | |
| *
 | |
| *           Accumulate transformation in the matrix Q.
 | |
| *
 | |
|             CALL DLARFX( 'R', N, 3, U, TAU, Q( 1, J1 ), LDQ, WORK )
 | |
|          END IF
 | |
|          GO TO 40
 | |
| *
 | |
|    30    CONTINUE
 | |
| *
 | |
| *        N1 = 2, N2 = 2: generate elementary reflectors H(1) and H(2) so
 | |
| *        that:
 | |
| *
 | |
| *        H(2) H(1) (  -X11  -X12 ) = (  *  * )
 | |
| *                  (  -X21  -X22 )   (  0  * )
 | |
| *                  ( scale    0  )   (  0  0 )
 | |
| *                  (    0  scale )   (  0  0 )
 | |
| *
 | |
|          U1( 1 ) = -X( 1, 1 )
 | |
|          U1( 2 ) = -X( 2, 1 )
 | |
|          U1( 3 ) = SCALE
 | |
|          CALL DLARFG( 3, U1( 1 ), U1( 2 ), 1, TAU1 )
 | |
|          U1( 1 ) = ONE
 | |
| *
 | |
|          TEMP = -TAU1*( X( 1, 2 )+U1( 2 )*X( 2, 2 ) )
 | |
|          U2( 1 ) = -TEMP*U1( 2 ) - X( 2, 2 )
 | |
|          U2( 2 ) = -TEMP*U1( 3 )
 | |
|          U2( 3 ) = SCALE
 | |
|          CALL DLARFG( 3, U2( 1 ), U2( 2 ), 1, TAU2 )
 | |
|          U2( 1 ) = ONE
 | |
| *
 | |
| *        Perform swap provisionally on diagonal block in D.
 | |
| *
 | |
|          CALL DLARFX( 'L', 3, 4, U1, TAU1, D, LDD, WORK )
 | |
|          CALL DLARFX( 'R', 4, 3, U1, TAU1, D, LDD, WORK )
 | |
|          CALL DLARFX( 'L', 3, 4, U2, TAU2, D( 2, 1 ), LDD, WORK )
 | |
|          CALL DLARFX( 'R', 4, 3, U2, TAU2, D( 1, 2 ), LDD, WORK )
 | |
| *
 | |
| *        Test whether to reject swap.
 | |
| *
 | |
|          IF( MAX( ABS( D( 3, 1 ) ), ABS( D( 3, 2 ) ), ABS( D( 4, 1 ) ),
 | |
|      $       ABS( D( 4, 2 ) ) ).GT.THRESH )GO TO 50
 | |
| *
 | |
| *        Accept swap: apply transformation to the entire matrix T.
 | |
| *
 | |
|          CALL DLARFX( 'L', 3, N-J1+1, U1, TAU1, T( J1, J1 ), LDT, WORK )
 | |
|          CALL DLARFX( 'R', J4, 3, U1, TAU1, T( 1, J1 ), LDT, WORK )
 | |
|          CALL DLARFX( 'L', 3, N-J1+1, U2, TAU2, T( J2, J1 ), LDT, WORK )
 | |
|          CALL DLARFX( 'R', J4, 3, U2, TAU2, T( 1, J2 ), LDT, WORK )
 | |
| *
 | |
|          T( J3, J1 ) = ZERO
 | |
|          T( J3, J2 ) = ZERO
 | |
|          T( J4, J1 ) = ZERO
 | |
|          T( J4, J2 ) = ZERO
 | |
| *
 | |
|          IF( WANTQ ) THEN
 | |
| *
 | |
| *           Accumulate transformation in the matrix Q.
 | |
| *
 | |
|             CALL DLARFX( 'R', N, 3, U1, TAU1, Q( 1, J1 ), LDQ, WORK )
 | |
|             CALL DLARFX( 'R', N, 3, U2, TAU2, Q( 1, J2 ), LDQ, WORK )
 | |
|          END IF
 | |
| *
 | |
|    40    CONTINUE
 | |
| *
 | |
|          IF( N2.EQ.2 ) THEN
 | |
| *
 | |
| *           Standardize new 2-by-2 block T11
 | |
| *
 | |
|             CALL DLANV2( T( J1, J1 ), T( J1, J2 ), T( J2, J1 ),
 | |
|      $                   T( J2, J2 ), WR1, WI1, WR2, WI2, CS, SN )
 | |
|             CALL DROT( N-J1-1, T( J1, J1+2 ), LDT, T( J2, J1+2 ), LDT,
 | |
|      $                 CS, SN )
 | |
|             CALL DROT( J1-1, T( 1, J1 ), 1, T( 1, J2 ), 1, CS, SN )
 | |
|             IF( WANTQ )
 | |
|      $         CALL DROT( N, Q( 1, J1 ), 1, Q( 1, J2 ), 1, CS, SN )
 | |
|          END IF
 | |
| *
 | |
|          IF( N1.EQ.2 ) THEN
 | |
| *
 | |
| *           Standardize new 2-by-2 block T22
 | |
| *
 | |
|             J3 = J1 + N2
 | |
|             J4 = J3 + 1
 | |
|             CALL DLANV2( T( J3, J3 ), T( J3, J4 ), T( J4, J3 ),
 | |
|      $                   T( J4, J4 ), WR1, WI1, WR2, WI2, CS, SN )
 | |
|             IF( J3+2.LE.N )
 | |
|      $         CALL DROT( N-J3-1, T( J3, J3+2 ), LDT, T( J4, J3+2 ),
 | |
|      $                    LDT, CS, SN )
 | |
|             CALL DROT( J3-1, T( 1, J3 ), 1, T( 1, J4 ), 1, CS, SN )
 | |
|             IF( WANTQ )
 | |
|      $         CALL DROT( N, Q( 1, J3 ), 1, Q( 1, J4 ), 1, CS, SN )
 | |
|          END IF
 | |
| *
 | |
|       END IF
 | |
|       RETURN
 | |
| *
 | |
| *     Exit with INFO = 1 if swap was rejected.
 | |
| *
 | |
|    50 CONTINUE
 | |
|       INFO = 1
 | |
|       RETURN
 | |
| *
 | |
| *     End of DLAEXC
 | |
| *
 | |
|       END
 |