LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
slatms.f
Go to the documentation of this file.
1*> \brief \b SLATMS
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8* Definition:
9* ===========
10*
11* SUBROUTINE SLATMS( M, N, DIST, ISEED, SYM, D, MODE, COND, DMAX,
12* KL, KU, PACK, A, LDA, WORK, INFO )
13*
14* .. Scalar Arguments ..
15* CHARACTER DIST, PACK, SYM
16* INTEGER INFO, KL, KU, LDA, M, MODE, N
17* REAL COND, DMAX
18* ..
19* .. Array Arguments ..
20* INTEGER ISEED( 4 )
21* REAL A( LDA, * ), D( * ), WORK( * )
22* ..
23*
24*
25*> \par Purpose:
26* =============
27*>
28*> \verbatim
29*>
30*> SLATMS generates random matrices with specified singular values
31*> (or symmetric/hermitian with specified eigenvalues)
32*> for testing LAPACK programs.
33*>
34*> SLATMS operates by applying the following sequence of
35*> operations:
36*>
37*> Set the diagonal to D, where D may be input or
38*> computed according to MODE, COND, DMAX, and SYM
39*> as described below.
40*>
41*> Generate a matrix with the appropriate band structure, by one
42*> of two methods:
43*>
44*> Method A:
45*> Generate a dense M x N matrix by multiplying D on the left
46*> and the right by random unitary matrices, then:
47*>
48*> Reduce the bandwidth according to KL and KU, using
49*> Householder transformations.
50*>
51*> Method B:
52*> Convert the bandwidth-0 (i.e., diagonal) matrix to a
53*> bandwidth-1 matrix using Givens rotations, "chasing"
54*> out-of-band elements back, much as in QR; then
55*> convert the bandwidth-1 to a bandwidth-2 matrix, etc.
56*> Note that for reasonably small bandwidths (relative to
57*> M and N) this requires less storage, as a dense matrix
58*> is not generated. Also, for symmetric matrices, only
59*> one triangle is generated.
60*>
61*> Method A is chosen if the bandwidth is a large fraction of the
62*> order of the matrix, and LDA is at least M (so a dense
63*> matrix can be stored.) Method B is chosen if the bandwidth
64*> is small (< 1/2 N for symmetric, < .3 N+M for
65*> non-symmetric), or LDA is less than M and not less than the
66*> bandwidth.
67*>
68*> Pack the matrix if desired. Options specified by PACK are:
69*> no packing
70*> zero out upper half (if symmetric)
71*> zero out lower half (if symmetric)
72*> store the upper half columnwise (if symmetric or upper
73*> triangular)
74*> store the lower half columnwise (if symmetric or lower
75*> triangular)
76*> store the lower triangle in banded format (if symmetric
77*> or lower triangular)
78*> store the upper triangle in banded format (if symmetric
79*> or upper triangular)
80*> store the entire matrix in banded format
81*> If Method B is chosen, and band format is specified, then the
82*> matrix will be generated in the band format, so no repacking
83*> will be necessary.
84*> \endverbatim
85*
86* Arguments:
87* ==========
88*
89*> \param[in] M
90*> \verbatim
91*> M is INTEGER
92*> The number of rows of A. Not modified.
93*> \endverbatim
94*>
95*> \param[in] N
96*> \verbatim
97*> N is INTEGER
98*> The number of columns of A. Not modified.
99*> \endverbatim
100*>
101*> \param[in] DIST
102*> \verbatim
103*> DIST is CHARACTER*1
104*> On entry, DIST specifies the type of distribution to be used
105*> to generate the random eigen-/singular values.
106*> 'U' => UNIFORM( 0, 1 ) ( 'U' for uniform )
107*> 'S' => UNIFORM( -1, 1 ) ( 'S' for symmetric )
108*> 'N' => NORMAL( 0, 1 ) ( 'N' for normal )
109*> Not modified.
110*> \endverbatim
111*>
112*> \param[in,out] ISEED
113*> \verbatim
114*> ISEED is INTEGER array, dimension ( 4 )
115*> On entry ISEED specifies the seed of the random number
116*> generator. They should lie between 0 and 4095 inclusive,
117*> and ISEED(4) should be odd. The random number generator
118*> uses a linear congruential sequence limited to small
119*> integers, and so should produce machine independent
120*> random numbers. The values of ISEED are changed on
121*> exit, and can be used in the next call to SLATMS
122*> to continue the same random number sequence.
123*> Changed on exit.
124*> \endverbatim
125*>
126*> \param[in] SYM
127*> \verbatim
128*> SYM is CHARACTER*1
129*> If SYM='S' or 'H', the generated matrix is symmetric, with
130*> eigenvalues specified by D, COND, MODE, and DMAX; they
131*> may be positive, negative, or zero.
132*> If SYM='P', the generated matrix is symmetric, with
133*> eigenvalues (= singular values) specified by D, COND,
134*> MODE, and DMAX; they will not be negative.
135*> If SYM='N', the generated matrix is nonsymmetric, with
136*> singular values specified by D, COND, MODE, and DMAX;
137*> they will not be negative.
138*> Not modified.
139*> \endverbatim
140*>
141*> \param[in,out] D
142*> \verbatim
143*> D is REAL array, dimension ( MIN( M , N ) )
144*> This array is used to specify the singular values or
145*> eigenvalues of A (see SYM, above.) If MODE=0, then D is
146*> assumed to contain the singular/eigenvalues, otherwise
147*> they will be computed according to MODE, COND, and DMAX,
148*> and placed in D.
149*> Modified if MODE is nonzero.
150*> \endverbatim
151*>
152*> \param[in] MODE
153*> \verbatim
154*> MODE is INTEGER
155*> On entry this describes how the singular/eigenvalues are to
156*> be specified:
157*> MODE = 0 means use D as input
158*> MODE = 1 sets D(1)=1 and D(2:N)=1.0/COND
159*> MODE = 2 sets D(1:N-1)=1 and D(N)=1.0/COND
160*> MODE = 3 sets D(I)=COND**(-(I-1)/(N-1))
161*> MODE = 4 sets D(i)=1 - (i-1)/(N-1)*(1 - 1/COND)
162*> MODE = 5 sets D to random numbers in the range
163*> ( 1/COND , 1 ) such that their logarithms
164*> are uniformly distributed.
165*> MODE = 6 set D to random numbers from same distribution
166*> as the rest of the matrix.
167*> MODE < 0 has the same meaning as ABS(MODE), except that
168*> the order of the elements of D is reversed.
169*> Thus if MODE is positive, D has entries ranging from
170*> 1 to 1/COND, if negative, from 1/COND to 1,
171*> If SYM='S' or 'H', and MODE is neither 0, 6, nor -6, then
172*> the elements of D will also be multiplied by a random
173*> sign (i.e., +1 or -1.)
174*> Not modified.
175*> \endverbatim
176*>
177*> \param[in] COND
178*> \verbatim
179*> COND is REAL
180*> On entry, this is used as described under MODE above.
181*> If used, it must be >= 1. Not modified.
182*> \endverbatim
183*>
184*> \param[in] DMAX
185*> \verbatim
186*> DMAX is REAL
187*> If MODE is neither -6, 0 nor 6, the contents of D, as
188*> computed according to MODE and COND, will be scaled by
189*> DMAX / max(abs(D(i))); thus, the maximum absolute eigen- or
190*> singular value (which is to say the norm) will be abs(DMAX).
191*> Note that DMAX need not be positive: if DMAX is negative
192*> (or zero), D will be scaled by a negative number (or zero).
193*> Not modified.
194*> \endverbatim
195*>
196*> \param[in] KL
197*> \verbatim
198*> KL is INTEGER
199*> This specifies the lower bandwidth of the matrix. For
200*> example, KL=0 implies upper triangular, KL=1 implies upper
201*> Hessenberg, and KL being at least M-1 means that the matrix
202*> has full lower bandwidth. KL must equal KU if the matrix
203*> is symmetric.
204*> Not modified.
205*> \endverbatim
206*>
207*> \param[in] KU
208*> \verbatim
209*> KU is INTEGER
210*> This specifies the upper bandwidth of the matrix. For
211*> example, KU=0 implies lower triangular, KU=1 implies lower
212*> Hessenberg, and KU being at least N-1 means that the matrix
213*> has full upper bandwidth. KL must equal KU if the matrix
214*> is symmetric.
215*> Not modified.
216*> \endverbatim
217*>
218*> \param[in] PACK
219*> \verbatim
220*> PACK is CHARACTER*1
221*> This specifies packing of matrix as follows:
222*> 'N' => no packing
223*> 'U' => zero out all subdiagonal entries (if symmetric)
224*> 'L' => zero out all superdiagonal entries (if symmetric)
225*> 'C' => store the upper triangle columnwise
226*> (only if the matrix is symmetric or upper triangular)
227*> 'R' => store the lower triangle columnwise
228*> (only if the matrix is symmetric or lower triangular)
229*> 'B' => store the lower triangle in band storage scheme
230*> (only if matrix symmetric or lower triangular)
231*> 'Q' => store the upper triangle in band storage scheme
232*> (only if matrix symmetric or upper triangular)
233*> 'Z' => store the entire matrix in band storage scheme
234*> (pivoting can be provided for by using this
235*> option to store A in the trailing rows of
236*> the allocated storage)
237*>
238*> Using these options, the various LAPACK packed and banded
239*> storage schemes can be obtained:
240*> GB - use 'Z'
241*> PB, SB or TB - use 'B' or 'Q'
242*> PP, SP or TP - use 'C' or 'R'
243*>
244*> If two calls to SLATMS differ only in the PACK parameter,
245*> they will generate mathematically equivalent matrices.
246*> Not modified.
247*> \endverbatim
248*>
249*> \param[in,out] A
250*> \verbatim
251*> A is REAL array, dimension ( LDA, N )
252*> On exit A is the desired test matrix. A is first generated
253*> in full (unpacked) form, and then packed, if so specified
254*> by PACK. Thus, the first M elements of the first N
255*> columns will always be modified. If PACK specifies a
256*> packed or banded storage scheme, all LDA elements of the
257*> first N columns will be modified; the elements of the
258*> array which do not correspond to elements of the generated
259*> matrix are set to zero.
260*> Modified.
261*> \endverbatim
262*>
263*> \param[in] LDA
264*> \verbatim
265*> LDA is INTEGER
266*> LDA specifies the first dimension of A as declared in the
267*> calling program. If PACK='N', 'U', 'L', 'C', or 'R', then
268*> LDA must be at least M. If PACK='B' or 'Q', then LDA must
269*> be at least MIN( KL, M-1) (which is equal to MIN(KU,N-1)).
270*> If PACK='Z', LDA must be large enough to hold the packed
271*> array: MIN( KU, N-1) + MIN( KL, M-1) + 1.
272*> Not modified.
273*> \endverbatim
274*>
275*> \param[out] WORK
276*> \verbatim
277*> WORK is REAL array, dimension ( 3*MAX( N , M ) )
278*> Workspace.
279*> Modified.
280*> \endverbatim
281*>
282*> \param[out] INFO
283*> \verbatim
284*> INFO is INTEGER
285*> Error code. On exit, INFO will be set to one of the
286*> following values:
287*> 0 => normal return
288*> -1 => M negative or unequal to N and SYM='S', 'H', or 'P'
289*> -2 => N negative
290*> -3 => DIST illegal string
291*> -5 => SYM illegal string
292*> -7 => MODE not in range -6 to 6
293*> -8 => COND less than 1.0, and MODE neither -6, 0 nor 6
294*> -10 => KL negative
295*> -11 => KU negative, or SYM='S' or 'H' and KU not equal to KL
296*> -12 => PACK illegal string, or PACK='U' or 'L', and SYM='N';
297*> or PACK='C' or 'Q' and SYM='N' and KL is not zero;
298*> or PACK='R' or 'B' and SYM='N' and KU is not zero;
299*> or PACK='U', 'L', 'C', 'R', 'B', or 'Q', and M is not
300*> N.
301*> -14 => LDA is less than M, or PACK='Z' and LDA is less than
302*> MIN(KU,N-1) + MIN(KL,M-1) + 1.
303*> 1 => Error return from SLATM1
304*> 2 => Cannot scale to DMAX (max. sing. value is 0)
305*> 3 => Error return from SLAGGE or SLAGSY
306*> \endverbatim
307*
308* Authors:
309* ========
310*
311*> \author Univ. of Tennessee
312*> \author Univ. of California Berkeley
313*> \author Univ. of Colorado Denver
314*> \author NAG Ltd.
315*
316*> \ingroup real_matgen
317*
318* =====================================================================
319 SUBROUTINE slatms( M, N, DIST, ISEED, SYM, D, MODE, COND, DMAX,
320 $ KL, KU, PACK, A, LDA, WORK, INFO )
321*
322* -- LAPACK computational routine --
323* -- LAPACK is a software package provided by Univ. of Tennessee, --
324* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
325*
326* .. Scalar Arguments ..
327 CHARACTER DIST, PACK, SYM
328 INTEGER INFO, KL, KU, LDA, M, MODE, N
329 REAL COND, DMAX
330* ..
331* .. Array Arguments ..
332 INTEGER ISEED( 4 )
333 REAL A( LDA, * ), D( * ), WORK( * )
334* ..
335*
336* =====================================================================
337*
338* .. Parameters ..
339 REAL ZERO
340 parameter( zero = 0.0e0 )
341 REAL ONE
342 parameter( one = 1.0e0 )
343 REAL TWOPI
344 parameter( twopi = 6.28318530717958647692528676655900576839e+0 )
345* ..
346* .. Local Scalars ..
347 LOGICAL GIVENS, ILEXTR, ILTEMP, TOPDWN
348 INTEGER I, IC, ICOL, IDIST, IENDCH, IINFO, IL, ILDA,
349 $ ioffg, ioffst, ipack, ipackg, ir, ir1, ir2,
350 $ irow, irsign, iskew, isym, isympk, j, jc, jch,
351 $ jkl, jku, jr, k, llb, minlda, mnmin, mr, nc,
352 $ uub
353 REAL ALPHA, ANGLE, C, DUMMY, EXTRA, S, TEMP
354* ..
355* .. External Functions ..
356 LOGICAL LSAME
357 REAL SLARND
358 EXTERNAL lsame, slarnd
359* ..
360* .. External Subroutines ..
361 EXTERNAL scopy, slagge, slagsy,
362 $ slarot, slartg, slatm1,
364* ..
365* .. Intrinsic Functions ..
366 INTRINSIC abs, cos, max, min, mod, real, sin
367* ..
368* .. Executable Statements ..
369*
370* 1) Decode and Test the input parameters.
371* Initialize flags & seed.
372*
373 info = 0
374*
375* Quick return if possible
376*
377 IF( m.EQ.0 .OR. n.EQ.0 )
378 $ RETURN
379*
380* Decode DIST
381*
382 IF( lsame( dist, 'U' ) ) THEN
383 idist = 1
384 ELSE IF( lsame( dist, 'S' ) ) THEN
385 idist = 2
386 ELSE IF( lsame( dist, 'N' ) ) THEN
387 idist = 3
388 ELSE
389 idist = -1
390 END IF
391*
392* Decode SYM
393*
394 IF( lsame( sym, 'N' ) ) THEN
395 isym = 1
396 irsign = 0
397 ELSE IF( lsame( sym, 'P' ) ) THEN
398 isym = 2
399 irsign = 0
400 ELSE IF( lsame( sym, 'S' ) ) THEN
401 isym = 2
402 irsign = 1
403 ELSE IF( lsame( sym, 'H' ) ) THEN
404 isym = 2
405 irsign = 1
406 ELSE
407 isym = -1
408 END IF
409*
410* Decode PACK
411*
412 isympk = 0
413 IF( lsame( pack, 'N' ) ) THEN
414 ipack = 0
415 ELSE IF( lsame( pack, 'U' ) ) THEN
416 ipack = 1
417 isympk = 1
418 ELSE IF( lsame( pack, 'L' ) ) THEN
419 ipack = 2
420 isympk = 1
421 ELSE IF( lsame( pack, 'C' ) ) THEN
422 ipack = 3
423 isympk = 2
424 ELSE IF( lsame( pack, 'R' ) ) THEN
425 ipack = 4
426 isympk = 3
427 ELSE IF( lsame( pack, 'B' ) ) THEN
428 ipack = 5
429 isympk = 3
430 ELSE IF( lsame( pack, 'Q' ) ) THEN
431 ipack = 6
432 isympk = 2
433 ELSE IF( lsame( pack, 'Z' ) ) THEN
434 ipack = 7
435 ELSE
436 ipack = -1
437 END IF
438*
439* Set certain internal parameters
440*
441 mnmin = min( m, n )
442 llb = min( kl, m-1 )
443 uub = min( ku, n-1 )
444 mr = min( m, n+llb )
445 nc = min( n, m+uub )
446*
447 IF( ipack.EQ.5 .OR. ipack.EQ.6 ) THEN
448 minlda = uub + 1
449 ELSE IF( ipack.EQ.7 ) THEN
450 minlda = llb + uub + 1
451 ELSE
452 minlda = m
453 END IF
454*
455* Use Givens rotation method if bandwidth small enough,
456* or if LDA is too small to store the matrix unpacked.
457*
458 givens = .false.
459 IF( isym.EQ.1 ) THEN
460 IF( real( llb+uub ).LT.0.3*real( max( 1, mr+nc ) ) )
461 $ givens = .true.
462 ELSE
463 IF( 2*llb.LT.m )
464 $ givens = .true.
465 END IF
466 IF( lda.LT.m .AND. lda.GE.minlda )
467 $ givens = .true.
468*
469* Set INFO if an error
470*
471 IF( m.LT.0 ) THEN
472 info = -1
473 ELSE IF( m.NE.n .AND. isym.NE.1 ) THEN
474 info = -1
475 ELSE IF( n.LT.0 ) THEN
476 info = -2
477 ELSE IF( idist.EQ.-1 ) THEN
478 info = -3
479 ELSE IF( isym.EQ.-1 ) THEN
480 info = -5
481 ELSE IF( abs( mode ).GT.6 ) THEN
482 info = -7
483 ELSE IF( ( mode.NE.0 .AND. abs( mode ).NE.6 ) .AND. cond.LT.one )
484 $ THEN
485 info = -8
486 ELSE IF( kl.LT.0 ) THEN
487 info = -10
488 ELSE IF( ku.LT.0 .OR. ( isym.NE.1 .AND. kl.NE.ku ) ) THEN
489 info = -11
490 ELSE IF( ipack.EQ.-1 .OR. ( isympk.EQ.1 .AND. isym.EQ.1 ) .OR.
491 $ ( isympk.EQ.2 .AND. isym.EQ.1 .AND. kl.GT.0 ) .OR.
492 $ ( isympk.EQ.3 .AND. isym.EQ.1 .AND. ku.GT.0 ) .OR.
493 $ ( isympk.NE.0 .AND. m.NE.n ) ) THEN
494 info = -12
495 ELSE IF( lda.LT.max( 1, minlda ) ) THEN
496 info = -14
497 END IF
498*
499 IF( info.NE.0 ) THEN
500 CALL xerbla( 'SLATMS', -info )
501 RETURN
502 END IF
503*
504* Initialize random number generator
505*
506 DO 10 i = 1, 4
507 iseed( i ) = mod( abs( iseed( i ) ), 4096 )
508 10 CONTINUE
509*
510 IF( mod( iseed( 4 ), 2 ).NE.1 )
511 $ iseed( 4 ) = iseed( 4 ) + 1
512*
513* 2) Set up D if indicated.
514*
515* Compute D according to COND and MODE
516*
517 CALL slatm1( mode, cond, irsign, idist, iseed, d, mnmin,
518 $ iinfo )
519 IF( iinfo.NE.0 ) THEN
520 info = 1
521 RETURN
522 END IF
523*
524* Choose Top-Down if D is (apparently) increasing,
525* Bottom-Up if D is (apparently) decreasing.
526*
527 IF( abs( d( 1 ) ).LE.abs( d( mnmin ) ) ) THEN
528 topdwn = .true.
529 ELSE
530 topdwn = .false.
531 END IF
532*
533 IF( mode.NE.0 .AND. abs( mode ).NE.6 ) THEN
534*
535* Scale by DMAX
536*
537 temp = abs( d( 1 ) )
538 DO 20 i = 2, mnmin
539 temp = max( temp, abs( d( i ) ) )
540 20 CONTINUE
541*
542 IF( temp.GT.zero ) THEN
543 alpha = dmax / temp
544 ELSE
545 info = 2
546 RETURN
547 END IF
548*
549 CALL sscal( mnmin, alpha, d, 1 )
550*
551 END IF
552*
553* 3) Generate Banded Matrix using Givens rotations.
554* Also the special case of UUB=LLB=0
555*
556* Compute Addressing constants to cover all
557* storage formats. Whether GE, SY, GB, or SB,
558* upper or lower triangle or both,
559* the (i,j)-th element is in
560* A( i - ISKEW*j + IOFFST, j )
561*
562 IF( ipack.GT.4 ) THEN
563 ilda = lda - 1
564 iskew = 1
565 IF( ipack.GT.5 ) THEN
566 ioffst = uub + 1
567 ELSE
568 ioffst = 1
569 END IF
570 ELSE
571 ilda = lda
572 iskew = 0
573 ioffst = 0
574 END IF
575*
576* IPACKG is the format that the matrix is generated in. If this is
577* different from IPACK, then the matrix must be repacked at the
578* end. It also signals how to compute the norm, for scaling.
579*
580 ipackg = 0
581 CALL slaset( 'Full', lda, n, zero, zero, a, lda )
582*
583* Diagonal Matrix -- We are done, unless it
584* is to be stored SP/PP/TP (PACK='R' or 'C')
585*
586 IF( llb.EQ.0 .AND. uub.EQ.0 ) THEN
587 CALL scopy( mnmin, d, 1, a( 1-iskew+ioffst, 1 ), ilda+1 )
588 IF( ipack.LE.2 .OR. ipack.GE.5 )
589 $ ipackg = ipack
590*
591 ELSE IF( givens ) THEN
592*
593* Check whether to use Givens rotations,
594* Householder transformations, or nothing.
595*
596 IF( isym.EQ.1 ) THEN
597*
598* Non-symmetric -- A = U D V
599*
600 IF( ipack.GT.4 ) THEN
601 ipackg = ipack
602 ELSE
603 ipackg = 0
604 END IF
605*
606 CALL scopy( mnmin, d, 1, a( 1-iskew+ioffst, 1 ), ilda+1 )
607*
608 IF( topdwn ) THEN
609 jkl = 0
610 DO 50 jku = 1, uub
611*
612* Transform from bandwidth JKL, JKU-1 to JKL, JKU
613*
614* Last row actually rotated is M
615* Last column actually rotated is MIN( M+JKU, N )
616*
617 DO 40 jr = 1, min( m+jku, n ) + jkl - 1
618 extra = zero
619 angle = twopi*slarnd( 1, iseed )
620 c = cos( angle )
621 s = sin( angle )
622 icol = max( 1, jr-jkl )
623 IF( jr.LT.m ) THEN
624 il = min( n, jr+jku ) + 1 - icol
625 CALL slarot( .true., jr.GT.jkl, .false., il,
626 $ c,
627 $ s, a( jr-iskew*icol+ioffst, icol ),
628 $ ilda, extra, dummy )
629 END IF
630*
631* Chase "EXTRA" back up
632*
633 ir = jr
634 ic = icol
635 DO 30 jch = jr - jkl, 1, -jkl - jku
636 IF( ir.LT.m ) THEN
637 CALL slartg( a( ir+1-iskew*( ic+1 )+ioffst,
638 $ ic+1 ), extra, c, s, dummy )
639 END IF
640 irow = max( 1, jch-jku )
641 il = ir + 2 - irow
642 temp = zero
643 iltemp = jch.GT.jku
644 CALL slarot( .false., iltemp, .true., il, c,
645 $ -s,
646 $ a( irow-iskew*ic+ioffst, ic ),
647 $ ilda, temp, extra )
648 IF( iltemp ) THEN
649 CALL slartg( a( irow+1-iskew*( ic+1 )+ioffst,
650 $ ic+1 ), temp, c, s, dummy )
651 icol = max( 1, jch-jku-jkl )
652 il = ic + 2 - icol
653 extra = zero
654 CALL slarot( .true., jch.GT.jku+jkl,
655 $ .true.,
656 $ il, c, -s, a( irow-iskew*icol+
657 $ ioffst, icol ), ilda, extra,
658 $ temp )
659 ic = icol
660 ir = irow
661 END IF
662 30 CONTINUE
663 40 CONTINUE
664 50 CONTINUE
665*
666 jku = uub
667 DO 80 jkl = 1, llb
668*
669* Transform from bandwidth JKL-1, JKU to JKL, JKU
670*
671 DO 70 jc = 1, min( n+jkl, m ) + jku - 1
672 extra = zero
673 angle = twopi*slarnd( 1, iseed )
674 c = cos( angle )
675 s = sin( angle )
676 irow = max( 1, jc-jku )
677 IF( jc.LT.n ) THEN
678 il = min( m, jc+jkl ) + 1 - irow
679 CALL slarot( .false., jc.GT.jku, .false., il,
680 $ c,
681 $ s, a( irow-iskew*jc+ioffst, jc ),
682 $ ilda, extra, dummy )
683 END IF
684*
685* Chase "EXTRA" back up
686*
687 ic = jc
688 ir = irow
689 DO 60 jch = jc - jku, 1, -jkl - jku
690 IF( ic.LT.n ) THEN
691 CALL slartg( a( ir+1-iskew*( ic+1 )+ioffst,
692 $ ic+1 ), extra, c, s, dummy )
693 END IF
694 icol = max( 1, jch-jkl )
695 il = ic + 2 - icol
696 temp = zero
697 iltemp = jch.GT.jkl
698 CALL slarot( .true., iltemp, .true., il, c,
699 $ -s,
700 $ a( ir-iskew*icol+ioffst, icol ),
701 $ ilda, temp, extra )
702 IF( iltemp ) THEN
703 CALL slartg( a( ir+1-iskew*( icol+1 )+ioffst,
704 $ icol+1 ), temp, c, s, dummy )
705 irow = max( 1, jch-jkl-jku )
706 il = ir + 2 - irow
707 extra = zero
708 CALL slarot( .false., jch.GT.jkl+jku,
709 $ .true.,
710 $ il, c, -s, a( irow-iskew*icol+
711 $ ioffst, icol ), ilda, extra,
712 $ temp )
713 ic = icol
714 ir = irow
715 END IF
716 60 CONTINUE
717 70 CONTINUE
718 80 CONTINUE
719*
720 ELSE
721*
722* Bottom-Up -- Start at the bottom right.
723*
724 jkl = 0
725 DO 110 jku = 1, uub
726*
727* Transform from bandwidth JKL, JKU-1 to JKL, JKU
728*
729* First row actually rotated is M
730* First column actually rotated is MIN( M+JKU, N )
731*
732 iendch = min( m, n+jkl ) - 1
733 DO 100 jc = min( m+jku, n ) - 1, 1 - jkl, -1
734 extra = zero
735 angle = twopi*slarnd( 1, iseed )
736 c = cos( angle )
737 s = sin( angle )
738 irow = max( 1, jc-jku+1 )
739 IF( jc.GT.0 ) THEN
740 il = min( m, jc+jkl+1 ) + 1 - irow
741 CALL slarot( .false., .false., jc+jkl.LT.m,
742 $ il,
743 $ c, s, a( irow-iskew*jc+ioffst,
744 $ jc ), ilda, dummy, extra )
745 END IF
746*
747* Chase "EXTRA" back down
748*
749 ic = jc
750 DO 90 jch = jc + jkl, iendch, jkl + jku
751 ilextr = ic.GT.0
752 IF( ilextr ) THEN
753 CALL slartg( a( jch-iskew*ic+ioffst, ic ),
754 $ extra, c, s, dummy )
755 END IF
756 ic = max( 1, ic )
757 icol = min( n-1, jch+jku )
758 iltemp = jch + jku.LT.n
759 temp = zero
760 CALL slarot( .true., ilextr, iltemp,
761 $ icol+2-ic,
762 $ c, s, a( jch-iskew*ic+ioffst, ic ),
763 $ ilda, extra, temp )
764 IF( iltemp ) THEN
765 CALL slartg( a( jch-iskew*icol+ioffst,
766 $ icol ), temp, c, s, dummy )
767 il = min( iendch, jch+jkl+jku ) + 2 - jch
768 extra = zero
769 CALL slarot( .false., .true.,
770 $ jch+jkl+jku.LE.iendch, il, c, s,
771 $ a( jch-iskew*icol+ioffst,
772 $ icol ), ilda, temp, extra )
773 ic = icol
774 END IF
775 90 CONTINUE
776 100 CONTINUE
777 110 CONTINUE
778*
779 jku = uub
780 DO 140 jkl = 1, llb
781*
782* Transform from bandwidth JKL-1, JKU to JKL, JKU
783*
784* First row actually rotated is MIN( N+JKL, M )
785* First column actually rotated is N
786*
787 iendch = min( n, m+jku ) - 1
788 DO 130 jr = min( n+jkl, m ) - 1, 1 - jku, -1
789 extra = zero
790 angle = twopi*slarnd( 1, iseed )
791 c = cos( angle )
792 s = sin( angle )
793 icol = max( 1, jr-jkl+1 )
794 IF( jr.GT.0 ) THEN
795 il = min( n, jr+jku+1 ) + 1 - icol
796 CALL slarot( .true., .false., jr+jku.LT.n,
797 $ il,
798 $ c, s, a( jr-iskew*icol+ioffst,
799 $ icol ), ilda, dummy, extra )
800 END IF
801*
802* Chase "EXTRA" back down
803*
804 ir = jr
805 DO 120 jch = jr + jku, iendch, jkl + jku
806 ilextr = ir.GT.0
807 IF( ilextr ) THEN
808 CALL slartg( a( ir-iskew*jch+ioffst, jch ),
809 $ extra, c, s, dummy )
810 END IF
811 ir = max( 1, ir )
812 irow = min( m-1, jch+jkl )
813 iltemp = jch + jkl.LT.m
814 temp = zero
815 CALL slarot( .false., ilextr, iltemp,
816 $ irow+2-ir,
817 $ c, s, a( ir-iskew*jch+ioffst,
818 $ jch ), ilda, extra, temp )
819 IF( iltemp ) THEN
820 CALL slartg( a( irow-iskew*jch+ioffst, jch ),
821 $ temp, c, s, dummy )
822 il = min( iendch, jch+jkl+jku ) + 2 - jch
823 extra = zero
824 CALL slarot( .true., .true.,
825 $ jch+jkl+jku.LE.iendch, il, c, s,
826 $ a( irow-iskew*jch+ioffst, jch ),
827 $ ilda, temp, extra )
828 ir = irow
829 END IF
830 120 CONTINUE
831 130 CONTINUE
832 140 CONTINUE
833 END IF
834*
835 ELSE
836*
837* Symmetric -- A = U D U'
838*
839 ipackg = ipack
840 ioffg = ioffst
841*
842 IF( topdwn ) THEN
843*
844* Top-Down -- Generate Upper triangle only
845*
846 IF( ipack.GE.5 ) THEN
847 ipackg = 6
848 ioffg = uub + 1
849 ELSE
850 ipackg = 1
851 END IF
852 CALL scopy( mnmin, d, 1, a( 1-iskew+ioffg, 1 ), ilda+1 )
853*
854 DO 170 k = 1, uub
855 DO 160 jc = 1, n - 1
856 irow = max( 1, jc-k )
857 il = min( jc+1, k+2 )
858 extra = zero
859 temp = a( jc-iskew*( jc+1 )+ioffg, jc+1 )
860 angle = twopi*slarnd( 1, iseed )
861 c = cos( angle )
862 s = sin( angle )
863 CALL slarot( .false., jc.GT.k, .true., il, c, s,
864 $ a( irow-iskew*jc+ioffg, jc ), ilda,
865 $ extra, temp )
866 CALL slarot( .true., .true., .false.,
867 $ min( k, n-jc )+1, c, s,
868 $ a( ( 1-iskew )*jc+ioffg, jc ), ilda,
869 $ temp, dummy )
870*
871* Chase EXTRA back up the matrix
872*
873 icol = jc
874 DO 150 jch = jc - k, 1, -k
875 CALL slartg( a( jch+1-iskew*( icol+1 )+ioffg,
876 $ icol+1 ), extra, c, s, dummy )
877 temp = a( jch-iskew*( jch+1 )+ioffg, jch+1 )
878 CALL slarot( .true., .true., .true., k+2, c,
879 $ -s,
880 $ a( ( 1-iskew )*jch+ioffg, jch ),
881 $ ilda, temp, extra )
882 irow = max( 1, jch-k )
883 il = min( jch+1, k+2 )
884 extra = zero
885 CALL slarot( .false., jch.GT.k, .true., il,
886 $ c,
887 $ -s, a( irow-iskew*jch+ioffg, jch ),
888 $ ilda, extra, temp )
889 icol = jch
890 150 CONTINUE
891 160 CONTINUE
892 170 CONTINUE
893*
894* If we need lower triangle, copy from upper. Note that
895* the order of copying is chosen to work for 'q' -> 'b'
896*
897 IF( ipack.NE.ipackg .AND. ipack.NE.3 ) THEN
898 DO 190 jc = 1, n
899 irow = ioffst - iskew*jc
900 DO 180 jr = jc, min( n, jc+uub )
901 a( jr+irow, jc ) = a( jc-iskew*jr+ioffg, jr )
902 180 CONTINUE
903 190 CONTINUE
904 IF( ipack.EQ.5 ) THEN
905 DO 210 jc = n - uub + 1, n
906 DO 200 jr = n + 2 - jc, uub + 1
907 a( jr, jc ) = zero
908 200 CONTINUE
909 210 CONTINUE
910 END IF
911 IF( ipackg.EQ.6 ) THEN
912 ipackg = ipack
913 ELSE
914 ipackg = 0
915 END IF
916 END IF
917 ELSE
918*
919* Bottom-Up -- Generate Lower triangle only
920*
921 IF( ipack.GE.5 ) THEN
922 ipackg = 5
923 IF( ipack.EQ.6 )
924 $ ioffg = 1
925 ELSE
926 ipackg = 2
927 END IF
928 CALL scopy( mnmin, d, 1, a( 1-iskew+ioffg, 1 ), ilda+1 )
929*
930 DO 240 k = 1, uub
931 DO 230 jc = n - 1, 1, -1
932 il = min( n+1-jc, k+2 )
933 extra = zero
934 temp = a( 1+( 1-iskew )*jc+ioffg, jc )
935 angle = twopi*slarnd( 1, iseed )
936 c = cos( angle )
937 s = -sin( angle )
938 CALL slarot( .false., .true., n-jc.GT.k, il, c,
939 $ s,
940 $ a( ( 1-iskew )*jc+ioffg, jc ), ilda,
941 $ temp, extra )
942 icol = max( 1, jc-k+1 )
943 CALL slarot( .true., .false., .true., jc+2-icol,
944 $ c,
945 $ s, a( jc-iskew*icol+ioffg, icol ),
946 $ ilda, dummy, temp )
947*
948* Chase EXTRA back down the matrix
949*
950 icol = jc
951 DO 220 jch = jc + k, n - 1, k
952 CALL slartg( a( jch-iskew*icol+ioffg, icol ),
953 $ extra, c, s, dummy )
954 temp = a( 1+( 1-iskew )*jch+ioffg, jch )
955 CALL slarot( .true., .true., .true., k+2, c,
956 $ s,
957 $ a( jch-iskew*icol+ioffg, icol ),
958 $ ilda, extra, temp )
959 il = min( n+1-jch, k+2 )
960 extra = zero
961 CALL slarot( .false., .true., n-jch.GT.k, il,
962 $ c,
963 $ s, a( ( 1-iskew )*jch+ioffg, jch ),
964 $ ilda, temp, extra )
965 icol = jch
966 220 CONTINUE
967 230 CONTINUE
968 240 CONTINUE
969*
970* If we need upper triangle, copy from lower. Note that
971* the order of copying is chosen to work for 'b' -> 'q'
972*
973 IF( ipack.NE.ipackg .AND. ipack.NE.4 ) THEN
974 DO 260 jc = n, 1, -1
975 irow = ioffst - iskew*jc
976 DO 250 jr = jc, max( 1, jc-uub ), -1
977 a( jr+irow, jc ) = a( jc-iskew*jr+ioffg, jr )
978 250 CONTINUE
979 260 CONTINUE
980 IF( ipack.EQ.6 ) THEN
981 DO 280 jc = 1, uub
982 DO 270 jr = 1, uub + 1 - jc
983 a( jr, jc ) = zero
984 270 CONTINUE
985 280 CONTINUE
986 END IF
987 IF( ipackg.EQ.5 ) THEN
988 ipackg = ipack
989 ELSE
990 ipackg = 0
991 END IF
992 END IF
993 END IF
994 END IF
995*
996 ELSE
997*
998* 4) Generate Banded Matrix by first
999* Rotating by random Unitary matrices,
1000* then reducing the bandwidth using Householder
1001* transformations.
1002*
1003* Note: we should get here only if LDA .ge. N
1004*
1005 IF( isym.EQ.1 ) THEN
1006*
1007* Non-symmetric -- A = U D V
1008*
1009 CALL slagge( mr, nc, llb, uub, d, a, lda, iseed, work,
1010 $ iinfo )
1011 ELSE
1012*
1013* Symmetric -- A = U D U'
1014*
1015 CALL slagsy( m, llb, d, a, lda, iseed, work, iinfo )
1016*
1017 END IF
1018 IF( iinfo.NE.0 ) THEN
1019 info = 3
1020 RETURN
1021 END IF
1022 END IF
1023*
1024* 5) Pack the matrix
1025*
1026 IF( ipack.NE.ipackg ) THEN
1027 IF( ipack.EQ.1 ) THEN
1028*
1029* 'U' -- Upper triangular, not packed
1030*
1031 DO 300 j = 1, m
1032 DO 290 i = j + 1, m
1033 a( i, j ) = zero
1034 290 CONTINUE
1035 300 CONTINUE
1036*
1037 ELSE IF( ipack.EQ.2 ) THEN
1038*
1039* 'L' -- Lower triangular, not packed
1040*
1041 DO 320 j = 2, m
1042 DO 310 i = 1, j - 1
1043 a( i, j ) = zero
1044 310 CONTINUE
1045 320 CONTINUE
1046*
1047 ELSE IF( ipack.EQ.3 ) THEN
1048*
1049* 'C' -- Upper triangle packed Columnwise.
1050*
1051 icol = 1
1052 irow = 0
1053 DO 340 j = 1, m
1054 DO 330 i = 1, j
1055 irow = irow + 1
1056 IF( irow.GT.lda ) THEN
1057 irow = 1
1058 icol = icol + 1
1059 END IF
1060 a( irow, icol ) = a( i, j )
1061 330 CONTINUE
1062 340 CONTINUE
1063*
1064 ELSE IF( ipack.EQ.4 ) THEN
1065*
1066* 'R' -- Lower triangle packed Columnwise.
1067*
1068 icol = 1
1069 irow = 0
1070 DO 360 j = 1, m
1071 DO 350 i = j, m
1072 irow = irow + 1
1073 IF( irow.GT.lda ) THEN
1074 irow = 1
1075 icol = icol + 1
1076 END IF
1077 a( irow, icol ) = a( i, j )
1078 350 CONTINUE
1079 360 CONTINUE
1080*
1081 ELSE IF( ipack.GE.5 ) THEN
1082*
1083* 'B' -- The lower triangle is packed as a band matrix.
1084* 'Q' -- The upper triangle is packed as a band matrix.
1085* 'Z' -- The whole matrix is packed as a band matrix.
1086*
1087 IF( ipack.EQ.5 )
1088 $ uub = 0
1089 IF( ipack.EQ.6 )
1090 $ llb = 0
1091*
1092 DO 380 j = 1, uub
1093 DO 370 i = min( j+llb, m ), 1, -1
1094 a( i-j+uub+1, j ) = a( i, j )
1095 370 CONTINUE
1096 380 CONTINUE
1097*
1098 DO 400 j = uub + 2, n
1099 DO 390 i = j - uub, min( j+llb, m )
1100 a( i-j+uub+1, j ) = a( i, j )
1101 390 CONTINUE
1102 400 CONTINUE
1103 END IF
1104*
1105* If packed, zero out extraneous elements.
1106*
1107* Symmetric/Triangular Packed --
1108* zero out everything after A(IROW,ICOL)
1109*
1110 IF( ipack.EQ.3 .OR. ipack.EQ.4 ) THEN
1111 DO 420 jc = icol, m
1112 DO 410 jr = irow + 1, lda
1113 a( jr, jc ) = zero
1114 410 CONTINUE
1115 irow = 0
1116 420 CONTINUE
1117*
1118 ELSE IF( ipack.GE.5 ) THEN
1119*
1120* Packed Band --
1121* 1st row is now in A( UUB+2-j, j), zero above it
1122* m-th row is now in A( M+UUB-j,j), zero below it
1123* last non-zero diagonal is now in A( UUB+LLB+1,j ),
1124* zero below it, too.
1125*
1126 ir1 = uub + llb + 2
1127 ir2 = uub + m + 2
1128 DO 450 jc = 1, n
1129 DO 430 jr = 1, uub + 1 - jc
1130 a( jr, jc ) = zero
1131 430 CONTINUE
1132 DO 440 jr = max( 1, min( ir1, ir2-jc ) ), lda
1133 a( jr, jc ) = zero
1134 440 CONTINUE
1135 450 CONTINUE
1136 END IF
1137 END IF
1138*
1139 RETURN
1140*
1141* End of SLATMS
1142*
1143 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
Definition scopy.f:82
subroutine slartg(f, g, c, s, r)
SLARTG generates a plane rotation with real cosine and real sine.
Definition slartg.f90:111
subroutine slaset(uplo, m, n, alpha, beta, a, lda)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition slaset.f:108
subroutine sscal(n, sa, sx, incx)
SSCAL
Definition sscal.f:79
subroutine slagge(m, n, kl, ku, d, a, lda, iseed, work, info)
SLAGGE
Definition slagge.f:113
subroutine slagsy(n, k, d, a, lda, iseed, work, info)
SLAGSY
Definition slagsy.f:101
subroutine slarot(lrows, lleft, lright, nl, c, s, a, lda, xleft, xright)
SLAROT
Definition slarot.f:227
subroutine slatm1(mode, cond, irsign, idist, iseed, d, n, info)
SLATM1
Definition slatm1.f:136
subroutine slatms(m, n, dist, iseed, sym, d, mode, cond, dmax, kl, ku, pack, a, lda, work, info)
SLATMS
Definition slatms.f:321