1       SUBROUTINE CHPT21( ITYPE, UPLO, N, KBAND, AP, D, E, U, LDU, VP,
  2      $                   TAU, WORK, RWORK, 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       CHARACTER          UPLO
 10       INTEGER            ITYPE, KBAND, LDU, N
 11 *     ..
 12 *     .. Array Arguments ..
 13       REAL               D( * ), E( * ), RESULT2 ), RWORK( * )
 14       COMPLEX            AP( * ), TAU( * ), U( LDU, * ), VP( * ),
 15      $                   WORK( * )
 16 *     ..
 17 *
 18 *  Purpose
 19 *  =======
 20 *
 21 *  CHPT21  generally checks a decomposition of the form
 22 *
 23 *          A = U S U*
 24 *
 25 *  where * means conjugate transpose, A is hermitian, U is
 26 *  unitary, and S is diagonal (if KBAND=0) or (real) symmetric
 27 *  tridiagonal (if KBAND=1).  If ITYPE=1, then U is represented as
 28 *  a dense matrix, otherwise the U is expressed as a product of
 29 *  Householder transformations, whose vectors are stored in the
 30 *  array "V" and whose scaling constants are in "TAU"; we shall
 31 *  use the letter "V" to refer to the product of Householder
 32 *  transformations (which should be equal to U).
 33 *
 34 *  Specifically, if ITYPE=1, then:
 35 *
 36 *          RESULT(1) = | A - U S U* | / ( |A| n ulp ) *and*
 37 *          RESULT(2) = | I - UU* | / ( n ulp )
 38 *
 39 *  If ITYPE=2, then:
 40 *
 41 *          RESULT(1) = | A - V S V* | / ( |A| n ulp )
 42 *
 43 *  If ITYPE=3, then:
 44 *
 45 *          RESULT(1) = | I - UV* | / ( n ulp )
 46 *
 47 *  Packed storage means that, for example, if UPLO='U', then the columns
 48 *  of the upper triangle of A are stored one after another, so that
 49 *  A(1,j+1) immediately follows A(j,j) in the array AP.  Similarly, if
 50 *  UPLO='L', then the columns of the lower triangle of A are stored one
 51 *  after another in AP, so that A(j+1,j+1) immediately follows A(n,j)
 52 *  in the array AP.  This means that A(i,j) is stored in:
 53 *
 54 *     AP( i + j*(j-1)/2 )                 if UPLO='U'
 55 *
 56 *     AP( i + (2*n-j)*(j-1)/2 )           if UPLO='L'
 57 *
 58 *  The array VP bears the same relation to the matrix V that A does to
 59 *  AP.
 60 *
 61 *  For ITYPE > 1, the transformation U is expressed as a product
 62 *  of Householder transformations:
 63 *
 64 *     If UPLO='U', then  V = H(n-1)...H(1),  where
 65 *
 66 *         H(j) = I  -  tau(j) v(j) v(j)*
 67 *
 68 *     and the first j-1 elements of v(j) are stored in V(1:j-1,j+1),
 69 *     (i.e., VP( j*(j+1)/2 + 1 : j*(j+1)/2 + j-1 ) ),
 70 *     the j-th element is 1, and the last n-j elements are 0.
 71 *
 72 *     If UPLO='L', then  V = H(1)...H(n-1),  where
 73 *
 74 *         H(j) = I  -  tau(j) v(j) v(j)*
 75 *
 76 *     and the first j elements of v(j) are 0, the (j+1)-st is 1, and the
 77 *     (j+2)-nd through n-th elements are stored in V(j+2:n,j) (i.e.,
 78 *     in VP( (2*n-j)*(j-1)/2 + j+2 : (2*n-j)*(j-1)/2 + n ) .)
 79 *
 80 *  Arguments
 81 *  =========
 82 *
 83 *  ITYPE   (input) INTEGER
 84 *          Specifies the type of tests to be performed.
 85 *          1: U expressed as a dense unitary matrix:
 86 *             RESULT(1) = | A - U S U* | / ( |A| n ulp )   *and*
 87 *             RESULT(2) = | I - UU* | / ( n ulp )
 88 *
 89 *          2: U expressed as a product V of Housholder transformations:
 90 *             RESULT(1) = | A - V S V* | / ( |A| n ulp )
 91 *
 92 *          3: U expressed both as a dense unitary matrix and
 93 *             as a product of Housholder transformations:
 94 *             RESULT(1) = | I - UV* | / ( n ulp )
 95 *
 96 *  UPLO    (input) CHARACTER
 97 *          If UPLO='U', the upper triangle of A and V will be used and
 98 *          the (strictly) lower triangle will not be referenced.
 99 *          If UPLO='L', the lower triangle of A and V will be used and
100 *          the (strictly) upper triangle will not be referenced.
101 *
102 *  N       (input) INTEGER
103 *          The size of the matrix.  If it is zero, CHPT21 does nothing.
104 *          It must be at least zero.
105 *
106 *  KBAND   (input) INTEGER
107 *          The bandwidth of the matrix.  It may only be zero or one.
108 *          If zero, then S is diagonal, and E is not referenced.  If
109 *          one, then S is symmetric tri-diagonal.
110 *
111 *  AP      (input) COMPLEX array, dimension (N*(N+1)/2)
112 *          The original (unfactored) matrix.  It is assumed to be
113 *          hermitian, and contains the columns of just the upper
114 *          triangle (UPLO='U') or only the lower triangle (UPLO='L'),
115 *          packed one after another.
116 *
117 *  D       (input) REAL array, dimension (N)
118 *          The diagonal of the (symmetric tri-) diagonal matrix.
119 *
120 *  E       (input) REAL array, dimension (N)
121 *          The off-diagonal of the (symmetric tri-) diagonal matrix.
122 *          E(1) is the (1,2) and (2,1) element, E(2) is the (2,3) and
123 *          (3,2) element, etc.
124 *          Not referenced if KBAND=0.
125 *
126 *  U       (input) COMPLEX array, dimension (LDU, N)
127 *          If ITYPE=1 or 3, this contains the unitary matrix in
128 *          the decomposition, expressed as a dense matrix.  If ITYPE=2,
129 *          then it is not referenced.
130 *
131 *  LDU     (input) INTEGER
132 *          The leading dimension of U.  LDU must be at least N and
133 *          at least 1.
134 *
135 *  VP      (input) REAL array, dimension (N*(N+1)/2)
136 *          If ITYPE=2 or 3, the columns of this array contain the
137 *          Householder vectors used to describe the unitary matrix
138 *          in the decomposition, as described in purpose.
139 *          *NOTE* If ITYPE=2 or 3, V is modified and restored.  The
140 *          subdiagonal (if UPLO='L') or the superdiagonal (if UPLO='U')
141 *          is set to one, and later reset to its original value, during
142 *          the course of the calculation.
143 *          If ITYPE=1, then it is neither referenced nor modified.
144 *
145 *  TAU     (input) COMPLEX array, dimension (N)
146 *          If ITYPE >= 2, then TAU(j) is the scalar factor of
147 *          v(j) v(j)* in the Householder transformation H(j) of
148 *          the product  U = H(1)...H(n-2)
149 *          If ITYPE < 2, then TAU is not referenced.
150 *
151 *  WORK    (workspace) COMPLEX array, dimension (N**2)
152 *          Workspace.
153 *
154 *  RWORK   (workspace) REAL array, dimension (N)
155 *          Workspace.
156 *
157 *  RESULT  (output) REAL array, dimension (2)
158 *          The values computed by the two tests described above.  The
159 *          values are currently limited to 1/ulp, to avoid overflow.
160 *          RESULT(1) is always modified.  RESULT(2) is modified only
161 *          if ITYPE=1.
162 *
163 *  =====================================================================
164 *
165 *     .. Parameters ..
166       REAL               ZERO, ONE, TEN
167       PARAMETER          ( ZERO = 0.0E+0, ONE = 1.0E+0, TEN = 10.0E+0 )
168       REAL               HALF
169       PARAMETER          ( HALF = 1.0E+0 / 2.0E+0 )
170       COMPLEX            CZERO, CONE
171       PARAMETER          ( CZERO = ( 0.0E+00.0E+0 ),
172      $                   CONE = ( 1.0E+00.0E+0 ) )
173 *     ..
174 *     .. Local Scalars ..
175       LOGICAL            LOWER
176       CHARACTER          CUPLO
177       INTEGER            IINFO, J, JP, JP1, JR, LAP
178       REAL               ANORM, ULP, UNFL, WNORM
179       COMPLEX            TEMP, VSAVE
180 *     ..
181 *     .. External Functions ..
182       LOGICAL            LSAME
183       REAL               CLANGE, CLANHP, SLAMCH
184       COMPLEX            CDOTC
185       EXTERNAL           LSAME, CLANGE, CLANHP, SLAMCH, CDOTC
186 *     ..
187 *     .. External Subroutines ..
188       EXTERNAL           CAXPY, CCOPY, CGEMM, CHPMV, CHPR, CHPR2,
189      $                   CLACPY, CLASET, CUPMTR
190 *     ..
191 *     .. Intrinsic Functions ..
192       INTRINSIC          CMPLXMAXMIN, REAL
193 *     ..
194 *     .. Executable Statements ..
195 *
196 *     Constants
197 *
198       RESULT1 ) = ZERO
199       IF( ITYPE.EQ.1 )
200      $   RESULT2 ) = ZERO
201       IF( N.LE.0 )
202      $   RETURN
203 *
204       LAP = ( N*( N+1 ) ) / 2
205 *
206       IF( LSAME( UPLO, 'U' ) ) THEN
207          LOWER = .FALSE.
208          CUPLO = 'U'
209       ELSE
210          LOWER = .TRUE.
211          CUPLO = 'L'
212       END IF
213 *
214       UNFL = SLAMCH( 'Safe minimum' )
215       ULP = SLAMCH( 'Epsilon' )*SLAMCH( 'Base' )
216 *
217 *     Some Error Checks
218 *
219       IF( ITYPE.LT.1 .OR. ITYPE.GT.3 ) THEN
220          RESULT1 ) = TEN / ULP
221          RETURN
222       END IF
223 *
224 *     Do Test 1
225 *
226 *     Norm of A:
227 *
228       IF( ITYPE.EQ.3 ) THEN
229          ANORM = ONE
230       ELSE
231          ANORM = MAX( CLANHP( '1', CUPLO, N, AP, RWORK ), UNFL )
232       END IF
233 *
234 *     Compute error matrix:
235 *
236       IF( ITYPE.EQ.1 ) THEN
237 *
238 *        ITYPE=1: error = A - U S U*
239 *
240          CALL CLASET( 'Full', N, N, CZERO, CZERO, WORK, N )
241          CALL CCOPY( LAP, AP, 1, WORK, 1 )
242 *
243          DO 10 J = 1, N
244             CALL CHPR( CUPLO, N, -D( J ), U( 1, J ), 1, WORK )
245    10    CONTINUE
246 *
247          IF( N.GT.1 .AND. KBAND.EQ.1 ) THEN
248             DO 20 J = 1, N - 1
249                CALL CHPR2( CUPLO, N, -CMPLX( E( J ) ), U( 1, J ), 1,
250      $                     U( 1, J-1 ), 1, WORK )
251    20       CONTINUE
252          END IF
253          WNORM = CLANHP( '1', CUPLO, N, WORK, RWORK )
254 *
255       ELSE IF( ITYPE.EQ.2 ) THEN
256 *
257 *        ITYPE=2: error = V S V* - A
258 *
259          CALL CLASET( 'Full', N, N, CZERO, CZERO, WORK, N )
260 *
261          IF( LOWER ) THEN
262             WORK( LAP ) = D( N )
263             DO 40 J = N - 11-1
264                JP = ( ( 2*N-J )*( J-1 ) ) / 2
265                JP1 = JP + N - J
266                IF( KBAND.EQ.1 ) THEN
267                   WORK( JP+J+1 ) = ( CONE-TAU( J ) )*E( J )
268                   DO 30 JR = J + 2, N
269                      WORK( JP+JR ) = -TAU( J )*E( J )*VP( JP+JR )
270    30             CONTINUE
271                END IF
272 *
273                IF( TAU( J ).NE.CZERO ) THEN
274                   VSAVE = VP( JP+J+1 )
275                   VP( JP+J+1 ) = CONE
276                   CALL CHPMV( 'L', N-J, CONE, WORK( JP1+J+1 ),
277      $                        VP( JP+J+1 ), 1, CZERO, WORK( LAP+1 ), 1 )
278                   TEMP = -HALF*TAU( J )*CDOTC( N-J, WORK( LAP+1 ), 1,
279      $                   VP( JP+J+1 ), 1 )
280                   CALL CAXPY( N-J, TEMP, VP( JP+J+1 ), 1, WORK( LAP+1 ),
281      $                        1 )
282                   CALL CHPR2( 'L', N-J, -TAU( J ), VP( JP+J+1 ), 1,
283      $                        WORK( LAP+1 ), 1, WORK( JP1+J+1 ) )
284 *
285                   VP( JP+J+1 ) = VSAVE
286                END IF
287                WORK( JP+J ) = D( J )
288    40       CONTINUE
289          ELSE
290             WORK( 1 ) = D( 1 )
291             DO 60 J = 1, N - 1
292                JP = ( J*( J-1 ) ) / 2
293                JP1 = JP + J
294                IF( KBAND.EQ.1 ) THEN
295                   WORK( JP1+J ) = ( CONE-TAU( J ) )*E( J )
296                   DO 50 JR = 1, J - 1
297                      WORK( JP1+JR ) = -TAU( J )*E( J )*VP( JP1+JR )
298    50             CONTINUE
299                END IF
300 *
301                IF( TAU( J ).NE.CZERO ) THEN
302                   VSAVE = VP( JP1+J )
303                   VP( JP1+J ) = CONE
304                   CALL CHPMV( 'U', J, CONE, WORK, VP( JP1+1 ), 1, CZERO,
305      $                        WORK( LAP+1 ), 1 )
306                   TEMP = -HALF*TAU( J )*CDOTC( J, WORK( LAP+1 ), 1,
307      $                   VP( JP1+1 ), 1 )
308                   CALL CAXPY( J, TEMP, VP( JP1+1 ), 1, WORK( LAP+1 ),
309      $                        1 )
310                   CALL CHPR2( 'U', J, -TAU( J ), VP( JP1+1 ), 1,
311      $                        WORK( LAP+1 ), 1, WORK )
312                   VP( JP1+J ) = VSAVE
313                END IF
314                WORK( JP1+J+1 ) = D( J+1 )
315    60       CONTINUE
316          END IF
317 *
318          DO 70 J = 1, LAP
319             WORK( J ) = WORK( J ) - AP( J )
320    70    CONTINUE
321          WNORM = CLANHP( '1', CUPLO, N, WORK, RWORK )
322 *
323       ELSE IF( ITYPE.EQ.3 ) THEN
324 *
325 *        ITYPE=3: error = U V* - I
326 *
327          IF( N.LT.2 )
328      $      RETURN
329          CALL CLACPY( ' ', N, N, U, LDU, WORK, N )
330          CALL CUPMTR( 'R', CUPLO, 'C', N, N, VP, TAU, WORK, N,
331      $                WORK( N**2+1 ), IINFO )
332          IF( IINFO.NE.0 ) THEN
333             RESULT1 ) = TEN / ULP
334             RETURN
335          END IF
336 *
337          DO 80 J = 1, N
338             WORK( ( N+1 )*( J-1 )+1 ) = WORK( ( N+1 )*( J-1 )+1 ) - CONE
339    80    CONTINUE
340 *
341          WNORM = CLANGE( '1', N, N, WORK, N, RWORK )
342       END IF
343 *
344       IF( ANORM.GT.WNORM ) THEN
345          RESULT1 ) = ( WNORM / ANORM ) / ( N*ULP )
346       ELSE
347          IF( ANORM.LT.ONE ) THEN
348             RESULT1 ) = ( MIN( WNORM, N*ANORM ) / ANORM ) / ( N*ULP )
349          ELSE
350             RESULT1 ) = MIN( WNORM / ANORM, REAL( N ) ) / ( N*ULP )
351          END IF
352       END IF
353 *
354 *     Do Test 2
355 *
356 *     Compute  UU* - I
357 *
358       IF( ITYPE.EQ.1 ) THEN
359          CALL CGEMM( 'N''C', N, N, N, CONE, U, LDU, U, LDU, CZERO,
360      $               WORK, N )
361 *
362          DO 90 J = 1, N
363             WORK( ( N+1 )*( J-1 )+1 ) = WORK( ( N+1 )*( J-1 )+1 ) - CONE
364    90    CONTINUE
365 *
366          RESULT2 ) = MIN( CLANGE( '1', N, N, WORK, N, RWORK ),
367      $                 REAL( N ) ) / ( N*ULP )
368       END IF
369 *
370       RETURN
371 *
372 *     End of CHPT21
373 *
374       END