1       SUBROUTINE ZSTT21( N, KBAND, AD, AE, SD, SE, U, LDU, WORK, RWORK,
  2      $                   RESULT )
  3 *
  4 *  -- LAPACK test routine (version 3.1) --
  5 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
  6 *     November 2006
  7 *
  8 *     .. Scalar Arguments ..
  9       INTEGER            KBAND, LDU, N
 10 *     ..
 11 *     .. Array Arguments ..
 12       DOUBLE PRECISION   AD( * ), AE( * ), RESULT2 ), RWORK( * ),
 13      $                   SD( * ), SE( * )
 14       COMPLEX*16         U( LDU, * ), WORK( * )
 15 *     ..
 16 *
 17 *  Purpose
 18 *  =======
 19 *
 20 *  ZSTT21  checks a decomposition of the form
 21 *
 22 *     A = U S U*
 23 *
 24 *  where * means conjugate transpose, A is real symmetric tridiagonal,
 25 *  U is unitary, and S is real and diagonal (if KBAND=0) or symmetric
 26 *  tridiagonal (if KBAND=1).  Two tests are performed:
 27 *
 28 *     RESULT(1) = | A - U S U* | / ( |A| n ulp )
 29 *
 30 *     RESULT(2) = | I - UU* | / ( n ulp )
 31 *
 32 *  Arguments
 33 *  =========
 34 *
 35 *  N       (input) INTEGER
 36 *          The size of the matrix.  If it is zero, ZSTT21 does nothing.
 37 *          It must be at least zero.
 38 *
 39 *  KBAND   (input) INTEGER
 40 *          The bandwidth of the matrix S.  It may only be zero or one.
 41 *          If zero, then S is diagonal, and SE is not referenced.  If
 42 *          one, then S is symmetric tri-diagonal.
 43 *
 44 *  AD      (input) DOUBLE PRECISION array, dimension (N)
 45 *          The diagonal of the original (unfactored) matrix A.  A is
 46 *          assumed to be real symmetric tridiagonal.
 47 *
 48 *  AE      (input) DOUBLE PRECISION array, dimension (N-1)
 49 *          The off-diagonal of the original (unfactored) matrix A.  A
 50 *          is assumed to be symmetric tridiagonal.  AE(1) is the (1,2)
 51 *          and (2,1) element, AE(2) is the (2,3) and (3,2) element, etc.
 52 *
 53 *  SD      (input) DOUBLE PRECISION array, dimension (N)
 54 *          The diagonal of the real (symmetric tri-) diagonal matrix S.
 55 *
 56 *  SE      (input) DOUBLE PRECISION array, dimension (N-1)
 57 *          The off-diagonal of the (symmetric tri-) diagonal matrix S.
 58 *          Not referenced if KBSND=0.  If KBAND=1, then AE(1) is the
 59 *          (1,2) and (2,1) element, SE(2) is the (2,3) and (3,2)
 60 *          element, etc.
 61 *
 62 *  U       (input) COMPLEX*16 array, dimension (LDU, N)
 63 *          The unitary matrix in the decomposition.
 64 *
 65 *  LDU     (input) INTEGER
 66 *          The leading dimension of U.  LDU must be at least N.
 67 *
 68 *  WORK    (workspace) COMPLEX*16 array, dimension (N**2)
 69 *
 70 *  RWORK   (workspace) DOUBLE PRECISION array, dimension (N)
 71 *
 72 *  RESULT  (output) DOUBLE PRECISION array, dimension (2)
 73 *          The values computed by the two tests described above.  The
 74 *          values are currently limited to 1/ulp, to avoid overflow.
 75 *          RESULT(1) is always modified.
 76 *
 77 *  =====================================================================
 78 *
 79 *     .. Parameters ..
 80       DOUBLE PRECISION   ZERO, ONE
 81       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
 82       COMPLEX*16         CZERO, CONE
 83       PARAMETER          ( CZERO = ( 0.0D+00.0D+0 ),
 84      $                   CONE = ( 1.0D+00.0D+0 ) )
 85 *     ..
 86 *     .. Local Scalars ..
 87       INTEGER            J
 88       DOUBLE PRECISION   ANORM, TEMP1, TEMP2, ULP, UNFL, WNORM
 89 *     ..
 90 *     .. External Functions ..
 91       DOUBLE PRECISION   DLAMCH, ZLANGE, ZLANHE
 92       EXTERNAL           DLAMCH, ZLANGE, ZLANHE
 93 *     ..
 94 *     .. External Subroutines ..
 95       EXTERNAL           ZGEMM, ZHER, ZHER2, ZLASET
 96 *     ..
 97 *     .. Intrinsic Functions ..
 98       INTRINSIC          ABSDBLEDCMPLXMAXMIN
 99 *     ..
100 *     .. Executable Statements ..
101 *
102 *     1)      Constants
103 *
104       RESULT1 ) = ZERO
105       RESULT2 ) = ZERO
106       IF( N.LE.0 )
107      $   RETURN
108 *
109       UNFL = DLAMCH( 'Safe minimum' )
110       ULP = DLAMCH( 'Precision' )
111 *
112 *     Do Test 1
113 *
114 *     Copy A & Compute its 1-Norm:
115 *
116       CALL ZLASET( 'Full', N, N, CZERO, CZERO, WORK, N )
117 *
118       ANORM = ZERO
119       TEMP1 = ZERO
120 *
121       DO 10 J = 1, N - 1
122          WORK( ( N+1 )*( J-1 )+1 ) = AD( J )
123          WORK( ( N+1 )*( J-1 )+2 ) = AE( J )
124          TEMP2 = ABS( AE( J ) )
125          ANORM = MAX( ANORM, ABS( AD( J ) )+TEMP1+TEMP2 )
126          TEMP1 = TEMP2
127    10 CONTINUE
128 *
129       WORK( N**2 ) = AD( N )
130       ANORM = MAX( ANORM, ABS( AD( N ) )+TEMP1, UNFL )
131 *
132 *     Norm of A - USU*
133 *
134       DO 20 J = 1, N
135          CALL ZHER( 'L', N, -SD( J ), U( 1, J ), 1, WORK, N )
136    20 CONTINUE
137 *
138       IF( N.GT.1 .AND. KBAND.EQ.1 ) THEN
139          DO 30 J = 1, N - 1
140             CALL ZHER2( 'L', N, -DCMPLX( SE( J ) ), U( 1, J ), 1,
141      $                  U( 1, J+1 ), 1, WORK, N )
142    30    CONTINUE
143       END IF
144 *
145       WNORM = ZLANHE( '1''L', N, WORK, N, RWORK )
146 *
147       IF( ANORM.GT.WNORM ) THEN
148          RESULT1 ) = ( WNORM / ANORM ) / ( N*ULP )
149       ELSE
150          IF( ANORM.LT.ONE ) THEN
151             RESULT1 ) = ( MIN( WNORM, N*ANORM ) / ANORM ) / ( N*ULP )
152          ELSE
153             RESULT1 ) = MIN( WNORM / ANORM, DBLE( N ) ) / ( N*ULP )
154          END IF
155       END IF
156 *
157 *     Do Test 2
158 *
159 *     Compute  UU* - I
160 *
161       CALL ZGEMM( 'N''C', N, N, N, CONE, U, LDU, U, LDU, CZERO, WORK,
162      $            N )
163 *
164       DO 40 J = 1, N
165          WORK( ( N+1 )*( J-1 )+1 ) = WORK( ( N+1 )*( J-1 )+1 ) - CONE
166    40 CONTINUE
167 *
168       RESULT2 ) = MINDBLE( N ), ZLANGE( '1', N, N, WORK, N,
169      $              RWORK ) ) / ( N*ULP )
170 *
171       RETURN
172 *
173 *     End of ZSTT21
174 *
175       END