LAPACK 3.3.1
Linear Algebra PACKage

slatmt.f

Go to the documentation of this file.
00001       SUBROUTINE SLATMT( M, N, DIST, ISEED, SYM, D, MODE, COND, DMAX,
00002      $                   RANK, KL, KU, PACK, A, LDA, WORK, INFO )
00003 *
00004 *  -- LAPACK test routine (version 3.1) --
00005 *     Craig Lucas, University of Manchester / NAG Ltd.
00006 *     October, 2008
00007 *
00008 *     .. Scalar Arguments ..
00009       REAL               COND, DMAX
00010       INTEGER            INFO, KL, KU, LDA, M, MODE, N, RANK
00011       CHARACTER          DIST, PACK, SYM
00012 *     ..
00013 *     .. Array Arguments ..
00014       REAL               A( LDA, * ), D( * ), WORK( * )
00015       INTEGER            ISEED( 4 )
00016 *     ..
00017 *
00018 *  Purpose
00019 *  =======
00020 *
00021 *     SLATMT generates random matrices with specified singular values
00022 *     (or symmetric/hermitian with specified eigenvalues)
00023 *     for testing LAPACK programs.
00024 *
00025 *     SLATMT operates by applying the following sequence of
00026 *     operations:
00027 *
00028 *       Set the diagonal to D, where D may be input or
00029 *          computed according to MODE, COND, DMAX, and SYM
00030 *          as described below.
00031 *
00032 *       Generate a matrix with the appropriate band structure, by one
00033 *          of two methods:
00034 *
00035 *       Method A:
00036 *           Generate a dense M x N matrix by multiplying D on the left
00037 *               and the right by random unitary matrices, then:
00038 *
00039 *           Reduce the bandwidth according to KL and KU, using
00040 *           Householder transformations.
00041 *
00042 *       Method B:
00043 *           Convert the bandwidth-0 (i.e., diagonal) matrix to a
00044 *               bandwidth-1 matrix using Givens rotations, "chasing"
00045 *               out-of-band elements back, much as in QR; then
00046 *               convert the bandwidth-1 to a bandwidth-2 matrix, etc.
00047 *               Note that for reasonably small bandwidths (relative to
00048 *               M and N) this requires less storage, as a dense matrix
00049 *               is not generated.  Also, for symmetric matrices, only
00050 *               one triangle is generated.
00051 *
00052 *       Method A is chosen if the bandwidth is a large fraction of the
00053 *           order of the matrix, and LDA is at least M (so a dense
00054 *           matrix can be stored.)  Method B is chosen if the bandwidth
00055 *           is small (< 1/2 N for symmetric, < .3 N+M for
00056 *           non-symmetric), or LDA is less than M and not less than the
00057 *           bandwidth.
00058 *
00059 *       Pack the matrix if desired. Options specified by PACK are:
00060 *          no packing
00061 *          zero out upper half (if symmetric)
00062 *          zero out lower half (if symmetric)
00063 *          store the upper half columnwise (if symmetric or upper
00064 *                triangular)
00065 *          store the lower half columnwise (if symmetric or lower
00066 *                triangular)
00067 *          store the lower triangle in banded format (if symmetric
00068 *                or lower triangular)
00069 *          store the upper triangle in banded format (if symmetric
00070 *                or upper triangular)
00071 *          store the entire matrix in banded format
00072 *       If Method B is chosen, and band format is specified, then the
00073 *          matrix will be generated in the band format, so no repacking
00074 *          will be necessary.
00075 *
00076 *  Arguments
00077 *  =========
00078 *
00079 *  M        (input) INTEGER
00080 *           The number of rows of A. Not modified.
00081 *
00082 *  N        (input) INTEGER
00083 *           The number of columns of A. Not modified.
00084 *
00085 *  DIST     (input) CHARACTER*1
00086 *           On entry, DIST specifies the type of distribution to be used
00087 *           to generate the random eigen-/singular values.
00088 *           'U' => UNIFORM( 0, 1 )  ( 'U' for uniform )
00089 *           'S' => UNIFORM( -1, 1 ) ( 'S' for symmetric )
00090 *           'N' => NORMAL( 0, 1 )   ( 'N' for normal )
00091 *           Not modified.
00092 *
00093 *  ISEED    (input/output) INTEGER array, dimension ( 4 )
00094 *           On entry ISEED specifies the seed of the random number
00095 *           generator. They should lie between 0 and 4095 inclusive,
00096 *           and ISEED(4) should be odd. The random number generator
00097 *           uses a linear congruential sequence limited to small
00098 *           integers, and so should produce machine independent
00099 *           random numbers. The values of ISEED are changed on
00100 *           exit, and can be used in the next call to SLATMT
00101 *           to continue the same random number sequence.
00102 *           Changed on exit.
00103 *
00104 *  SYM      (input) CHARACTER*1
00105 *           If SYM='S' or 'H', the generated matrix is symmetric, with
00106 *             eigenvalues specified by D, COND, MODE, and DMAX; they
00107 *             may be positive, negative, or zero.
00108 *           If SYM='P', the generated matrix is symmetric, with
00109 *             eigenvalues (= singular values) specified by D, COND,
00110 *             MODE, and DMAX; they will not be negative.
00111 *           If SYM='N', the generated matrix is nonsymmetric, with
00112 *             singular values specified by D, COND, MODE, and DMAX;
00113 *             they will not be negative.
00114 *           Not modified.
00115 *
00116 *  D        (input/output) REAL array, dimension ( MIN( M , N ) )
00117 *           This array is used to specify the singular values or
00118 *           eigenvalues of A (see SYM, above.)  If MODE=0, then D is
00119 *           assumed to contain the singular/eigenvalues, otherwise
00120 *           they will be computed according to MODE, COND, and DMAX,
00121 *           and placed in D.
00122 *           Modified if MODE is nonzero.
00123 *
00124 *  MODE     (input) INTEGER
00125 *           On entry this describes how the singular/eigenvalues are to
00126 *           be specified:
00127 *           MODE = 0 means use D as input
00128 *
00129 *           MODE = 1 sets D(1)=1 and D(2:RANK)=1.0/COND
00130 *           MODE = 2 sets D(1:RANK-1)=1 and D(RANK)=1.0/COND
00131 *           MODE = 3 sets D(I)=COND**(-(I-1)/(RANK-1))
00132 *
00133 *           MODE = 4 sets D(i)=1 - (i-1)/(N-1)*(1 - 1/COND)
00134 *           MODE = 5 sets D to random numbers in the range
00135 *                    ( 1/COND , 1 ) such that their logarithms
00136 *                    are uniformly distributed.
00137 *           MODE = 6 set D to random numbers from same distribution
00138 *                    as the rest of the matrix.
00139 *           MODE < 0 has the same meaning as ABS(MODE), except that
00140 *              the order of the elements of D is reversed.
00141 *           Thus if MODE is positive, D has entries ranging from
00142 *              1 to 1/COND, if negative, from 1/COND to 1,
00143 *           If SYM='S' or 'H', and MODE is neither 0, 6, nor -6, then
00144 *              the elements of D will also be multiplied by a random
00145 *              sign (i.e., +1 or -1.)
00146 *           Not modified.
00147 *
00148 *  COND     (input) REAL
00149 *           On entry, this is used as described under MODE above.
00150 *           If used, it must be >= 1. Not modified.
00151 *
00152 *  DMAX     (input) REAL
00153 *           If MODE is neither -6, 0 nor 6, the contents of D, as
00154 *           computed according to MODE and COND, will be scaled by
00155 *           DMAX / max(abs(D(i))); thus, the maximum absolute eigen- or
00156 *           singular value (which is to say the norm) will be abs(DMAX).
00157 *           Note that DMAX need not be positive: if DMAX is negative
00158 *           (or zero), D will be scaled by a negative number (or zero).
00159 *           Not modified.
00160 *
00161 *  RANK     (input) INTEGER
00162 *           The rank of matrix to be generated for modes 1,2,3 only.
00163 *           D( RANK+1:N ) = 0.
00164 *           Not modified.
00165 *
00166 *  KL       (input) INTEGER
00167 *           This specifies the lower bandwidth of the  matrix. For
00168 *           example, KL=0 implies upper triangular, KL=1 implies upper
00169 *           Hessenberg, and KL being at least M-1 means that the matrix
00170 *           has full lower bandwidth.  KL must equal KU if the matrix
00171 *           is symmetric.
00172 *           Not modified.
00173 *
00174 *  KU       (input) INTEGER
00175 *           This specifies the upper bandwidth of the  matrix. For
00176 *           example, KU=0 implies lower triangular, KU=1 implies lower
00177 *           Hessenberg, and KU being at least N-1 means that the matrix
00178 *           has full upper bandwidth.  KL must equal KU if the matrix
00179 *           is symmetric.
00180 *           Not modified.
00181 *
00182 *  PACK     (input) CHARACTER*1
00183 *           This specifies packing of matrix as follows:
00184 *           'N' => no packing
00185 *           'U' => zero out all subdiagonal entries (if symmetric)
00186 *           'L' => zero out all superdiagonal entries (if symmetric)
00187 *           'C' => store the upper triangle columnwise
00188 *                  (only if the matrix is symmetric or upper triangular)
00189 *           'R' => store the lower triangle columnwise
00190 *                  (only if the matrix is symmetric or lower triangular)
00191 *           'B' => store the lower triangle in band storage scheme
00192 *                  (only if matrix symmetric or lower triangular)
00193 *           'Q' => store the upper triangle in band storage scheme
00194 *                  (only if matrix symmetric or upper triangular)
00195 *           'Z' => store the entire matrix in band storage scheme
00196 *                      (pivoting can be provided for by using this
00197 *                      option to store A in the trailing rows of
00198 *                      the allocated storage)
00199 *
00200 *           Using these options, the various LAPACK packed and banded
00201 *           storage schemes can be obtained:
00202 *           GB               - use 'Z'
00203 *           PB, SB or TB     - use 'B' or 'Q'
00204 *           PP, SP or TP     - use 'C' or 'R'
00205 *
00206 *           If two calls to SLATMT differ only in the PACK parameter,
00207 *           they will generate mathematically equivalent matrices.
00208 *           Not modified.
00209 *
00210 *  A        (input/output) REAL array, dimension ( LDA, N )
00211 *           On exit A is the desired test matrix.  A is first generated
00212 *           in full (unpacked) form, and then packed, if so specified
00213 *           by PACK.  Thus, the first M elements of the first N
00214 *           columns will always be modified.  If PACK specifies a
00215 *           packed or banded storage scheme, all LDA elements of the
00216 *           first N columns will be modified; the elements of the
00217 *           array which do not correspond to elements of the generated
00218 *           matrix are set to zero.
00219 *           Modified.
00220 *
00221 *  LDA      (input) INTEGER
00222 *           LDA specifies the first dimension of A as declared in the
00223 *           calling program.  If PACK='N', 'U', 'L', 'C', or 'R', then
00224 *           LDA must be at least M.  If PACK='B' or 'Q', then LDA must
00225 *           be at least MIN( KL, M-1) (which is equal to MIN(KU,N-1)).
00226 *           If PACK='Z', LDA must be large enough to hold the packed
00227 *           array: MIN( KU, N-1) + MIN( KL, M-1) + 1.
00228 *           Not modified.
00229 *
00230 *  WORK     (workspace) REAL array, dimension ( 3*MAX( N , M ) )
00231 *           Workspace.
00232 *           Modified.
00233 *
00234 *  INFO     (output) INTEGER
00235 *           Error code.  On exit, INFO will be set to one of the
00236 *           following values:
00237 *             0 => normal return
00238 *            -1 => M negative or unequal to N and SYM='S', 'H', or 'P'
00239 *            -2 => N negative
00240 *            -3 => DIST illegal string
00241 *            -5 => SYM illegal string
00242 *            -7 => MODE not in range -6 to 6
00243 *            -8 => COND less than 1.0, and MODE neither -6, 0 nor 6
00244 *           -10 => KL negative
00245 *           -11 => KU negative, or SYM='S' or 'H' and KU not equal to KL
00246 *           -12 => PACK illegal string, or PACK='U' or 'L', and SYM='N';
00247 *                  or PACK='C' or 'Q' and SYM='N' and KL is not zero;
00248 *                  or PACK='R' or 'B' and SYM='N' and KU is not zero;
00249 *                  or PACK='U', 'L', 'C', 'R', 'B', or 'Q', and M is not
00250 *                  N.
00251 *           -14 => LDA is less than M, or PACK='Z' and LDA is less than
00252 *                  MIN(KU,N-1) + MIN(KL,M-1) + 1.
00253 *            1  => Error return from SLATM7
00254 *            2  => Cannot scale to DMAX (max. sing. value is 0)
00255 *            3  => Error return from SLAGGE or SLAGSY
00256 *
00257 *  =====================================================================
00258 *
00259 *     .. Parameters ..
00260       REAL               ZERO
00261       PARAMETER          ( ZERO = 0.0E0 )
00262       REAL               ONE
00263       PARAMETER          ( ONE = 1.0E0 )
00264       REAL               TWOPI
00265       PARAMETER          ( TWOPI = 6.2831853071795864769252867663E+0 )
00266 *     ..
00267 *     .. Local Scalars ..
00268       REAL               ALPHA, ANGLE, C, DUMMY, EXTRA, S, TEMP
00269       INTEGER            I, IC, ICOL, IDIST, IENDCH, IINFO, IL, ILDA,
00270      $                   IOFFG, IOFFST, IPACK, IPACKG, IR, IR1, IR2,
00271      $                   IROW, IRSIGN, ISKEW, ISYM, ISYMPK, J, JC, JCH,
00272      $                   JKL, JKU, JR, K, LLB, MINLDA, MNMIN, MR, NC,
00273      $                   UUB
00274       LOGICAL            GIVENS, ILEXTR, ILTEMP, TOPDWN
00275 *     ..
00276 *     .. External Functions ..
00277       REAL               SLARND
00278       LOGICAL            LSAME
00279       EXTERNAL           SLARND, LSAME
00280 *     ..
00281 *     .. External Subroutines ..
00282       EXTERNAL           SLATM7, SCOPY, SLAGGE, SLAGSY, SLAROT,
00283      $                   SLARTG, SLASET, SSCAL, XERBLA
00284 *     ..
00285 *     .. Intrinsic Functions ..
00286       INTRINSIC          ABS, COS, MAX, MIN, MOD, REAL, SIN
00287 *     ..
00288 *     .. Executable Statements ..
00289 *
00290 *     1)      Decode and Test the input parameters.
00291 *             Initialize flags & seed.
00292 *
00293       INFO = 0
00294 *
00295 *     Quick return if possible
00296 *
00297       IF( M.EQ.0 .OR. N.EQ.0 )
00298      $   RETURN
00299 *
00300 *     Decode DIST
00301 *
00302       IF( LSAME( DIST, 'U' ) ) THEN
00303          IDIST = 1
00304       ELSE IF( LSAME( DIST, 'S' ) ) THEN
00305          IDIST = 2
00306       ELSE IF( LSAME( DIST, 'N' ) ) THEN
00307          IDIST = 3
00308       ELSE
00309          IDIST = -1
00310       END IF
00311 *
00312 *     Decode SYM
00313 *
00314       IF( LSAME( SYM, 'N' ) ) THEN
00315          ISYM = 1
00316          IRSIGN = 0
00317       ELSE IF( LSAME( SYM, 'P' ) ) THEN
00318          ISYM = 2
00319          IRSIGN = 0
00320       ELSE IF( LSAME( SYM, 'S' ) ) THEN
00321          ISYM = 2
00322          IRSIGN = 1
00323       ELSE IF( LSAME( SYM, 'H' ) ) THEN
00324          ISYM = 2
00325          IRSIGN = 1
00326       ELSE
00327          ISYM = -1
00328       END IF
00329 *
00330 *     Decode PACK
00331 *
00332       ISYMPK = 0
00333       IF( LSAME( PACK, 'N' ) ) THEN
00334          IPACK = 0
00335       ELSE IF( LSAME( PACK, 'U' ) ) THEN
00336          IPACK = 1
00337          ISYMPK = 1
00338       ELSE IF( LSAME( PACK, 'L' ) ) THEN
00339          IPACK = 2
00340          ISYMPK = 1
00341       ELSE IF( LSAME( PACK, 'C' ) ) THEN
00342          IPACK = 3
00343          ISYMPK = 2
00344       ELSE IF( LSAME( PACK, 'R' ) ) THEN
00345          IPACK = 4
00346          ISYMPK = 3
00347       ELSE IF( LSAME( PACK, 'B' ) ) THEN
00348          IPACK = 5
00349          ISYMPK = 3
00350       ELSE IF( LSAME( PACK, 'Q' ) ) THEN
00351          IPACK = 6
00352          ISYMPK = 2
00353       ELSE IF( LSAME( PACK, 'Z' ) ) THEN
00354          IPACK = 7
00355       ELSE
00356          IPACK = -1
00357       END IF
00358 *
00359 *     Set certain internal parameters
00360 *
00361       MNMIN = MIN( M, N )
00362       LLB = MIN( KL, M-1 )
00363       UUB = MIN( KU, N-1 )
00364       MR = MIN( M, N+LLB )
00365       NC = MIN( N, M+UUB )
00366 *
00367       IF( IPACK.EQ.5 .OR. IPACK.EQ.6 ) THEN
00368          MINLDA = UUB + 1
00369       ELSE IF( IPACK.EQ.7 ) THEN
00370          MINLDA = LLB + UUB + 1
00371       ELSE
00372          MINLDA = M
00373       END IF
00374 *
00375 *     Use Givens rotation method if bandwidth small enough,
00376 *     or if LDA is too small to store the matrix unpacked.
00377 *
00378       GIVENS = .FALSE.
00379       IF( ISYM.EQ.1 ) THEN
00380          IF( REAL( LLB+UUB ).LT.0.3*REAL( MAX( 1, MR+NC ) ) )
00381      $      GIVENS = .TRUE.
00382       ELSE
00383          IF( 2*LLB.LT.M )
00384      $      GIVENS = .TRUE.
00385       END IF
00386       IF( LDA.LT.M .AND. LDA.GE.MINLDA )
00387      $   GIVENS = .TRUE.
00388 *
00389 *     Set INFO if an error
00390 *
00391       IF( M.LT.0 ) THEN
00392          INFO = -1
00393       ELSE IF( M.NE.N .AND. ISYM.NE.1 ) THEN
00394          INFO = -1
00395       ELSE IF( N.LT.0 ) THEN
00396          INFO = -2
00397       ELSE IF( IDIST.EQ.-1 ) THEN
00398          INFO = -3
00399       ELSE IF( ISYM.EQ.-1 ) THEN
00400          INFO = -5
00401       ELSE IF( ABS( MODE ).GT.6 ) THEN
00402          INFO = -7
00403       ELSE IF( ( MODE.NE.0 .AND. ABS( MODE ).NE.6 ) .AND. COND.LT.ONE )
00404      $         THEN
00405          INFO = -8
00406       ELSE IF( KL.LT.0 ) THEN
00407          INFO = -10
00408       ELSE IF( KU.LT.0 .OR. ( ISYM.NE.1 .AND. KL.NE.KU ) ) THEN
00409          INFO = -11
00410       ELSE IF( IPACK.EQ.-1 .OR. ( ISYMPK.EQ.1 .AND. ISYM.EQ.1 ) .OR.
00411      $         ( ISYMPK.EQ.2 .AND. ISYM.EQ.1 .AND. KL.GT.0 ) .OR.
00412      $         ( ISYMPK.EQ.3 .AND. ISYM.EQ.1 .AND. KU.GT.0 ) .OR.
00413      $         ( ISYMPK.NE.0 .AND. M.NE.N ) ) THEN
00414          INFO = -12
00415       ELSE IF( LDA.LT.MAX( 1, MINLDA ) ) THEN
00416          INFO = -14
00417       END IF
00418 *
00419       IF( INFO.NE.0 ) THEN
00420          CALL XERBLA( 'SLATMT', -INFO )
00421          RETURN
00422       END IF
00423 *
00424 *     Initialize random number generator
00425 *
00426       DO 100 I = 1, 4
00427          ISEED( I ) = MOD( ABS( ISEED( I ) ), 4096 )
00428   100 CONTINUE
00429 *
00430       IF( MOD( ISEED( 4 ), 2 ).NE.1 )
00431      $   ISEED( 4 ) = ISEED( 4 ) + 1
00432 *
00433 *     2)      Set up D  if indicated.
00434 *
00435 *             Compute D according to COND and MODE
00436 *
00437       CALL SLATM7( MODE, COND, IRSIGN, IDIST, ISEED, D, MNMIN, RANK,
00438      $             IINFO )
00439       IF( IINFO.NE.0 ) THEN
00440          INFO = 1
00441          RETURN
00442       END IF
00443 *
00444 *     Choose Top-Down if D is (apparently) increasing,
00445 *     Bottom-Up if D is (apparently) decreasing.
00446 *
00447       IF( ABS( D( 1 ) ).LE.ABS( D( RANK ) ) ) THEN
00448          TOPDWN = .TRUE.
00449       ELSE
00450          TOPDWN = .FALSE.
00451       END IF
00452 *
00453       IF( MODE.NE.0 .AND. ABS( MODE ).NE.6 ) THEN
00454 *
00455 *        Scale by DMAX
00456 *
00457          TEMP = ABS( D( 1 ) )
00458          DO 110 I = 2, RANK
00459             TEMP = MAX( TEMP, ABS( D( I ) ) )
00460   110    CONTINUE
00461 *
00462          IF( TEMP.GT.ZERO ) THEN
00463             ALPHA = DMAX / TEMP
00464          ELSE
00465             INFO = 2
00466             RETURN
00467          END IF
00468 *
00469          CALL SSCAL( RANK, ALPHA, D, 1 )
00470 *
00471       END IF
00472 *
00473 *     3)      Generate Banded Matrix using Givens rotations.
00474 *             Also the special case of UUB=LLB=0
00475 *
00476 *               Compute Addressing constants to cover all
00477 *               storage formats.  Whether GE, SY, GB, or SB,
00478 *               upper or lower triangle or both,
00479 *               the (i,j)-th element is in
00480 *               A( i - ISKEW*j + IOFFST, j )
00481 *
00482       IF( IPACK.GT.4 ) THEN
00483          ILDA = LDA - 1
00484          ISKEW = 1
00485          IF( IPACK.GT.5 ) THEN
00486             IOFFST = UUB + 1
00487          ELSE
00488             IOFFST = 1
00489          END IF
00490       ELSE
00491          ILDA = LDA
00492          ISKEW = 0
00493          IOFFST = 0
00494       END IF
00495 *
00496 *     IPACKG is the format that the matrix is generated in. If this is
00497 *     different from IPACK, then the matrix must be repacked at the
00498 *     end.  It also signals how to compute the norm, for scaling.
00499 *
00500       IPACKG = 0
00501       CALL SLASET( 'Full', LDA, N, ZERO, ZERO, A, LDA )
00502 *
00503 *     Diagonal Matrix -- We are done, unless it
00504 *     is to be stored SP/PP/TP (PACK='R' or 'C')
00505 *
00506       IF( LLB.EQ.0 .AND. UUB.EQ.0 ) THEN
00507          CALL SCOPY( MNMIN, D, 1, A( 1-ISKEW+IOFFST, 1 ), ILDA+1 )
00508          IF( IPACK.LE.2 .OR. IPACK.GE.5 )
00509      $      IPACKG = IPACK
00510 *
00511       ELSE IF( GIVENS ) THEN
00512 *
00513 *        Check whether to use Givens rotations,
00514 *        Householder transformations, or nothing.
00515 *
00516          IF( ISYM.EQ.1 ) THEN
00517 *
00518 *           Non-symmetric -- A = U D V
00519 *
00520             IF( IPACK.GT.4 ) THEN
00521                IPACKG = IPACK
00522             ELSE
00523                IPACKG = 0
00524             END IF
00525 *
00526             CALL SCOPY( MNMIN, D, 1, A( 1-ISKEW+IOFFST, 1 ), ILDA+1 )
00527 *
00528             IF( TOPDWN ) THEN
00529                JKL = 0
00530                DO 140 JKU = 1, UUB
00531 *
00532 *                 Transform from bandwidth JKL, JKU-1 to JKL, JKU
00533 *
00534 *                 Last row actually rotated is M
00535 *                 Last column actually rotated is MIN( M+JKU, N )
00536 *
00537                   DO 130 JR = 1, MIN( M+JKU, N ) + JKL - 1
00538                      EXTRA = ZERO
00539                      ANGLE = TWOPI*SLARND( 1, ISEED )
00540                      C = COS( ANGLE )
00541                      S = SIN( ANGLE )
00542                      ICOL = MAX( 1, JR-JKL )
00543                      IF( JR.LT.M ) THEN
00544                         IL = MIN( N, JR+JKU ) + 1 - ICOL
00545                         CALL SLAROT( .TRUE., JR.GT.JKL, .FALSE., IL, C,
00546      $                               S, A( JR-ISKEW*ICOL+IOFFST, ICOL ),
00547      $                               ILDA, EXTRA, DUMMY )
00548                      END IF
00549 *
00550 *                    Chase "EXTRA" back up
00551 *
00552                      IR = JR
00553                      IC = ICOL
00554                      DO 120 JCH = JR - JKL, 1, -JKL - JKU
00555                         IF( IR.LT.M ) THEN
00556                            CALL SLARTG( A( IR+1-ISKEW*( IC+1 )+IOFFST,
00557      $                                  IC+1 ), EXTRA, C, S, DUMMY )
00558                         END IF
00559                         IROW = MAX( 1, JCH-JKU )
00560                         IL = IR + 2 - IROW
00561                         TEMP = ZERO
00562                         ILTEMP = JCH.GT.JKU
00563                         CALL SLAROT( .FALSE., ILTEMP, .TRUE., IL, C, -S,
00564      $                               A( IROW-ISKEW*IC+IOFFST, IC ),
00565      $                               ILDA, TEMP, EXTRA )
00566                         IF( ILTEMP ) THEN
00567                            CALL SLARTG( A( IROW+1-ISKEW*( IC+1 )+IOFFST,
00568      $                                  IC+1 ), TEMP, C, S, DUMMY )
00569                            ICOL = MAX( 1, JCH-JKU-JKL )
00570                            IL = IC + 2 - ICOL
00571                            EXTRA = ZERO
00572                            CALL SLAROT( .TRUE., JCH.GT.JKU+JKL, .TRUE.,
00573      $                                  IL, C, -S, A( IROW-ISKEW*ICOL+
00574      $                                  IOFFST, ICOL ), ILDA, EXTRA,
00575      $                                  TEMP )
00576                            IC = ICOL
00577                            IR = IROW
00578                         END IF
00579   120                CONTINUE
00580   130             CONTINUE
00581   140          CONTINUE
00582 *
00583                JKU = UUB
00584                DO 170 JKL = 1, LLB
00585 *
00586 *                 Transform from bandwidth JKL-1, JKU to JKL, JKU
00587 *
00588                   DO 160 JC = 1, MIN( N+JKL, M ) + JKU - 1
00589                      EXTRA = ZERO
00590                      ANGLE = TWOPI*SLARND( 1, ISEED )
00591                      C = COS( ANGLE )
00592                      S = SIN( ANGLE )
00593                      IROW = MAX( 1, JC-JKU )
00594                      IF( JC.LT.N ) THEN
00595                         IL = MIN( M, JC+JKL ) + 1 - IROW
00596                         CALL SLAROT( .FALSE., JC.GT.JKU, .FALSE., IL, C,
00597      $                               S, A( IROW-ISKEW*JC+IOFFST, JC ),
00598      $                               ILDA, EXTRA, DUMMY )
00599                      END IF
00600 *
00601 *                    Chase "EXTRA" back up
00602 *
00603                      IC = JC
00604                      IR = IROW
00605                      DO 150 JCH = JC - JKU, 1, -JKL - JKU
00606                         IF( IC.LT.N ) THEN
00607                            CALL SLARTG( A( IR+1-ISKEW*( IC+1 )+IOFFST,
00608      $                                  IC+1 ), EXTRA, C, S, DUMMY )
00609                         END IF
00610                         ICOL = MAX( 1, JCH-JKL )
00611                         IL = IC + 2 - ICOL
00612                         TEMP = ZERO
00613                         ILTEMP = JCH.GT.JKL
00614                         CALL SLAROT( .TRUE., ILTEMP, .TRUE., IL, C, -S,
00615      $                               A( IR-ISKEW*ICOL+IOFFST, ICOL ),
00616      $                               ILDA, TEMP, EXTRA )
00617                         IF( ILTEMP ) THEN
00618                            CALL SLARTG( A( IR+1-ISKEW*( ICOL+1 )+IOFFST,
00619      $                                  ICOL+1 ), TEMP, C, S, DUMMY )
00620                            IROW = MAX( 1, JCH-JKL-JKU )
00621                            IL = IR + 2 - IROW
00622                            EXTRA = ZERO
00623                            CALL SLAROT( .FALSE., JCH.GT.JKL+JKU, .TRUE.,
00624      $                                  IL, C, -S, A( IROW-ISKEW*ICOL+
00625      $                                  IOFFST, ICOL ), ILDA, EXTRA,
00626      $                                  TEMP )
00627                            IC = ICOL
00628                            IR = IROW
00629                         END IF
00630   150                CONTINUE
00631   160             CONTINUE
00632   170          CONTINUE
00633 *
00634             ELSE
00635 *
00636 *              Bottom-Up -- Start at the bottom right.
00637 *
00638                JKL = 0
00639                DO 200 JKU = 1, UUB
00640 *
00641 *                 Transform from bandwidth JKL, JKU-1 to JKL, JKU
00642 *
00643 *                 First row actually rotated is M
00644 *                 First column actually rotated is MIN( M+JKU, N )
00645 *
00646                   IENDCH = MIN( M, N+JKL ) - 1
00647                   DO 190 JC = MIN( M+JKU, N ) - 1, 1 - JKL, -1
00648                      EXTRA = ZERO
00649                      ANGLE = TWOPI*SLARND( 1, ISEED )
00650                      C = COS( ANGLE )
00651                      S = SIN( ANGLE )
00652                      IROW = MAX( 1, JC-JKU+1 )
00653                      IF( JC.GT.0 ) THEN
00654                         IL = MIN( M, JC+JKL+1 ) + 1 - IROW
00655                         CALL SLAROT( .FALSE., .FALSE., JC+JKL.LT.M, IL,
00656      $                               C, S, A( IROW-ISKEW*JC+IOFFST,
00657      $                               JC ), ILDA, DUMMY, EXTRA )
00658                      END IF
00659 *
00660 *                    Chase "EXTRA" back down
00661 *
00662                      IC = JC
00663                      DO 180 JCH = JC + JKL, IENDCH, JKL + JKU
00664                         ILEXTR = IC.GT.0
00665                         IF( ILEXTR ) THEN
00666                            CALL SLARTG( A( JCH-ISKEW*IC+IOFFST, IC ),
00667      $                                  EXTRA, C, S, DUMMY )
00668                         END IF
00669                         IC = MAX( 1, IC )
00670                         ICOL = MIN( N-1, JCH+JKU )
00671                         ILTEMP = JCH + JKU.LT.N
00672                         TEMP = ZERO
00673                         CALL SLAROT( .TRUE., ILEXTR, ILTEMP, ICOL+2-IC,
00674      $                               C, S, A( JCH-ISKEW*IC+IOFFST, IC ),
00675      $                               ILDA, EXTRA, TEMP )
00676                         IF( ILTEMP ) THEN
00677                            CALL SLARTG( A( JCH-ISKEW*ICOL+IOFFST,
00678      $                                  ICOL ), TEMP, C, S, DUMMY )
00679                            IL = MIN( IENDCH, JCH+JKL+JKU ) + 2 - JCH
00680                            EXTRA = ZERO
00681                            CALL SLAROT( .FALSE., .TRUE.,
00682      $                                  JCH+JKL+JKU.LE.IENDCH, IL, C, S,
00683      $                                  A( JCH-ISKEW*ICOL+IOFFST,
00684      $                                  ICOL ), ILDA, TEMP, EXTRA )
00685                            IC = ICOL
00686                         END IF
00687   180                CONTINUE
00688   190             CONTINUE
00689   200          CONTINUE
00690 *
00691                JKU = UUB
00692                DO 230 JKL = 1, LLB
00693 *
00694 *                 Transform from bandwidth JKL-1, JKU to JKL, JKU
00695 *
00696 *                 First row actually rotated is MIN( N+JKL, M )
00697 *                 First column actually rotated is N
00698 *
00699                   IENDCH = MIN( N, M+JKU ) - 1
00700                   DO 220 JR = MIN( N+JKL, M ) - 1, 1 - JKU, -1
00701                      EXTRA = ZERO
00702                      ANGLE = TWOPI*SLARND( 1, ISEED )
00703                      C = COS( ANGLE )
00704                      S = SIN( ANGLE )
00705                      ICOL = MAX( 1, JR-JKL+1 )
00706                      IF( JR.GT.0 ) THEN
00707                         IL = MIN( N, JR+JKU+1 ) + 1 - ICOL
00708                         CALL SLAROT( .TRUE., .FALSE., JR+JKU.LT.N, IL,
00709      $                               C, S, A( JR-ISKEW*ICOL+IOFFST,
00710      $                               ICOL ), ILDA, DUMMY, EXTRA )
00711                      END IF
00712 *
00713 *                    Chase "EXTRA" back down
00714 *
00715                      IR = JR
00716                      DO 210 JCH = JR + JKU, IENDCH, JKL + JKU
00717                         ILEXTR = IR.GT.0
00718                         IF( ILEXTR ) THEN
00719                            CALL SLARTG( A( IR-ISKEW*JCH+IOFFST, JCH ),
00720      $                                  EXTRA, C, S, DUMMY )
00721                         END IF
00722                         IR = MAX( 1, IR )
00723                         IROW = MIN( M-1, JCH+JKL )
00724                         ILTEMP = JCH + JKL.LT.M
00725                         TEMP = ZERO
00726                         CALL SLAROT( .FALSE., ILEXTR, ILTEMP, IROW+2-IR,
00727      $                               C, S, A( IR-ISKEW*JCH+IOFFST,
00728      $                               JCH ), ILDA, EXTRA, TEMP )
00729                         IF( ILTEMP ) THEN
00730                            CALL SLARTG( A( IROW-ISKEW*JCH+IOFFST, JCH ),
00731      $                                  TEMP, C, S, DUMMY )
00732                            IL = MIN( IENDCH, JCH+JKL+JKU ) + 2 - JCH
00733                            EXTRA = ZERO
00734                            CALL SLAROT( .TRUE., .TRUE.,
00735      $                                  JCH+JKL+JKU.LE.IENDCH, IL, C, S,
00736      $                                  A( IROW-ISKEW*JCH+IOFFST, JCH ),
00737      $                                  ILDA, TEMP, EXTRA )
00738                            IR = IROW
00739                         END IF
00740   210                CONTINUE
00741   220             CONTINUE
00742   230          CONTINUE
00743             END IF
00744 *
00745          ELSE
00746 *
00747 *           Symmetric -- A = U D U'
00748 *
00749             IPACKG = IPACK
00750             IOFFG = IOFFST
00751 *
00752             IF( TOPDWN ) THEN
00753 *
00754 *              Top-Down -- Generate Upper triangle only
00755 *
00756                IF( IPACK.GE.5 ) THEN
00757                   IPACKG = 6
00758                   IOFFG = UUB + 1
00759                ELSE
00760                   IPACKG = 1
00761                END IF
00762                CALL SCOPY( MNMIN, D, 1, A( 1-ISKEW+IOFFG, 1 ), ILDA+1 )
00763 *
00764                DO 260 K = 1, UUB
00765                   DO 250 JC = 1, N - 1
00766                      IROW = MAX( 1, JC-K )
00767                      IL = MIN( JC+1, K+2 )
00768                      EXTRA = ZERO
00769                      TEMP = A( JC-ISKEW*( JC+1 )+IOFFG, JC+1 )
00770                      ANGLE = TWOPI*SLARND( 1, ISEED )
00771                      C = COS( ANGLE )
00772                      S = SIN( ANGLE )
00773                      CALL SLAROT( .FALSE., JC.GT.K, .TRUE., IL, C, S,
00774      $                            A( IROW-ISKEW*JC+IOFFG, JC ), ILDA,
00775      $                            EXTRA, TEMP )
00776                      CALL SLAROT( .TRUE., .TRUE., .FALSE.,
00777      $                            MIN( K, N-JC )+1, C, S,
00778      $                            A( ( 1-ISKEW )*JC+IOFFG, JC ), ILDA,
00779      $                            TEMP, DUMMY )
00780 *
00781 *                    Chase EXTRA back up the matrix
00782 *
00783                      ICOL = JC
00784                      DO 240 JCH = JC - K, 1, -K
00785                         CALL SLARTG( A( JCH+1-ISKEW*( ICOL+1 )+IOFFG,
00786      $                               ICOL+1 ), EXTRA, C, S, DUMMY )
00787                         TEMP = A( JCH-ISKEW*( JCH+1 )+IOFFG, JCH+1 )
00788                         CALL SLAROT( .TRUE., .TRUE., .TRUE., K+2, C, -S,
00789      $                               A( ( 1-ISKEW )*JCH+IOFFG, JCH ),
00790      $                               ILDA, TEMP, EXTRA )
00791                         IROW = MAX( 1, JCH-K )
00792                         IL = MIN( JCH+1, K+2 )
00793                         EXTRA = ZERO
00794                         CALL SLAROT( .FALSE., JCH.GT.K, .TRUE., IL, C,
00795      $                               -S, A( IROW-ISKEW*JCH+IOFFG, JCH ),
00796      $                               ILDA, EXTRA, TEMP )
00797                         ICOL = JCH
00798   240                CONTINUE
00799   250             CONTINUE
00800   260          CONTINUE
00801 *
00802 *              If we need lower triangle, copy from upper. Note that
00803 *              the order of copying is chosen to work for 'q' -> 'b'
00804 *
00805                IF( IPACK.NE.IPACKG .AND. IPACK.NE.3 ) THEN
00806                   DO 280 JC = 1, N
00807                      IROW = IOFFST - ISKEW*JC
00808                      DO 270 JR = JC, MIN( N, JC+UUB )
00809                         A( JR+IROW, JC ) = A( JC-ISKEW*JR+IOFFG, JR )
00810   270                CONTINUE
00811   280             CONTINUE
00812                   IF( IPACK.EQ.5 ) THEN
00813                      DO 300 JC = N - UUB + 1, N
00814                         DO 290 JR = N + 2 - JC, UUB + 1
00815                            A( JR, JC ) = ZERO
00816   290                   CONTINUE
00817   300                CONTINUE
00818                   END IF
00819                   IF( IPACKG.EQ.6 ) THEN
00820                      IPACKG = IPACK
00821                   ELSE
00822                      IPACKG = 0
00823                   END IF
00824                END IF
00825             ELSE
00826 *
00827 *              Bottom-Up -- Generate Lower triangle only
00828 *
00829                IF( IPACK.GE.5 ) THEN
00830                   IPACKG = 5
00831                   IF( IPACK.EQ.6 )
00832      $               IOFFG = 1
00833                ELSE
00834                   IPACKG = 2
00835                END IF
00836                CALL SCOPY( MNMIN, D, 1, A( 1-ISKEW+IOFFG, 1 ), ILDA+1 )
00837 *
00838                DO 330 K = 1, UUB
00839                   DO 320 JC = N - 1, 1, -1
00840                      IL = MIN( N+1-JC, K+2 )
00841                      EXTRA = ZERO
00842                      TEMP = A( 1+( 1-ISKEW )*JC+IOFFG, JC )
00843                      ANGLE = TWOPI*SLARND( 1, ISEED )
00844                      C = COS( ANGLE )
00845                      S = -SIN( ANGLE )
00846                      CALL SLAROT( .FALSE., .TRUE., N-JC.GT.K, IL, C, S,
00847      $                            A( ( 1-ISKEW )*JC+IOFFG, JC ), ILDA,
00848      $                            TEMP, EXTRA )
00849                      ICOL = MAX( 1, JC-K+1 )
00850                      CALL SLAROT( .TRUE., .FALSE., .TRUE., JC+2-ICOL, C,
00851      $                            S, A( JC-ISKEW*ICOL+IOFFG, ICOL ),
00852      $                            ILDA, DUMMY, TEMP )
00853 *
00854 *                    Chase EXTRA back down the matrix
00855 *
00856                      ICOL = JC
00857                      DO 310 JCH = JC + K, N - 1, K
00858                         CALL SLARTG( A( JCH-ISKEW*ICOL+IOFFG, ICOL ),
00859      $                               EXTRA, C, S, DUMMY )
00860                         TEMP = A( 1+( 1-ISKEW )*JCH+IOFFG, JCH )
00861                         CALL SLAROT( .TRUE., .TRUE., .TRUE., K+2, C, S,
00862      $                               A( JCH-ISKEW*ICOL+IOFFG, ICOL ),
00863      $                               ILDA, EXTRA, TEMP )
00864                         IL = MIN( N+1-JCH, K+2 )
00865                         EXTRA = ZERO
00866                         CALL SLAROT( .FALSE., .TRUE., N-JCH.GT.K, IL, C,
00867      $                               S, A( ( 1-ISKEW )*JCH+IOFFG, JCH ),
00868      $                               ILDA, TEMP, EXTRA )
00869                         ICOL = JCH
00870   310                CONTINUE
00871   320             CONTINUE
00872   330          CONTINUE
00873 *
00874 *              If we need upper triangle, copy from lower. Note that
00875 *              the order of copying is chosen to work for 'b' -> 'q'
00876 *
00877                IF( IPACK.NE.IPACKG .AND. IPACK.NE.4 ) THEN
00878                   DO 350 JC = N, 1, -1
00879                      IROW = IOFFST - ISKEW*JC
00880                      DO 340 JR = JC, MAX( 1, JC-UUB ), -1
00881                         A( JR+IROW, JC ) = A( JC-ISKEW*JR+IOFFG, JR )
00882   340                CONTINUE
00883   350             CONTINUE
00884                   IF( IPACK.EQ.6 ) THEN
00885                      DO 370 JC = 1, UUB
00886                         DO 360 JR = 1, UUB + 1 - JC
00887                            A( JR, JC ) = ZERO
00888   360                   CONTINUE
00889   370                CONTINUE
00890                   END IF
00891                   IF( IPACKG.EQ.5 ) THEN
00892                      IPACKG = IPACK
00893                   ELSE
00894                      IPACKG = 0
00895                   END IF
00896                END IF
00897             END IF
00898          END IF
00899 *
00900       ELSE
00901 *
00902 *        4)      Generate Banded Matrix by first
00903 *                Rotating by random Unitary matrices,
00904 *                then reducing the bandwidth using Householder
00905 *                transformations.
00906 *
00907 *                Note: we should get here only if LDA .ge. N
00908 *
00909          IF( ISYM.EQ.1 ) THEN
00910 *
00911 *           Non-symmetric -- A = U D V
00912 *
00913             CALL SLAGGE( MR, NC, LLB, UUB, D, A, LDA, ISEED, WORK,
00914      $                   IINFO )
00915          ELSE
00916 *
00917 *           Symmetric -- A = U D U'
00918 *
00919             CALL SLAGSY( M, LLB, D, A, LDA, ISEED, WORK, IINFO )
00920 *
00921          END IF
00922          IF( IINFO.NE.0 ) THEN
00923             INFO = 3
00924             RETURN
00925          END IF
00926       END IF
00927 *
00928 *     5)      Pack the matrix
00929 *
00930       IF( IPACK.NE.IPACKG ) THEN
00931          IF( IPACK.EQ.1 ) THEN
00932 *
00933 *           'U' -- Upper triangular, not packed
00934 *
00935             DO 390 J = 1, M
00936                DO 380 I = J + 1, M
00937                   A( I, J ) = ZERO
00938   380          CONTINUE
00939   390       CONTINUE
00940 *
00941          ELSE IF( IPACK.EQ.2 ) THEN
00942 *
00943 *           'L' -- Lower triangular, not packed
00944 *
00945             DO 410 J = 2, M
00946                DO 400 I = 1, J - 1
00947                   A( I, J ) = ZERO
00948   400          CONTINUE
00949   410       CONTINUE
00950 *
00951          ELSE IF( IPACK.EQ.3 ) THEN
00952 *
00953 *           'C' -- Upper triangle packed Columnwise.
00954 *
00955             ICOL = 1
00956             IROW = 0
00957             DO 430 J = 1, M
00958                DO 420 I = 1, J
00959                   IROW = IROW + 1
00960                   IF( IROW.GT.LDA ) THEN
00961                      IROW = 1
00962                      ICOL = ICOL + 1
00963                   END IF
00964                   A( IROW, ICOL ) = A( I, J )
00965   420          CONTINUE
00966   430       CONTINUE
00967 *
00968          ELSE IF( IPACK.EQ.4 ) THEN
00969 *
00970 *           'R' -- Lower triangle packed Columnwise.
00971 *
00972             ICOL = 1
00973             IROW = 0
00974             DO 450 J = 1, M
00975                DO 440 I = J, M
00976                   IROW = IROW + 1
00977                   IF( IROW.GT.LDA ) THEN
00978                      IROW = 1
00979                      ICOL = ICOL + 1
00980                   END IF
00981                   A( IROW, ICOL ) = A( I, J )
00982   440          CONTINUE
00983   450       CONTINUE
00984 *
00985          ELSE IF( IPACK.GE.5 ) THEN
00986 *
00987 *           'B' -- The lower triangle is packed as a band matrix.
00988 *           'Q' -- The upper triangle is packed as a band matrix.
00989 *           'Z' -- The whole matrix is packed as a band matrix.
00990 *
00991             IF( IPACK.EQ.5 )
00992      $         UUB = 0
00993             IF( IPACK.EQ.6 )
00994      $         LLB = 0
00995 *
00996             DO 470 J = 1, UUB
00997                DO 460 I = MIN( J+LLB, M ), 1, -1
00998                   A( I-J+UUB+1, J ) = A( I, J )
00999   460          CONTINUE
01000   470       CONTINUE
01001 *
01002             DO 490 J = UUB + 2, N
01003                DO 480 I = J - UUB, MIN( J+LLB, M )
01004                   A( I-J+UUB+1, J ) = A( I, J )
01005   480          CONTINUE
01006   490       CONTINUE
01007          END IF
01008 *
01009 *        If packed, zero out extraneous elements.
01010 *
01011 *        Symmetric/Triangular Packed --
01012 *        zero out everything after A(IROW,ICOL)
01013 *
01014          IF( IPACK.EQ.3 .OR. IPACK.EQ.4 ) THEN
01015             DO 510 JC = ICOL, M
01016                DO 500 JR = IROW + 1, LDA
01017                   A( JR, JC ) = ZERO
01018   500          CONTINUE
01019                IROW = 0
01020   510       CONTINUE
01021 *
01022          ELSE IF( IPACK.GE.5 ) THEN
01023 *
01024 *           Packed Band --
01025 *              1st row is now in A( UUB+2-j, j), zero above it
01026 *              m-th row is now in A( M+UUB-j,j), zero below it
01027 *              last non-zero diagonal is now in A( UUB+LLB+1,j ),
01028 *                 zero below it, too.
01029 *
01030             IR1 = UUB + LLB + 2
01031             IR2 = UUB + M + 2
01032             DO 540 JC = 1, N
01033                DO 520 JR = 1, UUB + 1 - JC
01034                   A( JR, JC ) = ZERO
01035   520          CONTINUE
01036                DO 530 JR = MAX( 1, MIN( IR1, IR2-JC ) ), LDA
01037                   A( JR, JC ) = ZERO
01038   530          CONTINUE
01039   540       CONTINUE
01040          END IF
01041       END IF
01042 *
01043       RETURN
01044 *
01045 *     End of SLATMT
01046 *
01047       END
 All Files Functions