1       SUBROUTINE ZLAGSY( 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       DOUBLE PRECISION   D( * )
 13       COMPLEX*16         A( LDA, * ), WORK( * )
 14 *     ..
 15 *
 16 *  Purpose
 17 *  =======
 18 *
 19 *  ZLAGSY generates a complex symmetric matrix A, by pre- and post-
 20 *  multiplying a real diagonal matrix D with a random unitary matrix:
 21 *  A = U*D*U**T. The semi-bandwidth may then be reduced to k by
 22 *  additional 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) DOUBLE PRECISION array, dimension (N)
 35 *          The diagonal elements of the diagonal matrix D.
 36 *
 37 *  A       (output) COMPLEX*16 array, dimension (LDA,N)
 38 *          The generated n by n symmetric 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*16 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*16         ZERO, ONE, HALF
 60       PARAMETER          ( ZERO = ( 0.0D+00.0D+0 ),
 61      $                   ONE = ( 1.0D+00.0D+0 ),
 62      $                   HALF = ( 0.5D+00.0D+0 ) )
 63 *     ..
 64 *     .. Local Scalars ..
 65       INTEGER            I, II, J, JJ
 66       DOUBLE PRECISION   WN
 67       COMPLEX*16         ALPHA, TAU, WA, WB
 68 *     ..
 69 *     .. External Subroutines ..
 70       EXTERNAL           XERBLA, ZAXPY, ZGEMV, ZGERC, ZLACGV, ZLARNV,
 71      $                   ZSCAL, ZSYMV
 72 *     ..
 73 *     .. External Functions ..
 74       DOUBLE PRECISION   DZNRM2
 75       COMPLEX*16         ZDOTC
 76       EXTERNAL           DZNRM2, ZDOTC
 77 *     ..
 78 *     .. Intrinsic Functions ..
 79       INTRINSIC          ABSDBLEMAX
 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( 'ZLAGSY'-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 symmetric matrix
110 *
111       DO 60 I = N - 11-1
112 *
113 *        generate random reflection
114 *
115          CALL ZLARNV( 3, ISEED, N-I+1, WORK )
116          WN = DZNRM2( 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 ZSCAL( N-I, ONE / WB, WORK( 2 ), 1 )
123             WORK( 1 ) = ONE
124             TAU = DBLE( 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 * conjg(u)
131 *
132          CALL ZLACGV( N-I+1, WORK, 1 )
133          CALL ZSYMV( 'Lower', N-I+1, TAU, A( I, I ), LDA, WORK, 1, ZERO,
134      $               WORK( N+1 ), 1 )
135          CALL ZLACGV( N-I+1, WORK, 1 )
136 *
137 *        compute  v := y - 1/2 * tau * ( u, y ) * u
138 *
139          ALPHA = -HALF*TAU*ZDOTC( N-I+1, WORK, 1, WORK( N+1 ), 1 )
140          CALL ZAXPY( N-I+1, ALPHA, WORK, 1, WORK( N+1 ), 1 )
141 *
142 *        apply the transformation as a rank-2 update to A(i:n,i:n)
143 *
144 *        CALL ZSYR2( 'Lower', N-I+1, -ONE, WORK, 1, WORK( N+1 ), 1,
145 *        $               A( I, I ), LDA )
146 *
147          DO 50 JJ = I, N
148             DO 40 II = JJ, N
149                A( II, JJ ) = A( II, JJ ) -
150      $                       WORK( II-I+1 )*WORK( N+JJ-I+1 ) -
151      $                       WORK( N+II-I+1 )*WORK( JJ-I+1 )
152    40       CONTINUE
153    50    CONTINUE
154    60 CONTINUE
155 *
156 *     Reduce number of subdiagonals to K
157 *
158       DO 100 I = 1, N - 1 - K
159 *
160 *        generate reflection to annihilate A(k+i+1:n,i)
161 *
162          WN = DZNRM2( N-K-I+1, A( K+I, I ), 1 )
163          WA = ( WN / ABS( A( K+I, I ) ) )*A( K+I, I )
164          IF( WN.EQ.ZERO ) THEN
165             TAU = ZERO
166          ELSE
167             WB = A( K+I, I ) + WA
168             CALL ZSCAL( N-K-I, ONE / WB, A( K+I+1, I ), 1 )
169             A( K+I, I ) = ONE
170             TAU = DBLE( WB / WA )
171          END IF
172 *
173 *        apply reflection to A(k+i:n,i+1:k+i-1) from the left
174 *
175          CALL ZGEMV( 'Conjugate transpose', N-K-I+1, K-1, ONE,
176      $               A( K+I, I+1 ), LDA, A( K+I, I ), 1, ZERO, WORK, 1 )
177          CALL ZGERC( N-K-I+1, K-1-TAU, A( K+I, I ), 1, WORK, 1,
178      $               A( K+I, I+1 ), LDA )
179 *
180 *        apply reflection to A(k+i:n,k+i:n) from the left and the right
181 *
182 *        compute  y := tau * A * conjg(u)
183 *
184          CALL ZLACGV( N-K-I+1, A( K+I, I ), 1 )
185          CALL ZSYMV( 'Lower', N-K-I+1, TAU, A( K+I, K+I ), LDA,
186      $               A( K+I, I ), 1, ZERO, WORK, 1 )
187          CALL ZLACGV( N-K-I+1, A( K+I, I ), 1 )
188 *
189 *        compute  v := y - 1/2 * tau * ( u, y ) * u
190 *
191          ALPHA = -HALF*TAU*ZDOTC( N-K-I+1, A( K+I, I ), 1, WORK, 1 )
192          CALL ZAXPY( N-K-I+1, ALPHA, A( K+I, I ), 1, WORK, 1 )
193 *
194 *        apply symmetric rank-2 update to A(k+i:n,k+i:n)
195 *
196 *        CALL ZSYR2( 'Lower', N-K-I+1, -ONE, A( K+I, I ), 1, WORK, 1,
197 *        $               A( K+I, K+I ), LDA )
198 *
199          DO 80 JJ = K + I, N
200             DO 70 II = JJ, N
201                A( II, JJ ) = A( II, JJ ) - A( II, I )*WORK( JJ-K-I+1 ) -
202      $                       WORK( II-K-I+1 )*A( JJ, I )
203    70       CONTINUE
204    80    CONTINUE
205 *
206          A( K+I, I ) = -WA
207          DO 90 J = K + I + 1, N
208             A( J, I ) = ZERO
209    90    CONTINUE
210   100 CONTINUE
211 *
212 *     Store full symmetric matrix
213 *
214       DO 120 J = 1, N
215          DO 110 I = J + 1, N
216             A( J, I ) = A( I, J )
217   110    CONTINUE
218   120 CONTINUE
219       RETURN
220 *
221 *     End of ZLAGSY
222 *
223       END