📄 zlattp.f
字号:
SUBROUTINE ZLATTP( IMAT, UPLO, TRANS, DIAG, ISEED, N, AP, B, WORK,
$ RWORK, INFO )
*
* -- LAPACK test routine (version 3.1) --
* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
* November 2006
*
* .. Scalar Arguments ..
CHARACTER DIAG, TRANS, UPLO
INTEGER IMAT, INFO, N
* ..
* .. Array Arguments ..
INTEGER ISEED( 4 )
DOUBLE PRECISION RWORK( * )
COMPLEX*16 AP( * ), B( * ), WORK( * )
* ..
*
* Purpose
* =======
*
* ZLATTP generates a triangular test matrix in packed storage.
* IMAT and UPLO uniquely specify the properties of the test matrix,
* which is returned in the array AP.
*
* Arguments
* =========
*
* IMAT (input) INTEGER
* An integer key describing which matrix to generate for this
* path.
*
* UPLO (input) CHARACTER*1
* Specifies whether the matrix A will be upper or lower
* triangular.
* = 'U': Upper triangular
* = 'L': Lower triangular
*
* TRANS (input) CHARACTER*1
* Specifies whether the matrix or its transpose will be used.
* = 'N': No transpose
* = 'T': Transpose
* = 'C': Conjugate transpose
*
* DIAG (output) CHARACTER*1
* Specifies whether or not the matrix A is unit triangular.
* = 'N': Non-unit triangular
* = 'U': Unit triangular
*
* ISEED (input/output) INTEGER array, dimension (4)
* The seed vector for the random number generator (used in
* ZLATMS). Modified on exit.
*
* N (input) INTEGER
* The order of the matrix to be generated.
*
* AP (output) COMPLEX*16 array, dimension (N*(N+1)/2)
* The upper or lower triangular matrix A, packed columnwise in
* a linear array. The j-th column of A is stored in the array
* AP as follows:
* if UPLO = 'U', AP((j-1)*j/2 + i) = A(i,j) for 1<=i<=j;
* if UPLO = 'L',
* AP((j-1)*(n-j) + j*(j+1)/2 + i-j) = A(i,j) for j<=i<=n.
*
* B (output) COMPLEX*16 array, dimension (N)
* The right hand side vector, if IMAT > 10.
*
* WORK (workspace) COMPLEX*16 array, dimension (2*N)
*
* RWORK (workspace) DOUBLE PRECISION array, dimension (N)
*
* INFO (output) INTEGER
* = 0: successful exit
* < 0: if INFO = -i, the i-th argument had an illegal value
*
* =====================================================================
*
* .. Parameters ..
DOUBLE PRECISION ONE, TWO, ZERO
PARAMETER ( ONE = 1.0D+0, TWO = 2.0D+0, ZERO = 0.0D+0 )
* ..
* .. Local Scalars ..
LOGICAL UPPER
CHARACTER DIST, PACKIT, TYPE
CHARACTER*3 PATH
INTEGER I, IY, J, JC, JCNEXT, JCOUNT, JJ, JL, JR, JX,
$ KL, KU, MODE
DOUBLE PRECISION ANORM, BIGNUM, BNORM, BSCAL, C, CNDNUM, REXP,
$ SFAC, SMLNUM, T, TEXP, TLEFT, TSCAL, ULP, UNFL,
$ X, Y, Z
COMPLEX*16 CTEMP, PLUS1, PLUS2, RA, RB, S, STAR1
* ..
* .. External Functions ..
LOGICAL LSAME
INTEGER IZAMAX
DOUBLE PRECISION DLAMCH
COMPLEX*16 ZLARND
EXTERNAL LSAME, IZAMAX, DLAMCH, ZLARND
* ..
* .. External Subroutines ..
EXTERNAL DLABAD, DLARNV, ZDSCAL, ZLARNV, ZLATB4, ZLATMS,
$ ZROT, ZROTG
* ..
* .. Intrinsic Functions ..
INTRINSIC ABS, DBLE, DCMPLX, DCONJG, MAX, SQRT
* ..
* .. Executable Statements ..
*
PATH( 1: 1 ) = 'Zomplex precision'
PATH( 2: 3 ) = 'TP'
UNFL = DLAMCH( 'Safe minimum' )
ULP = DLAMCH( 'Epsilon' )*DLAMCH( 'Base' )
SMLNUM = UNFL
BIGNUM = ( ONE-ULP ) / SMLNUM
CALL DLABAD( SMLNUM, BIGNUM )
IF( ( IMAT.GE.7 .AND. IMAT.LE.10 ) .OR. IMAT.EQ.18 ) THEN
DIAG = 'U'
ELSE
DIAG = 'N'
END IF
INFO = 0
*
* Quick return if N.LE.0.
*
IF( N.LE.0 )
$ RETURN
*
* Call ZLATB4 to set parameters for CLATMS.
*
UPPER = LSAME( UPLO, 'U' )
IF( UPPER ) THEN
CALL ZLATB4( PATH, IMAT, N, N, TYPE, KL, KU, ANORM, MODE,
$ CNDNUM, DIST )
PACKIT = 'C'
ELSE
CALL ZLATB4( PATH, -IMAT, N, N, TYPE, KL, KU, ANORM, MODE,
$ CNDNUM, DIST )
PACKIT = 'R'
END IF
*
* IMAT <= 6: Non-unit triangular matrix
*
IF( IMAT.LE.6 ) THEN
CALL ZLATMS( N, N, DIST, ISEED, TYPE, RWORK, MODE, CNDNUM,
$ ANORM, KL, KU, PACKIT, AP, N, WORK, INFO )
*
* IMAT > 6: Unit triangular matrix
* The diagonal is deliberately set to something other than 1.
*
* IMAT = 7: Matrix is the identity
*
ELSE IF( IMAT.EQ.7 ) THEN
IF( UPPER ) THEN
JC = 1
DO 20 J = 1, N
DO 10 I = 1, J - 1
AP( JC+I-1 ) = ZERO
10 CONTINUE
AP( JC+J-1 ) = J
JC = JC + J
20 CONTINUE
ELSE
JC = 1
DO 40 J = 1, N
AP( JC ) = J
DO 30 I = J + 1, N
AP( JC+I-J ) = ZERO
30 CONTINUE
JC = JC + N - J + 1
40 CONTINUE
END IF
*
* IMAT > 7: Non-trivial unit triangular matrix
*
* Generate a unit triangular matrix T with condition CNDNUM by
* forming a triangular matrix with known singular values and
* filling in the zero entries with Givens rotations.
*
ELSE IF( IMAT.LE.10 ) THEN
IF( UPPER ) THEN
JC = 0
DO 60 J = 1, N
DO 50 I = 1, J - 1
AP( JC+I ) = ZERO
50 CONTINUE
AP( JC+J ) = J
JC = JC + J
60 CONTINUE
ELSE
JC = 1
DO 80 J = 1, N
AP( JC ) = J
DO 70 I = J + 1, N
AP( JC+I-J ) = ZERO
70 CONTINUE
JC = JC + N - J + 1
80 CONTINUE
END IF
*
* Since the trace of a unit triangular matrix is 1, the product
* of its singular values must be 1. Let s = sqrt(CNDNUM),
* x = sqrt(s) - 1/sqrt(s), y = sqrt(2/(n-2))*x, and z = x**2.
* The following triangular matrix has singular values s, 1, 1,
* ..., 1, 1/s:
*
* 1 y y y ... y y z
* 1 0 0 ... 0 0 y
* 1 0 ... 0 0 y
* . ... . . .
* . . . .
* 1 0 y
* 1 y
* 1
*
* To fill in the zeros, we first multiply by a matrix with small
* condition number of the form
*
* 1 0 0 0 0 ...
* 1 + * 0 0 ...
* 1 + 0 0 0
* 1 + * 0 0
* 1 + 0 0
* ...
* 1 + 0
* 1 0
* 1
*
* Each element marked with a '*' is formed by taking the product
* of the adjacent elements marked with '+'. The '*'s can be
* chosen freely, and the '+'s are chosen so that the inverse of
* T will have elements of the same magnitude as T. If the *'s in
* both T and inv(T) have small magnitude, T is well conditioned.
* The two offdiagonals of T are stored in WORK.
*
* The product of these two matrices has the form
*
* 1 y y y y y . y y z
* 1 + * 0 0 . 0 0 y
* 1 + 0 0 . 0 0 y
* 1 + * . . . .
* 1 + . . . .
* . . . . .
* . . . .
* 1 + y
* 1 y
* 1
*
* Now we multiply by Givens rotations, using the fact that
*
* [ c s ] [ 1 w ] [ -c -s ] = [ 1 -w ]
* [ -s c ] [ 0 1 ] [ s -c ] [ 0 1 ]
* and
* [ -c -s ] [ 1 0 ] [ c s ] = [ 1 0 ]
* [ s -c ] [ w 1 ] [ -s c ] [ -w 1 ]
*
* where c = w / sqrt(w**2+4) and s = 2 / sqrt(w**2+4).
*
STAR1 = 0.25D0*ZLARND( 5, ISEED )
SFAC = 0.5D0
PLUS1 = SFAC*ZLARND( 5, ISEED )
DO 90 J = 1, N, 2
PLUS2 = STAR1 / PLUS1
WORK( J ) = PLUS1
WORK( N+J ) = STAR1
IF( J+1.LE.N ) THEN
WORK( J+1 ) = PLUS2
WORK( N+J+1 ) = ZERO
PLUS1 = STAR1 / PLUS2
REXP = ZLARND( 2, ISEED )
IF( REXP.LT.ZERO ) THEN
STAR1 = -SFAC**( ONE-REXP )*ZLARND( 5, ISEED )
ELSE
STAR1 = SFAC**( ONE+REXP )*ZLARND( 5, ISEED )
END IF
END IF
90 CONTINUE
*
X = SQRT( CNDNUM ) - ONE / SQRT( CNDNUM )
IF( N.GT.2 ) THEN
Y = SQRT( TWO / DBLE( N-2 ) )*X
ELSE
Y = ZERO
END IF
Z = X*X
*
IF( UPPER ) THEN
*
* Set the upper triangle of A with a unit triangular matrix
* of known condition number.
*
JC = 1
DO 100 J = 2, N
AP( JC+1 ) = Y
IF( J.GT.2 )
$ AP( JC+J-1 ) = WORK( J-2 )
IF( J.GT.3 )
$ AP( JC+J-2 ) = WORK( N+J-3 )
JC = JC + J
100 CONTINUE
JC = JC - N
AP( JC+1 ) = Z
DO 110 J = 2, N - 1
AP( JC+J ) = Y
110 CONTINUE
ELSE
*
* Set the lower triangle of A with a unit triangular matrix
* of known condition number.
*
DO 120 I = 2, N - 1
AP( I ) = Y
120 CONTINUE
AP( N ) = Z
JC = N + 1
DO 130 J = 2, N - 1
AP( JC+1 ) = WORK( J-1 )
IF( J.LT.N-1 )
$ AP( JC+2 ) = WORK( N+J-1 )
AP( JC+N-J ) = Y
JC = JC + N - J + 1
130 CONTINUE
END IF
*
* Fill in the zeros using Givens rotations
*
IF( UPPER ) THEN
JC = 1
DO 150 J = 1, N - 1
JCNEXT = JC + J
RA = AP( JCNEXT+J-1 )
RB = TWO
CALL ZROTG( RA, RB, C, S )
*
* Multiply by [ c s; -conjg(s) c] on the left.
*
IF( N.GT.J+1 ) THEN
JX = JCNEXT + J
DO 140 I = J + 2, N
CTEMP = C*AP( JX+J ) + S*AP( JX+J+1 )
AP( JX+J+1 ) = -DCONJG( S )*AP( JX+J ) +
$ C*AP( JX+J+1 )
AP( JX+J ) = CTEMP
JX = JX + I
140 CONTINUE
END IF
*
* Multiply by [-c -s; conjg(s) -c] on the right.
*
IF( J.GT.1 )
$ CALL ZROT( J-1, AP( JCNEXT ), 1, AP( JC ), 1, -C, -S )
*
* Negate A(J,J+1).
*
AP( JCNEXT+J-1 ) = -AP( JCNEXT+J-1 )
JC = JCNEXT
150 CONTINUE
ELSE
JC = 1
DO 170 J = 1, N - 1
JCNEXT = JC + N - J + 1
RA = AP( JC+1 )
RB = TWO
CALL ZROTG( RA, RB, C, S )
S = DCONJG( S )
*
* Multiply by [ c -s; conjg(s) c] on the right.
*
IF( N.GT.J+1 )
$ CALL ZROT( N-J-1, AP( JCNEXT+1 ), 1, AP( JC+2 ), 1, C,
$ -S )
*
* Multiply by [-c s; -conjg(s) -c] on the left.
*
IF( J.GT.1 ) THEN
JX = 1
DO 160 I = 1, J - 1
CTEMP = -C*AP( JX+J-I ) + S*AP( JX+J-I+1 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -