dynare/mex/sources/libslicot/SB03SY.f

452 lines
14 KiB
Fortran

SUBROUTINE SB03SY( JOB, TRANA, LYAPUN, N, T, LDT, U, LDU, XA,
$ LDXA, SEPD, THNORM, IWORK, DWORK, LDWORK,
$ INFO )
C
C SLICOT RELEASE 5.0.
C
C Copyright (c) 2002-2009 NICONET e.V.
C
C This program is free software: you can redistribute it and/or
C modify it under the terms of the GNU General Public License as
C published by the Free Software Foundation, either version 2 of
C the License, or (at your option) any later version.
C
C This program is distributed in the hope that it will be useful,
C but WITHOUT ANY WARRANTY; without even the implied warranty of
C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
C GNU General Public License for more details.
C
C You should have received a copy of the GNU General Public License
C along with this program. If not, see
C <http://www.gnu.org/licenses/>.
C
C PURPOSE
C
C To estimate the "separation" between the matrices op(A) and
C op(A)',
C
C sepd(op(A),op(A)') = min norm(op(A)'*X*op(A) - X)/norm(X)
C = 1 / norm(inv(Omega))
C
C and/or the 1-norm of Theta, where op(A) = A or A' (A**T), and
C Omega and Theta are linear operators associated to the real
C discrete-time Lyapunov matrix equation
C
C op(A)'*X*op(A) - X = C,
C
C defined by
C
C Omega(W) = op(A)'*W*op(A) - W,
C Theta(W) = inv(Omega(op(W)'*X*op(A) + op(A)'*X*op(W))).
C
C The 1-norm condition estimators are used.
C
C ARGUMENTS
C
C Mode Parameters
C
C JOB CHARACTER*1
C Specifies the computation to be performed, as follows:
C = 'S': Compute the separation only;
C = 'T': Compute the norm of Theta only;
C = 'B': Compute both the separation and the norm of Theta.
C
C TRANA CHARACTER*1
C Specifies the form of op(A) to be used, as follows:
C = 'N': op(A) = A (No transpose);
C = 'T': op(A) = A**T (Transpose);
C = 'C': op(A) = A**T (Conjugate transpose = Transpose).
C
C LYAPUN CHARACTER*1
C Specifies whether or not the original Lyapunov equations
C should be solved, as follows:
C = 'O': Solve the original Lyapunov equations, updating
C the right-hand sides and solutions with the
C matrix U, e.g., X <-- U'*X*U;
C = 'R': Solve reduced Lyapunov equations only, without
C updating the right-hand sides and solutions.
C
C Input/Output Parameters
C
C N (input) INTEGER
C The order of the matrices A and X. N >= 0.
C
C T (input) DOUBLE PRECISION array, dimension (LDT,N)
C The leading N-by-N upper Hessenberg part of this array
C must contain the upper quasi-triangular matrix T in Schur
C canonical form from a Schur factorization of A.
C
C LDT INTEGER
C The leading dimension of array T. LDT >= MAX(1,N).
C
C U (input) DOUBLE PRECISION array, dimension (LDU,N)
C The leading N-by-N part of this array must contain the
C orthogonal matrix U from a real Schur factorization of A.
C If LYAPUN = 'R', the array U is not referenced.
C
C LDU INTEGER
C The leading dimension of array U.
C LDU >= 1, if LYAPUN = 'R';
C LDU >= MAX(1,N), if LYAPUN = 'O'.
C
C XA (input) DOUBLE PRECISION array, dimension (LDXA,N)
C The leading N-by-N part of this array must contain the
C matrix product X*op(A), if LYAPUN = 'O', or U'*X*U*op(T),
C if LYAPUN = 'R', in the Lyapunov equation.
C If JOB = 'S', the array XA is not referenced.
C
C LDXA INTEGER
C The leading dimension of array XA.
C LDXA >= 1, if JOB = 'S';
C LDXA >= MAX(1,N), if JOB = 'T' or 'B'.
C
C SEPD (output) DOUBLE PRECISION
C If JOB = 'S' or JOB = 'B', and INFO >= 0, SEPD contains
C the estimated quantity sepd(op(A),op(A)').
C If JOB = 'T' or N = 0, SEPD is not referenced.
C
C THNORM (output) DOUBLE PRECISION
C If JOB = 'T' or JOB = 'B', and INFO >= 0, THNORM contains
C the estimated 1-norm of operator Theta.
C If JOB = 'S' or N = 0, THNORM is not referenced.
C
C Workspace
C
C IWORK INTEGER array, dimension (N*N)
C
C DWORK DOUBLE PRECISION array, dimension (LDWORK)
C
C LDWORK INTEGER
C The length of the array DWORK.
C LDWORK >= 0, if N = 0;
C LDWORK >= MAX(3,2*N*N), if N > 0.
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 = N+1: if T has (almost) reciprocal eigenvalues;
C perturbed values were used to solve Lyapunov
C equations (but the matrix T is unchanged).
C
C METHOD
C
C SEPD is defined as
C
C sepd( op(A), op(A)' ) = sigma_min( K )
C
C where sigma_min(K) is the smallest singular value of the
C N*N-by-N*N matrix
C
C K = kprod( op(A)', op(A)' ) - I(N**2).
C
C I(N**2) is an N*N-by-N*N identity matrix, and kprod denotes the
C Kronecker product. The routine estimates sigma_min(K) by the
C reciprocal of an estimate of the 1-norm of inverse(K), computed as
C suggested in [1]. This involves the solution of several discrete-
C time Lyapunov equations, either direct or transposed. The true
C reciprocal 1-norm of inverse(K) cannot differ from sigma_min(K) by
C more than a factor of N.
C The 1-norm of Theta is estimated similarly.
C
C REFERENCES
C
C [1] Higham, N.J.
C FORTRAN codes for estimating the one-norm of a real or
C complex matrix, with applications to condition estimation.
C ACM Trans. Math. Softw., 14, pp. 381-396, 1988.
C
C NUMERICAL ASPECTS
C 3
C The algorithm requires 0(N ) operations.
C
C FURTHER COMMENTS
C
C When SEPD is zero, the routine returns immediately, with THNORM
C (if requested) not set. In this case, the equation is singular.
C The option LYAPUN = 'R' may occasionally produce slightly worse
C or better estimates, and it is much faster than the option 'O'.
C
C CONTRIBUTOR
C
C V. Sima, Research Institute for Informatics, Bucharest, Romania,
C Oct. 1998. Partly based on DDLSVX (and then SB03SD) by P. Petkov,
C Tech. University of Sofia, March 1998 (and December 1998).
C
C REVISIONS
C
C February 6, 1999, V. Sima, Katholieke Univ. Leuven, Belgium.
C V. Sima, Research Institute for Informatics, Bucharest, Oct. 2004.
C
C KEYWORDS
C
C Lyapunov equation, orthogonal transformation, real Schur form.
C
C ******************************************************************
C
C .. Parameters ..
DOUBLE PRECISION ZERO, ONE, HALF
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, HALF = 0.5D+0 )
C ..
C .. Scalar Arguments ..
CHARACTER JOB, LYAPUN, TRANA
INTEGER INFO, LDT, LDU, LDWORK, LDXA, N
DOUBLE PRECISION SEPD, THNORM
C ..
C .. Array Arguments ..
INTEGER IWORK( * )
DOUBLE PRECISION DWORK( * ), T( LDT, * ), U( LDU, * ),
$ XA( LDXA, * )
C ..
C .. Local Scalars ..
LOGICAL NOTRNA, UPDATE, WANTS, WANTT
CHARACTER TRANAT, UPLO
INTEGER INFO2, ITMP, KASE, NN
DOUBLE PRECISION BIGNUM, EST, SCALE
C ..
C .. External Functions ..
LOGICAL LSAME
DOUBLE PRECISION DLAMCH, DLANSY
EXTERNAL DLAMCH, DLANSY, LSAME
C ..
C .. External Subroutines ..
EXTERNAL DLACON, DLACPY, DSCAL, DSYR2K, MA02ED, MB01RU,
$ SB03MX, XERBLA
C ..
C .. Intrinsic Functions ..
INTRINSIC MAX
C ..
C .. Executable Statements ..
C
C Decode and Test input parameters.
C
WANTS = LSAME( JOB, 'S' )
WANTT = LSAME( JOB, 'T' )
NOTRNA = LSAME( TRANA, 'N' )
UPDATE = LSAME( LYAPUN, 'O' )
C
NN = N*N
INFO = 0
IF( .NOT. ( WANTS .OR. WANTT .OR. LSAME( JOB, 'B' ) ) ) THEN
INFO = -1
ELSE IF( .NOT.( NOTRNA .OR. LSAME( TRANA, 'T' ) .OR.
$ LSAME( TRANA, 'C' ) ) ) THEN
INFO = -2
ELSE IF( .NOT.( UPDATE .OR. LSAME( LYAPUN, 'R' ) ) ) THEN
INFO = -3
ELSE IF( N.LT.0 ) THEN
INFO = -4
ELSE IF( LDT.LT.MAX( 1, N ) ) THEN
INFO = -6
ELSE IF( LDU.LT.1 .OR. ( UPDATE .AND. LDU.LT.N ) ) THEN
INFO = -8
ELSE IF( LDXA.LT.1 .OR. ( .NOT.WANTS .AND. LDXA.LT.N ) ) THEN
INFO = -10
ELSE IF( LDWORK.LT.0 .OR.
$ ( LDWORK.LT.MAX( 3, 2*NN ) .AND. N.GT.0 ) ) THEN
INFO = -15
END IF
C
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'SB03SY', -INFO )
RETURN
END IF
C
C Quick return if possible.
C
IF( N.EQ.0 )
$ RETURN
C
ITMP = NN + 1
C
IF( NOTRNA ) THEN
TRANAT = 'T'
ELSE
TRANAT = 'N'
END IF
C
IF( .NOT.WANTT ) THEN
C
C Estimate sepd(op(A),op(A)').
C Workspace: max(3,2*N*N).
C
KASE = 0
C
C REPEAT
10 CONTINUE
CALL DLACON( NN, DWORK( ITMP ), DWORK, IWORK, EST, KASE )
IF( KASE.NE.0 ) THEN
C
C Select the triangular part of symmetric matrix to be used.
C
IF( DLANSY( '1-norm', 'Upper', N, DWORK, N, DWORK( ITMP ) )
$ .GE.
$ DLANSY( '1-norm', 'Lower', N, DWORK, N, DWORK( ITMP ) )
$ ) THEN
UPLO = 'U'
ELSE
UPLO = 'L'
END IF
C
IF( UPDATE ) THEN
C
C Transform the right-hand side: RHS := U'*RHS*U.
C
CALL MB01RU( UPLO, 'Transpose', N, N, ZERO, ONE, DWORK,
$ N, U, LDU, DWORK, N, DWORK( ITMP ), NN,
$ INFO2 )
CALL DSCAL( N, HALF, DWORK, N+1 )
END IF
CALL MA02ED( UPLO, N, DWORK, N )
C
IF( KASE.EQ.1 ) THEN
C
C Solve op(T)'*Y*op(T) - Y = scale*RHS.
C
CALL SB03MX( TRANA, N, T, LDT, DWORK, N, SCALE,
$ DWORK( ITMP ), INFO2 )
ELSE
C
C Solve op(T)*W*op(T)' - W = scale*RHS.
C
CALL SB03MX( TRANAT, N, T, LDT, DWORK, N, SCALE,
$ DWORK( ITMP ), INFO2 )
END IF
C
IF( INFO2.GT.0 )
$ INFO = N + 1
C
IF( UPDATE ) THEN
C
C Transform back to obtain the solution: Z := U*Z*U', with
C Z = Y or Z = W.
C
CALL MB01RU( UPLO, 'No transpose', N, N, ZERO, ONE,
$ DWORK, N, U, LDU, DWORK, N, DWORK( ITMP ),
$ NN, INFO2 )
CALL DSCAL( N, HALF, DWORK, N+1 )
C
C Fill in the remaining triangle of the symmetric matrix.
C
CALL MA02ED( UPLO, N, DWORK, N )
END IF
C
GO TO 10
END IF
C UNTIL KASE = 0
C
IF( EST.GT.SCALE ) THEN
SEPD = SCALE / EST
ELSE
BIGNUM = ONE / DLAMCH( 'Safe minimum' )
IF( SCALE.LT.EST*BIGNUM ) THEN
SEPD = SCALE / EST
ELSE
SEPD = BIGNUM
END IF
END IF
C
C Return if the equation is singular.
C
IF( SEPD.EQ.ZERO )
$ RETURN
END IF
C
IF( .NOT.WANTS ) THEN
C
C Estimate norm(Theta).
C Workspace: max(3,2*N*N).
C
KASE = 0
C
C REPEAT
20 CONTINUE
CALL DLACON( NN, DWORK( ITMP ), DWORK, IWORK, EST, KASE )
IF( KASE.NE.0 ) THEN
C
C Select the triangular part of symmetric matrix to be used.
C
IF( DLANSY( '1-norm', 'Upper', N, DWORK, N, DWORK( ITMP ) )
$ .GE.
$ DLANSY( '1-norm', 'Lower', N, DWORK, N, DWORK( ITMP ) )
$ ) THEN
UPLO = 'U'
ELSE
UPLO = 'L'
END IF
C
C Fill in the remaining triangle of the symmetric matrix.
C
CALL MA02ED( UPLO, N, DWORK, N )
C
C Compute RHS = op(W)'*X*op(A) + op(A)'*X*op(W).
C
CALL DSYR2K( UPLO, TRANAT, N, N, ONE, DWORK, N, XA, LDXA,
$ ZERO, DWORK( ITMP ), N )
CALL DLACPY( UPLO, N, N, DWORK( ITMP ), N, DWORK, N )
C
IF( UPDATE ) THEN
C
C Transform the right-hand side: RHS := U'*RHS*U.
C
CALL MB01RU( UPLO, 'Transpose', N, N, ZERO, ONE, DWORK,
$ N, U, LDU, DWORK, N, DWORK( ITMP ), NN,
$ INFO2 )
CALL DSCAL( N, HALF, DWORK, N+1 )
END IF
CALL MA02ED( UPLO, N, DWORK, N )
C
IF( KASE.EQ.1 ) THEN
C
C Solve op(T)'*Y*op(T) - Y = scale*RHS.
C
CALL SB03MX( TRANA, N, T, LDT, DWORK, N, SCALE,
$ DWORK( ITMP ), INFO2 )
ELSE
C
C Solve op(T)*W*op(T)' - W = scale*RHS.
C
CALL SB03MX( TRANAT, N, T, LDT, DWORK, N, SCALE,
$ DWORK( ITMP ), INFO2 )
END IF
C
IF( INFO2.GT.0 )
$ INFO = N + 1
C
IF( UPDATE ) THEN
C
C Transform back to obtain the solution: Z := U*Z*U', with
C Z = Y or Z = W.
C
CALL MB01RU( UPLO, 'No transpose', N, N, ZERO, ONE,
$ DWORK, N, U, LDU, DWORK, N, DWORK( ITMP ),
$ NN, INFO2 )
CALL DSCAL( N, HALF, DWORK, N+1 )
C
C Fill in the remaining triangle of the symmetric matrix.
C
CALL MA02ED( UPLO, N, DWORK, N )
END IF
C
GO TO 20
END IF
C UNTIL KASE = 0
C
IF( EST.LT.SCALE ) THEN
THNORM = EST / SCALE
ELSE
BIGNUM = ONE / DLAMCH( 'Safe minimum' )
IF( EST.LT.SCALE*BIGNUM ) THEN
THNORM = EST / SCALE
ELSE
THNORM = BIGNUM
END IF
END IF
END IF
C
RETURN
C *** Last line of SB03SY ***
END