1       SUBROUTINE CLAGHE( N, K, D, A, LDA, ISEED, WORK, INFO )
  2 *
  3 *  -- LAPACK auxiliary test routine (version 3.1) --
  4 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
  5 *     November 2006
  6 *
  7 *     .. Scalar Arguments ..
  8       INTEGER            INFO, K, LDA, N
  9 *     ..
 10 *     .. Array Arguments ..
 11       INTEGER            ISEED( 4 )
 12       REAL               D( * )
 13       COMPLEX            A( LDA, * ), WORK( * )
 14 *     ..
 15 *
 16 *  Purpose
 17 *  =======
 18 *
 19 *  CLAGHE generates a complex hermitian matrix A, by pre- and post-
 20 *  multiplying a real diagonal matrix D with a random unitary matrix:
 21 *  A = U*D*U'. The semi-bandwidth may then be reduced to k by additional
 22 *  unitary transformations.
 23 *
 24 *  Arguments
 25 *  =========
 26 *
 27 *  N       (input) INTEGER
 28 *          The order of the matrix A.  N >= 0.
 29 *
 30 *  K       (input) INTEGER
 31 *          The number of nonzero subdiagonals within the band of A.
 32 *          0 <= K <= N-1.
 33 *
 34 *  D       (input) REAL array, dimension (N)
 35 *          The diagonal elements of the diagonal matrix D.
 36 *
 37 *  A       (output) COMPLEX array, dimension (LDA,N)
 38 *          The generated n by n hermitian matrix A (the full matrix is
 39 *          stored).
 40 *
 41 *  LDA     (input) INTEGER
 42 *          The leading dimension of the array A.  LDA >= N.
 43 *
 44 *  ISEED   (input/output) INTEGER array, dimension (4)
 45 *          On entry, the seed of the random number generator; the array
 46 *          elements must be between 0 and 4095, and ISEED(4) must be
 47 *          odd.
 48 *          On exit, the seed is updated.
 49 *
 50 *  WORK    (workspace) COMPLEX array, dimension (2*N)
 51 *
 52 *  INFO    (output) INTEGER
 53 *          = 0: successful exit
 54 *          < 0: if INFO = -i, the i-th argument had an illegal value
 55 *
 56 *  =====================================================================
 57 *
 58 *     .. Parameters ..
 59       COMPLEX            ZERO, ONE, HALF
 60       PARAMETER          ( ZERO = ( 0.0E+00.0E+0 ),
 61      $                   ONE = ( 1.0E+00.0E+0 ),
 62      $                   HALF = ( 0.5E+00.0E+0 ) )
 63 *     ..
 64 *     .. Local Scalars ..
 65       INTEGER            I, J
 66       REAL               WN
 67       COMPLEX            ALPHA, TAU, WA, WB
 68 *     ..
 69 *     .. External Subroutines ..
 70       EXTERNAL           CAXPY, CGEMV, CGERC, CHEMV, CHER2, CLARNV,
 71      $                   CSCAL, XERBLA
 72 *     ..
 73 *     .. External Functions ..
 74       REAL               SCNRM2
 75       COMPLEX            CDOTC
 76       EXTERNAL           SCNRM2, CDOTC
 77 *     ..
 78 *     .. Intrinsic Functions ..
 79       INTRINSIC          ABSCONJGMAX, REAL
 80 *     ..
 81 *     .. Executable Statements ..
 82 *
 83 *     Test the input arguments
 84 *
 85       INFO = 0
 86       IF( N.LT.0 ) THEN
 87          INFO = -1
 88       ELSE IF( K.LT.0 .OR. K.GT.N-1 ) THEN
 89          INFO = -2
 90       ELSE IF( LDA.LT.MAX1, N ) ) THEN
 91          INFO = -5
 92       END IF
 93       IF( INFO.LT.0 ) THEN
 94          CALL XERBLA( 'CLAGHE'-INFO )
 95          RETURN
 96       END IF
 97 *
 98 *     initialize lower triangle of A to diagonal matrix
 99 *
100       DO 20 J = 1, N
101          DO 10 I = J + 1, N
102             A( I, J ) = ZERO
103    10    CONTINUE
104    20 CONTINUE
105       DO 30 I = 1, N
106          A( I, I ) = D( I )
107    30 CONTINUE
108 *
109 *     Generate lower triangle of hermitian matrix
110 *
111       DO 40 I = N - 11-1
112 *
113 *        generate random reflection
114 *
115          CALL CLARNV( 3, ISEED, N-I+1, WORK )
116          WN = SCNRM2( N-I+1, WORK, 1 )
117          WA = ( WN / ABS( WORK( 1 ) ) )*WORK( 1 )
118          IF( WN.EQ.ZERO ) THEN
119             TAU = ZERO
120          ELSE
121             WB = WORK( 1 ) + WA
122             CALL CSCAL( N-I, ONE / WB, WORK( 2 ), 1 )
123             WORK( 1 ) = ONE
124             TAU = REAL( WB / WA )
125          END IF
126 *
127 *        apply random reflection to A(i:n,i:n) from the left
128 *        and the right
129 *
130 *        compute  y := tau * A * u
131 *
132          CALL CHEMV( 'Lower', N-I+1, TAU, A( I, I ), LDA, WORK, 1, ZERO,
133      $               WORK( N+1 ), 1 )
134 *
135 *        compute  v := y - 1/2 * tau * ( y, u ) * u
136 *
137          ALPHA = -HALF*TAU*CDOTC( N-I+1, WORK( N+1 ), 1, WORK, 1 )
138          CALL CAXPY( N-I+1, ALPHA, WORK, 1, WORK( N+1 ), 1 )
139 *
140 *        apply the transformation as a rank-2 update to A(i:n,i:n)
141 *
142          CALL CHER2( 'Lower', N-I+1-ONE, WORK, 1, WORK( N+1 ), 1,
143      $               A( I, I ), LDA )
144    40 CONTINUE
145 *
146 *     Reduce number of subdiagonals to K
147 *
148       DO 60 I = 1, N - 1 - K
149 *
150 *        generate reflection to annihilate A(k+i+1:n,i)
151 *
152          WN = SCNRM2( N-K-I+1, A( K+I, I ), 1 )
153          WA = ( WN / ABS( A( K+I, I ) ) )*A( K+I, I )
154          IF( WN.EQ.ZERO ) THEN
155             TAU = ZERO
156          ELSE
157             WB = A( K+I, I ) + WA
158             CALL CSCAL( N-K-I, ONE / WB, A( K+I+1, I ), 1 )
159             A( K+I, I ) = ONE
160             TAU = REAL( WB / WA )
161          END IF
162 *
163 *        apply reflection to A(k+i:n,i+1:k+i-1) from the left
164 *
165          CALL CGEMV( 'Conjugate transpose', N-K-I+1, K-1, ONE,
166      $               A( K+I, I+1 ), LDA, A( K+I, I ), 1, ZERO, WORK, 1 )
167          CALL CGERC( N-K-I+1, K-1-TAU, A( K+I, I ), 1, WORK, 1,
168      $               A( K+I, I+1 ), LDA )
169 *
170 *        apply reflection to A(k+i:n,k+i:n) from the left and the right
171 *
172 *        compute  y := tau * A * u
173 *
174          CALL CHEMV( 'Lower', N-K-I+1, TAU, A( K+I, K+I ), LDA,
175      $               A( K+I, I ), 1, ZERO, WORK, 1 )
176 *
177 *        compute  v := y - 1/2 * tau * ( y, u ) * u
178 *
179          ALPHA = -HALF*TAU*CDOTC( N-K-I+1, WORK, 1, A( K+I, I ), 1 )
180          CALL CAXPY( N-K-I+1, ALPHA, A( K+I, I ), 1, WORK, 1 )
181 *
182 *        apply hermitian rank-2 update to A(k+i:n,k+i:n)
183 *
184          CALL CHER2( 'Lower', N-K-I+1-ONE, A( K+I, I ), 1, WORK, 1,
185      $               A( K+I, K+I ), LDA )
186 *
187          A( K+I, I ) = -WA
188          DO 50 J = K + I + 1, N
189             A( J, I ) = ZERO
190    50    CONTINUE
191    60 CONTINUE
192 *
193 *     Store full hermitian matrix
194 *
195       DO 80 J = 1, N
196          DO 70 I = J + 1, N
197             A( J, I ) = CONJG( A( I, J ) )
198    70    CONTINUE
199    80 CONTINUE
200       RETURN
201 *
202 *     End of CLAGHE
203 *
204       END