1       SUBROUTINE ZLATM4( ITYPE, N, NZ1, NZ2, RSIGN, AMAGN, RCOND,
  2      $                   TRIANG, IDIST, ISEED, A, LDA )
  3 *
  4 *  -- LAPACK auxiliary test routine (version 3.1) --
  5 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
  6 *     November 2006
  7 *
  8 *     .. Scalar Arguments ..
  9       LOGICAL            RSIGN
 10       INTEGER            IDIST, ITYPE, LDA, N, NZ1, NZ2
 11       DOUBLE PRECISION   AMAGN, RCOND, TRIANG
 12 *     ..
 13 *     .. Array Arguments ..
 14       INTEGER            ISEED( 4 )
 15       COMPLEX*16         A( LDA, * )
 16 *     ..
 17 *
 18 *  Purpose
 19 *  =======
 20 *
 21 *  ZLATM4 generates basic square matrices, which may later be
 22 *  multiplied by others in order to produce test matrices.  It is
 23 *  intended mainly to be used to test the generalized eigenvalue
 24 *  routines.
 25 *
 26 *  It first generates the diagonal and (possibly) subdiagonal,
 27 *  according to the value of ITYPE, NZ1, NZ2, RSIGN, AMAGN, and RCOND.
 28 *  It then fills in the upper triangle with random numbers, if TRIANG is
 29 *  non-zero.
 30 *
 31 *  Arguments
 32 *  =========
 33 *
 34 *  ITYPE   (input) INTEGER
 35 *          The "type" of matrix on the diagonal and sub-diagonal.
 36 *          If ITYPE < 0, then type abs(ITYPE) is generated and then
 37 *             swapped end for end (A(I,J) := A'(N-J,N-I).)  See also
 38 *             the description of AMAGN and RSIGN.
 39 *
 40 *          Special types:
 41 *          = 0:  the zero matrix.
 42 *          = 1:  the identity.
 43 *          = 2:  a transposed Jordan block.
 44 *          = 3:  If N is odd, then a k+1 x k+1 transposed Jordan block
 45 *                followed by a k x k identity block, where k=(N-1)/2.
 46 *                If N is even, then k=(N-2)/2, and a zero diagonal entry
 47 *                is tacked onto the end.
 48 *
 49 *          Diagonal types.  The diagonal consists of NZ1 zeros, then
 50 *             k=N-NZ1-NZ2 nonzeros.  The subdiagonal is zero.  ITYPE
 51 *             specifies the nonzero diagonal entries as follows:
 52 *          = 4:  1, ..., k
 53 *          = 5:  1, RCOND, ..., RCOND
 54 *          = 6:  1, ..., 1, RCOND
 55 *          = 7:  1, a, a^2, ..., a^(k-1)=RCOND
 56 *          = 8:  1, 1-d, 1-2*d, ..., 1-(k-1)*d=RCOND
 57 *          = 9:  random numbers chosen from (RCOND,1)
 58 *          = 10: random numbers with distribution IDIST (see ZLARND.)
 59 *
 60 *  N       (input) INTEGER
 61 *          The order of the matrix.
 62 *
 63 *  NZ1     (input) INTEGER
 64 *          If abs(ITYPE) > 3, then the first NZ1 diagonal entries will
 65 *          be zero.
 66 *
 67 *  NZ2     (input) INTEGER
 68 *          If abs(ITYPE) > 3, then the last NZ2 diagonal entries will
 69 *          be zero.
 70 *
 71 *  RSIGN   (input) LOGICAL
 72 *          = .TRUE.:  The diagonal and subdiagonal entries will be
 73 *                     multiplied by random numbers of magnitude 1.
 74 *          = .FALSE.: The diagonal and subdiagonal entries will be
 75 *                     left as they are (usually non-negative real.)
 76 *
 77 *  AMAGN   (input) DOUBLE PRECISION
 78 *          The diagonal and subdiagonal entries will be multiplied by
 79 *          AMAGN.
 80 *
 81 *  RCOND   (input) DOUBLE PRECISION
 82 *          If abs(ITYPE) > 4, then the smallest diagonal entry will be
 83 *          RCOND.  RCOND must be between 0 and 1.
 84 *
 85 *  TRIANG  (input) DOUBLE PRECISION
 86 *          The entries above the diagonal will be random numbers with
 87 *          magnitude bounded by TRIANG (i.e., random numbers multiplied
 88 *          by TRIANG.)
 89 *
 90 *  IDIST   (input) INTEGER
 91 *          On entry, DIST specifies the type of distribution to be used
 92 *          to generate a random matrix .
 93 *          = 1: real and imaginary parts each UNIFORM( 0, 1 )
 94 *          = 2: real and imaginary parts each UNIFORM( -1, 1 )
 95 *          = 3: real and imaginary parts each NORMAL( 0, 1 )
 96 *          = 4: complex number uniform in DISK( 0, 1 )
 97 *
 98 *  ISEED   (input/output) INTEGER array, dimension (4)
 99 *          On entry ISEED specifies the seed of the random number
100 *          generator.  The values of ISEED are changed on exit, and can
101 *          be used in the next call to ZLATM4 to continue the same
102 *          random number sequence.
103 *          Note: ISEED(4) should be odd, for the random number generator
104 *          used at present.
105 *
106 *  A       (output) COMPLEX*16 array, dimension (LDA, N)
107 *          Array to be computed.
108 *
109 *  LDA     (input) INTEGER
110 *          Leading dimension of A.  Must be at least 1 and at least N.
111 *
112 *  =====================================================================
113 *
114 *     .. Parameters ..
115       DOUBLE PRECISION   ZERO, ONE
116       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
117       COMPLEX*16         CZERO, CONE
118       PARAMETER          ( CZERO = ( 0.0D+00.0D+0 ),
119      $                   CONE = ( 1.0D+00.0D+0 ) )
120 *     ..
121 *     .. Local Scalars ..
122       INTEGER            I, ISDB, ISDE, JC, JD, JR, K, KBEG, KEND, KLEN
123       DOUBLE PRECISION   ALPHA
124       COMPLEX*16         CTEMP
125 *     ..
126 *     .. External Functions ..
127       DOUBLE PRECISION   DLARAN
128       COMPLEX*16         ZLARND
129       EXTERNAL           DLARAN, ZLARND
130 *     ..
131 *     .. External Subroutines ..
132       EXTERNAL           ZLASET
133 *     ..
134 *     .. Intrinsic Functions ..
135       INTRINSIC          ABSDBLEDCMPLXEXPLOGMAXMINMOD
136 *     ..
137 *     .. Executable Statements ..
138 *
139       IF( N.LE.0 )
140      $   RETURN
141       CALL ZLASET( 'Full', N, N, CZERO, CZERO, A, LDA )
142 *
143 *     Insure a correct ISEED
144 *
145       IFMOD( ISEED( 4 ), 2 ).NE.1 )
146      $   ISEED( 4 ) = ISEED( 4 ) + 1
147 *
148 *     Compute diagonal and subdiagonal according to ITYPE, NZ1, NZ2,
149 *     and RCOND
150 *
151       IF( ITYPE.NE.0 ) THEN
152          IFABS( ITYPE ).GE.4 ) THEN
153             KBEG = MAX1MIN( N, NZ1+1 ) )
154             KEND = MAX( KBEG, MIN( N, N-NZ2 ) )
155             KLEN = KEND + 1 - KBEG
156          ELSE
157             KBEG = 1
158             KEND = N
159             KLEN = N
160          END IF
161          ISDB = 1
162          ISDE = 0
163          GO TO ( 10305080100120140160,
164      $           180200 )ABS( ITYPE )
165 *
166 *        abs(ITYPE) = 1: Identity
167 *
168    10    CONTINUE
169          DO 20 JD = 1, N
170             A( JD, JD ) = CONE
171    20    CONTINUE
172          GO TO 220
173 *
174 *        abs(ITYPE) = 2: Transposed Jordan block
175 *
176    30    CONTINUE
177          DO 40 JD = 1, N - 1
178             A( JD+1, JD ) = CONE
179    40    CONTINUE
180          ISDB = 1
181          ISDE = N - 1
182          GO TO 220
183 *
184 *        abs(ITYPE) = 3: Transposed Jordan block, followed by the
185 *                        identity.
186 *
187    50    CONTINUE
188          K = ( N-1 ) / 2
189          DO 60 JD = 1, K
190             A( JD+1, JD ) = CONE
191    60    CONTINUE
192          ISDB = 1
193          ISDE = K
194          DO 70 JD = K + 22*+ 1
195             A( JD, JD ) = CONE
196    70    CONTINUE
197          GO TO 220
198 *
199 *        abs(ITYPE) = 4: 1,...,k
200 *
201    80    CONTINUE
202          DO 90 JD = KBEG, KEND
203             A( JD, JD ) = DCMPLX( JD-NZ1 )
204    90    CONTINUE
205          GO TO 220
206 *
207 *        abs(ITYPE) = 5: One large D value:
208 *
209   100    CONTINUE
210          DO 110 JD = KBEG + 1, KEND
211             A( JD, JD ) = DCMPLX( RCOND )
212   110    CONTINUE
213          A( KBEG, KBEG ) = CONE
214          GO TO 220
215 *
216 *        abs(ITYPE) = 6: One small D value:
217 *
218   120    CONTINUE
219          DO 130 JD = KBEG, KEND - 1
220             A( JD, JD ) = CONE
221   130    CONTINUE
222          A( KEND, KEND ) = DCMPLX( RCOND )
223          GO TO 220
224 *
225 *        abs(ITYPE) = 7: Exponentially distributed D values:
226 *
227   140    CONTINUE
228          A( KBEG, KBEG ) = CONE
229          IF( KLEN.GT.1 ) THEN
230             ALPHA = RCOND**( ONE / DBLE( KLEN-1 ) )
231             DO 150 I = 2, KLEN
232                A( NZ1+I, NZ1+I ) = DCMPLX( ALPHA**DBLE( I-1 ) )
233   150       CONTINUE
234          END IF
235          GO TO 220
236 *
237 *        abs(ITYPE) = 8: Arithmetically distributed D values:
238 *
239   160    CONTINUE
240          A( KBEG, KBEG ) = CONE
241          IF( KLEN.GT.1 ) THEN
242             ALPHA = ( ONE-RCOND ) / DBLE( KLEN-1 )
243             DO 170 I = 2, KLEN
244                A( NZ1+I, NZ1+I ) = DCMPLXDBLE( KLEN-I )*ALPHA+RCOND )
245   170       CONTINUE
246          END IF
247          GO TO 220
248 *
249 *        abs(ITYPE) = 9: Randomly distributed D values on ( RCOND, 1):
250 *
251   180    CONTINUE
252          ALPHA = LOG( RCOND )
253          DO 190 JD = KBEG, KEND
254             A( JD, JD ) = EXP( ALPHA*DLARAN( ISEED ) )
255   190    CONTINUE
256          GO TO 220
257 *
258 *        abs(ITYPE) = 10: Randomly distributed D values from DIST
259 *
260   200    CONTINUE
261          DO 210 JD = KBEG, KEND
262             A( JD, JD ) = ZLARND( IDIST, ISEED )
263   210    CONTINUE
264 *
265   220    CONTINUE
266 *
267 *        Scale by AMAGN
268 *
269          DO 230 JD = KBEG, KEND
270             A( JD, JD ) = AMAGN*DBLE( A( JD, JD ) )
271   230    CONTINUE
272          DO 240 JD = ISDB, ISDE
273             A( JD+1, JD ) = AMAGN*DBLE( A( JD+1, JD ) )
274   240    CONTINUE
275 *
276 *        If RSIGN = .TRUE., assign random signs to diagonal and
277 *        subdiagonal
278 *
279          IF( RSIGN ) THEN
280             DO 250 JD = KBEG, KEND
281                IFDBLE( A( JD, JD ) ).NE.ZERO ) THEN
282                   CTEMP = ZLARND( 3, ISEED )
283                   CTEMP = CTEMP / ABS( CTEMP )
284                   A( JD, JD ) = CTEMP*DBLE( A( JD, JD ) )
285                END IF
286   250       CONTINUE
287             DO 260 JD = ISDB, ISDE
288                IFDBLE( A( JD+1, JD ) ).NE.ZERO ) THEN
289                   CTEMP = ZLARND( 3, ISEED )
290                   CTEMP = CTEMP / ABS( CTEMP )
291                   A( JD+1, JD ) = CTEMP*DBLE( A( JD+1, JD ) )
292                END IF
293   260       CONTINUE
294          END IF
295 *
296 *        Reverse if ITYPE < 0
297 *
298          IF( ITYPE.LT.0 ) THEN
299             DO 270 JD = KBEG, ( KBEG+KEND-1 ) / 2
300                CTEMP = A( JD, JD )
301                A( JD, JD ) = A( KBEG+KEND-JD, KBEG+KEND-JD )
302                A( KBEG+KEND-JD, KBEG+KEND-JD ) = CTEMP
303   270       CONTINUE
304             DO 280 JD = 1, ( N-1 ) / 2
305                CTEMP = A( JD+1, JD )
306                A( JD+1, JD ) = A( N+1-JD, N-JD )
307                A( N+1-JD, N-JD ) = CTEMP
308   280       CONTINUE
309          END IF
310 *
311       END IF
312 *
313 *     Fill in upper triangle
314 *
315       IF( TRIANG.NE.ZERO ) THEN
316          DO 300 JC = 2, N
317             DO 290 JR = 1, JC - 1
318                A( JR, JC ) = TRIANG*ZLARND( IDIST, ISEED )
319   290       CONTINUE
320   300    CONTINUE
321       END IF
322 *
323       RETURN
324 *
325 *     End of ZLATM4
326 *
327       END