1       SUBROUTINE SLAGGE( M, N, KL, KU, 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, KL, KU, LDA, M, N
  9 *     ..
 10 *     .. Array Arguments ..
 11       INTEGER            ISEED( 4 )
 12       REAL               A( LDA, * ), D( * ), WORK( * )
 13 *     ..
 14 *
 15 *  Purpose
 16 *  =======
 17 *
 18 *  SLAGGE generates a real general m by n matrix A, by pre- and post-
 19 *  multiplying a real diagonal matrix D with random orthogonal matrices:
 20 *  A = U*D*V. The lower and upper bandwidths may then be reduced to
 21 *  kl and ku by additional orthogonal transformations.
 22 *
 23 *  Arguments
 24 *  =========
 25 *
 26 *  M       (input) INTEGER
 27 *          The number of rows of the matrix A.  M >= 0.
 28 *
 29 *  N       (input) INTEGER
 30 *          The number of columns of the matrix A.  N >= 0.
 31 *
 32 *  KL      (input) INTEGER
 33 *          The number of nonzero subdiagonals within the band of A.
 34 *          0 <= KL <= M-1.
 35 *
 36 *  KU      (input) INTEGER
 37 *          The number of nonzero superdiagonals within the band of A.
 38 *          0 <= KU <= N-1.
 39 *
 40 *  D       (input) REAL array, dimension (min(M,N))
 41 *          The diagonal elements of the diagonal matrix D.
 42 *
 43 *  A       (output) REAL array, dimension (LDA,N)
 44 *          The generated m by n matrix A.
 45 *
 46 *  LDA     (input) INTEGER
 47 *          The leading dimension of the array A.  LDA >= M.
 48 *
 49 *  ISEED   (input/output) INTEGER array, dimension (4)
 50 *          On entry, the seed of the random number generator; the array
 51 *          elements must be between 0 and 4095, and ISEED(4) must be
 52 *          odd.
 53 *          On exit, the seed is updated.
 54 *
 55 *  WORK    (workspace) REAL array, dimension (M+N)
 56 *
 57 *  INFO    (output) INTEGER
 58 *          = 0: successful exit
 59 *          < 0: if INFO = -i, the i-th argument had an illegal value
 60 *
 61 *  =====================================================================
 62 *
 63 *     .. Parameters ..
 64       REAL               ZERO, ONE
 65       PARAMETER          ( ZERO = 0.0E+0, ONE = 1.0E+0 )
 66 *     ..
 67 *     .. Local Scalars ..
 68       INTEGER            I, J
 69       REAL               TAU, WA, WB, WN
 70 *     ..
 71 *     .. External Subroutines ..
 72       EXTERNAL           SGEMV, SGER, SLARNV, SSCAL, XERBLA
 73 *     ..
 74 *     .. Intrinsic Functions ..
 75       INTRINSIC          MAXMINSIGN
 76 *     ..
 77 *     .. External Functions ..
 78       REAL               SNRM2
 79       EXTERNAL           SNRM2
 80 *     ..
 81 *     .. Executable Statements ..
 82 *
 83 *     Test the input arguments
 84 *
 85       INFO = 0
 86       IF( M.LT.0 ) THEN
 87          INFO = -1
 88       ELSE IF( N.LT.0 ) THEN
 89          INFO = -2
 90       ELSE IF( KL.LT.0 .OR. KL.GT.M-1 ) THEN
 91          INFO = -3
 92       ELSE IF( KU.LT.0 .OR. KU.GT.N-1 ) THEN
 93          INFO = -4
 94       ELSE IF( LDA.LT.MAX1, M ) ) THEN
 95          INFO = -7
 96       END IF
 97       IF( INFO.LT.0 ) THEN
 98          CALL XERBLA( 'SLAGGE'-INFO )
 99          RETURN
100       END IF
101 *
102 *     initialize A to diagonal matrix
103 *
104       DO 20 J = 1, N
105          DO 10 I = 1, M
106             A( I, J ) = ZERO
107    10    CONTINUE
108    20 CONTINUE
109       DO 30 I = 1MIN( M, N )
110          A( I, I ) = D( I )
111    30 CONTINUE
112 *
113 *     pre- and post-multiply A by random orthogonal matrices
114 *
115       DO 40 I = MIN( M, N ), 1-1
116          IF( I.LT.M ) THEN
117 *
118 *           generate random reflection
119 *
120             CALL SLARNV( 3, ISEED, M-I+1, WORK )
121             WN = SNRM2( M-I+1, WORK, 1 )
122             WA = SIGN( WN, WORK( 1 ) )
123             IF( WN.EQ.ZERO ) THEN
124                TAU = ZERO
125             ELSE
126                WB = WORK( 1 ) + WA
127                CALL SSCAL( M-I, ONE / WB, WORK( 2 ), 1 )
128                WORK( 1 ) = ONE
129                TAU = WB / WA
130             END IF
131 *
132 *           multiply A(i:m,i:n) by random reflection from the left
133 *
134             CALL SGEMV( 'Transpose', M-I+1, N-I+1, ONE, A( I, I ), LDA,
135      $                  WORK, 1, ZERO, WORK( M+1 ), 1 )
136             CALL SGER( M-I+1, N-I+1-TAU, WORK, 1, WORK( M+1 ), 1,
137      $                 A( I, I ), LDA )
138          END IF
139          IF( I.LT.N ) THEN
140 *
141 *           generate random reflection
142 *
143             CALL SLARNV( 3, ISEED, N-I+1, WORK )
144             WN = SNRM2( N-I+1, WORK, 1 )
145             WA = SIGN( WN, WORK( 1 ) )
146             IF( WN.EQ.ZERO ) THEN
147                TAU = ZERO
148             ELSE
149                WB = WORK( 1 ) + WA
150                CALL SSCAL( N-I, ONE / WB, WORK( 2 ), 1 )
151                WORK( 1 ) = ONE
152                TAU = WB / WA
153             END IF
154 *
155 *           multiply A(i:m,i:n) by random reflection from the right
156 *
157             CALL SGEMV( 'No transpose', M-I+1, N-I+1, ONE, A( I, I ),
158      $                  LDA, WORK, 1, ZERO, WORK( N+1 ), 1 )
159             CALL SGER( M-I+1, N-I+1-TAU, WORK( N+1 ), 1, WORK, 1,
160      $                 A( I, I ), LDA )
161          END IF
162    40 CONTINUE
163 *
164 *     Reduce number of subdiagonals to KL and number of superdiagonals
165 *     to KU
166 *
167       DO 70 I = 1MAX( M-1-KL, N-1-KU )
168          IF( KL.LE.KU ) THEN
169 *
170 *           annihilate subdiagonal elements first (necessary if KL = 0)
171 *
172             IF( I.LE.MIN( M-1-KL, N ) ) THEN
173 *
174 *              generate reflection to annihilate A(kl+i+1:m,i)
175 *
176                WN = SNRM2( M-KL-I+1, A( KL+I, I ), 1 )
177                WA = SIGN( WN, A( KL+I, I ) )
178                IF( WN.EQ.ZERO ) THEN
179                   TAU = ZERO
180                ELSE
181                   WB = A( KL+I, I ) + WA
182                   CALL SSCAL( M-KL-I, ONE / WB, A( KL+I+1, I ), 1 )
183                   A( KL+I, I ) = ONE
184                   TAU = WB / WA
185                END IF
186 *
187 *              apply reflection to A(kl+i:m,i+1:n) from the left
188 *
189                CALL SGEMV( 'Transpose', M-KL-I+1, N-I, ONE,
190      $                     A( KL+I, I+1 ), LDA, A( KL+I, I ), 1, ZERO,
191      $                     WORK, 1 )
192                CALL SGER( M-KL-I+1, N-I, -TAU, A( KL+I, I ), 1, WORK, 1,
193      $                    A( KL+I, I+1 ), LDA )
194                A( KL+I, I ) = -WA
195             END IF
196 *
197             IF( I.LE.MIN( N-1-KU, M ) ) THEN
198 *
199 *              generate reflection to annihilate A(i,ku+i+1:n)
200 *
201                WN = SNRM2( N-KU-I+1, A( I, KU+I ), LDA )
202                WA = SIGN( WN, A( I, KU+I ) )
203                IF( WN.EQ.ZERO ) THEN
204                   TAU = ZERO
205                ELSE
206                   WB = A( I, KU+I ) + WA
207                   CALL SSCAL( N-KU-I, ONE / WB, A( I, KU+I+1 ), LDA )
208                   A( I, KU+I ) = ONE
209                   TAU = WB / WA
210                END IF
211 *
212 *              apply reflection to A(i+1:m,ku+i:n) from the right
213 *
214                CALL SGEMV( 'No transpose', M-I, N-KU-I+1, ONE,
215      $                     A( I+1, KU+I ), LDA, A( I, KU+I ), LDA, ZERO,
216      $                     WORK, 1 )
217                CALL SGER( M-I, N-KU-I+1-TAU, WORK, 1, A( I, KU+I ),
218      $                    LDA, A( I+1, KU+I ), LDA )
219                A( I, KU+I ) = -WA
220             END IF
221          ELSE
222 *
223 *           annihilate superdiagonal elements first (necessary if
224 *           KU = 0)
225 *
226             IF( I.LE.MIN( N-1-KU, M ) ) THEN
227 *
228 *              generate reflection to annihilate A(i,ku+i+1:n)
229 *
230                WN = SNRM2( N-KU-I+1, A( I, KU+I ), LDA )
231                WA = SIGN( WN, A( I, KU+I ) )
232                IF( WN.EQ.ZERO ) THEN
233                   TAU = ZERO
234                ELSE
235                   WB = A( I, KU+I ) + WA
236                   CALL SSCAL( N-KU-I, ONE / WB, A( I, KU+I+1 ), LDA )
237                   A( I, KU+I ) = ONE
238                   TAU = WB / WA
239                END IF
240 *
241 *              apply reflection to A(i+1:m,ku+i:n) from the right
242 *
243                CALL SGEMV( 'No transpose', M-I, N-KU-I+1, ONE,
244      $                     A( I+1, KU+I ), LDA, A( I, KU+I ), LDA, ZERO,
245      $                     WORK, 1 )
246                CALL SGER( M-I, N-KU-I+1-TAU, WORK, 1, A( I, KU+I ),
247      $                    LDA, A( I+1, KU+I ), LDA )
248                A( I, KU+I ) = -WA
249             END IF
250 *
251             IF( I.LE.MIN( M-1-KL, N ) ) THEN
252 *
253 *              generate reflection to annihilate A(kl+i+1:m,i)
254 *
255                WN = SNRM2( M-KL-I+1, A( KL+I, I ), 1 )
256                WA = SIGN( WN, A( KL+I, I ) )
257                IF( WN.EQ.ZERO ) THEN
258                   TAU = ZERO
259                ELSE
260                   WB = A( KL+I, I ) + WA
261                   CALL SSCAL( M-KL-I, ONE / WB, A( KL+I+1, I ), 1 )
262                   A( KL+I, I ) = ONE
263                   TAU = WB / WA
264                END IF
265 *
266 *              apply reflection to A(kl+i:m,i+1:n) from the left
267 *
268                CALL SGEMV( 'Transpose', M-KL-I+1, N-I, ONE,
269      $                     A( KL+I, I+1 ), LDA, A( KL+I, I ), 1, ZERO,
270      $                     WORK, 1 )
271                CALL SGER( M-KL-I+1, N-I, -TAU, A( KL+I, I ), 1, WORK, 1,
272      $                    A( KL+I, I+1 ), LDA )
273                A( KL+I, I ) = -WA
274             END IF
275          END IF
276 *
277          DO 50 J = KL + I + 1, M
278             A( J, I ) = ZERO
279    50    CONTINUE
280 *
281          DO 60 J = KU + I + 1, N
282             A( I, J ) = ZERO
283    60    CONTINUE
284    70 CONTINUE
285       RETURN
286 *
287 *     End of SLAGGE
288 *
289       END