LAPACK 3.3.0

zlatme.f

Go to the documentation of this file.
00001       SUBROUTINE ZLATME( N, DIST, ISEED, D, MODE, COND, DMAX, EI, 
00002      $  RSIGN, 
00003      $                   UPPER, SIM, DS, MODES, CONDS, KL, KU, ANORM, 
00004      $  A, 
00005      $                   LDA, WORK, INFO )
00006 *
00007 *  -- LAPACK test routine (version 3.1) --
00008 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
00009 *     June 2010
00010 *
00011 *     .. Scalar Arguments ..
00012       CHARACTER          DIST, EI, RSIGN, SIM, UPPER
00013       INTEGER            INFO, KL, KU, LDA, MODE, MODES, N
00014       DOUBLE PRECISION   ANORM, COND, CONDS
00015       COMPLEX*16         DMAX
00016 *     ..
00017 *     .. Array Arguments ..
00018       INTEGER            ISEED( 4 )
00019       DOUBLE PRECISION   DS( * )
00020       COMPLEX*16         A( LDA, * ), D( * ), WORK( * )
00021 *     ..
00022 *
00023 *  Purpose
00024 *  =======
00025 *
00026 *     ZLATME generates random non-symmetric square matrices with
00027 *     specified eigenvalues for testing LAPACK programs.
00028 *
00029 *     ZLATME operates by applying the following sequence of
00030 *     operations:
00031 *
00032 *     1. Set the diagonal to D, where D may be input or
00033 *          computed according to MODE, COND, DMAX, and RSIGN
00034 *          as described below.
00035 *
00036 *     2. If UPPER='T', the upper triangle of A is set to random values
00037 *          out of distribution DIST.
00038 *
00039 *     3. If SIM='T', A is multiplied on the left by a random matrix
00040 *          X, whose singular values are specified by DS, MODES, and
00041 *          CONDS, and on the right by X inverse.
00042 *
00043 *     4. If KL < N-1, the lower bandwidth is reduced to KL using
00044 *          Householder transformations.  If KU < N-1, the upper
00045 *          bandwidth is reduced to KU.
00046 *
00047 *     5. If ANORM is not negative, the matrix is scaled to have
00048 *          maximum-element-norm ANORM.
00049 *
00050 *     (Note: since the matrix cannot be reduced beyond Hessenberg form,
00051 *      no packing options are available.)
00052 *
00053 *  Arguments
00054 *  =========
00055 *
00056 *  N        (input) INTEGER
00057 *           The number of columns (or rows) of A. Not modified.
00058 *
00059 *  DIST     (input) CHARACTER*1
00060 *           On entry, DIST specifies the type of distribution to be used
00061 *           to generate the random eigen-/singular values, and on the
00062 *           upper triangle (see UPPER).
00063 *           'U' => UNIFORM( 0, 1 )  ( 'U' for uniform )
00064 *           'S' => UNIFORM( -1, 1 ) ( 'S' for symmetric )
00065 *           'N' => NORMAL( 0, 1 )   ( 'N' for normal )
00066 *           'D' => uniform on the complex disc |z| < 1.
00067 *           Not modified.
00068 *
00069 *  ISEED    (input/output) INTEGER array, dimension ( 4 )
00070 *           On entry ISEED specifies the seed of the random number
00071 *           generator. They should lie between 0 and 4095 inclusive,
00072 *           and ISEED(4) should be odd. The random number generator
00073 *           uses a linear congruential sequence limited to small
00074 *           integers, and so should produce machine independent
00075 *           random numbers. The values of ISEED are changed on
00076 *           exit, and can be used in the next call to ZLATME
00077 *           to continue the same random number sequence.
00078 *           Changed on exit.
00079 *
00080 *  D        (input/output) COMPLEX*16 array, dimension ( N )
00081 *           This array is used to specify the eigenvalues of A.  If
00082 *           MODE=0, then D is assumed to contain the eigenvalues
00083 *           otherwise they will be computed according to MODE, COND,
00084 *           DMAX, and RSIGN and placed in D.
00085 *           Modified if MODE is nonzero.
00086 *
00087 *  MODE     (input) INTEGER
00088 *           On entry this describes how the eigenvalues are to
00089 *           be specified:
00090 *           MODE = 0 means use D as input
00091 *           MODE = 1 sets D(1)=1 and D(2:N)=1.0/COND
00092 *           MODE = 2 sets D(1:N-1)=1 and D(N)=1.0/COND
00093 *           MODE = 3 sets D(I)=COND**(-(I-1)/(N-1))
00094 *           MODE = 4 sets D(i)=1 - (i-1)/(N-1)*(1 - 1/COND)
00095 *           MODE = 5 sets D to random numbers in the range
00096 *                    ( 1/COND , 1 ) such that their logarithms
00097 *                    are uniformly distributed.
00098 *           MODE = 6 set D to random numbers from same distribution
00099 *                    as the rest of the matrix.
00100 *           MODE < 0 has the same meaning as ABS(MODE), except that
00101 *              the order of the elements of D is reversed.
00102 *           Thus if MODE is between 1 and 4, D has entries ranging
00103 *              from 1 to 1/COND, if between -1 and -4, D has entries
00104 *              ranging from 1/COND to 1,
00105 *           Not modified.
00106 *
00107 *  COND     (input) DOUBLE PRECISION
00108 *           On entry, this is used as described under MODE above.
00109 *           If used, it must be >= 1. Not modified.
00110 *
00111 *  DMAX     (input) COMPLEX*16
00112 *           If MODE is neither -6, 0 nor 6, the contents of D, as
00113 *           computed according to MODE and COND, will be scaled by
00114 *           DMAX / max(abs(D(i))).  Note that DMAX need not be
00115 *           positive or real: if DMAX is negative or complex (or zero),
00116 *           D will be scaled by a negative or complex number (or zero).
00117 *           If RSIGN='F' then the largest (absolute) eigenvalue will be
00118 *           equal to DMAX.
00119 *           Not modified.
00120 *
00121 *  EI       (input) CHARACTER*1 array, dimension ( N )
00122 *           (ignored)
00123 *           Not modified.
00124 *
00125 *  RSIGN    (input) CHARACTER*1
00126 *           If MODE is not 0, 6, or -6, and RSIGN='T', then the
00127 *           elements of D, as computed according to MODE and COND, will
00128 *           be multiplied by a random complex number from the unit
00129 *           circle |z| = 1.  If RSIGN='F', they will not be.  RSIGN may
00130 *           only have the values 'T' or 'F'.
00131 *           Not modified.
00132 *
00133 *  UPPER    (input) CHARACTER*1
00134 *           If UPPER='T', then the elements of A above the diagonal
00135 *           will be set to random numbers out of DIST.  If UPPER='F',
00136 *           they will not.  UPPER may only have the values 'T' or 'F'.
00137 *           Not modified.
00138 *
00139 *  SIM      (input) CHARACTER*1
00140 *           If SIM='T', then A will be operated on by a "similarity
00141 *           transform", i.e., multiplied on the left by a matrix X and
00142 *           on the right by X inverse.  X = U S V, where U and V are
00143 *           random unitary matrices and S is a (diagonal) matrix of
00144 *           singular values specified by DS, MODES, and CONDS.  If
00145 *           SIM='F', then A will not be transformed.
00146 *           Not modified.
00147 *
00148 *  DS       (input/output) DOUBLE PRECISION array, dimension ( N )
00149 *           This array is used to specify the singular values of X,
00150 *           in the same way that D specifies the eigenvalues of A.
00151 *           If MODE=0, the DS contains the singular values, which
00152 *           may not be zero.
00153 *           Modified if MODE is nonzero.
00154 *
00155 *  MODES    (input) INTEGER
00156 *
00157 *  CONDS    (input) DOUBLE PRECISION
00158 *           Similar to MODE and COND, but for specifying the diagonal
00159 *           of S.  MODES=-6 and +6 are not allowed (since they would
00160 *           result in randomly ill-conditioned eigenvalues.)
00161 *
00162 *  KL       (input) INTEGER
00163 *           This specifies the lower bandwidth of the  matrix.  KL=1
00164 *           specifies upper Hessenberg form.  If KL is at least N-1,
00165 *           then A will have full lower bandwidth.
00166 *           Not modified.
00167 *
00168 *  KU       (input) INTEGER
00169 *           This specifies the upper bandwidth of the  matrix.  KU=1
00170 *           specifies lower Hessenberg form.  If KU is at least N-1,
00171 *           then A will have full upper bandwidth; if KU and KL
00172 *           are both at least N-1, then A will be dense.  Only one of
00173 *           KU and KL may be less than N-1.
00174 *           Not modified.
00175 *
00176 *  ANORM    (input) DOUBLE PRECISION
00177 *           If ANORM is not negative, then A will be scaled by a non-
00178 *           negative real number to make the maximum-element-norm of A
00179 *           to be ANORM.
00180 *           Not modified.
00181 *
00182 *  A        (output) COMPLEX*16 array, dimension ( LDA, N )
00183 *           On exit A is the desired test matrix.
00184 *           Modified.
00185 *
00186 *  LDA      (input) INTEGER
00187 *           LDA specifies the first dimension of A as declared in the
00188 *           calling program.  LDA must be at least M.
00189 *           Not modified.
00190 *
00191 *  WORK     (workspace) COMPLEX*16 array, dimension ( 3*N )
00192 *           Workspace.
00193 *           Modified.
00194 *
00195 *  INFO     (output) INTEGER
00196 *           Error code.  On exit, INFO will be set to one of the
00197 *           following values:
00198 *             0 => normal return
00199 *            -1 => N negative
00200 *            -2 => DIST illegal string
00201 *            -5 => MODE not in range -6 to 6
00202 *            -6 => COND less than 1.0, and MODE neither -6, 0 nor 6
00203 *            -9 => RSIGN is not 'T' or 'F'
00204 *           -10 => UPPER is not 'T' or 'F'
00205 *           -11 => SIM   is not 'T' or 'F'
00206 *           -12 => MODES=0 and DS has a zero singular value.
00207 *           -13 => MODES is not in the range -5 to 5.
00208 *           -14 => MODES is nonzero and CONDS is less than 1.
00209 *           -15 => KL is less than 1.
00210 *           -16 => KU is less than 1, or KL and KU are both less than
00211 *                  N-1.
00212 *           -19 => LDA is less than M.
00213 *            1  => Error return from ZLATM1 (computing D)
00214 *            2  => Cannot scale to DMAX (max. eigenvalue is 0)
00215 *            3  => Error return from DLATM1 (computing DS)
00216 *            4  => Error return from ZLARGE
00217 *            5  => Zero singular value from DLATM1.
00218 *
00219 *  =====================================================================
00220 *
00221 *     .. Parameters ..
00222       DOUBLE PRECISION   ZERO
00223       PARAMETER          ( ZERO = 0.0D+0 )
00224       DOUBLE PRECISION   ONE
00225       PARAMETER          ( ONE = 1.0D+0 )
00226       COMPLEX*16         CZERO
00227       PARAMETER          ( CZERO = ( 0.0D+0, 0.0D+0 ) )
00228       COMPLEX*16         CONE
00229       PARAMETER          ( CONE = ( 1.0D+0, 0.0D+0 ) )
00230 *     ..
00231 *     .. Local Scalars ..
00232       LOGICAL            BADS
00233       INTEGER            I, IC, ICOLS, IDIST, IINFO, IR, IROWS, IRSIGN,
00234      $                   ISIM, IUPPER, J, JC, JCR
00235       DOUBLE PRECISION   RALPHA, TEMP
00236       COMPLEX*16         ALPHA, TAU, XNORMS
00237 *     ..
00238 *     .. Local Arrays ..
00239       DOUBLE PRECISION   TEMPA( 1 )
00240 *     ..
00241 *     .. External Functions ..
00242       LOGICAL            LSAME
00243       DOUBLE PRECISION   ZLANGE
00244       COMPLEX*16         ZLARND
00245       EXTERNAL           LSAME, ZLANGE, ZLARND
00246 *     ..
00247 *     .. External Subroutines ..
00248       EXTERNAL           DLATM1, XERBLA, ZCOPY, ZDSCAL, ZGEMV, ZGERC,
00249      $                   ZLACGV, ZLARFG, ZLARGE, ZLARNV, ZLASET, ZLATM1,
00250      $                   ZSCAL
00251 *     ..
00252 *     .. Intrinsic Functions ..
00253       INTRINSIC          ABS, DCONJG, MAX, MOD
00254 *     ..
00255 *     .. Executable Statements ..
00256 *
00257 *     1)      Decode and Test the input parameters.
00258 *             Initialize flags & seed.
00259 *
00260       INFO = 0
00261 *
00262 *     Quick return if possible
00263 *
00264       IF( N.EQ.0 )
00265      $   RETURN
00266 *
00267 *     Decode DIST
00268 *
00269       IF( LSAME( DIST, 'U' ) ) THEN
00270          IDIST = 1
00271       ELSE IF( LSAME( DIST, 'S' ) ) THEN
00272          IDIST = 2
00273       ELSE IF( LSAME( DIST, 'N' ) ) THEN
00274          IDIST = 3
00275       ELSE IF( LSAME( DIST, 'D' ) ) THEN
00276          IDIST = 4
00277       ELSE
00278          IDIST = -1
00279       END IF
00280 *
00281 *     Decode RSIGN
00282 *
00283       IF( LSAME( RSIGN, 'T' ) ) THEN
00284          IRSIGN = 1
00285       ELSE IF( LSAME( RSIGN, 'F' ) ) THEN
00286          IRSIGN = 0
00287       ELSE
00288          IRSIGN = -1
00289       END IF
00290 *
00291 *     Decode UPPER
00292 *
00293       IF( LSAME( UPPER, 'T' ) ) THEN
00294          IUPPER = 1
00295       ELSE IF( LSAME( UPPER, 'F' ) ) THEN
00296          IUPPER = 0
00297       ELSE
00298          IUPPER = -1
00299       END IF
00300 *
00301 *     Decode SIM
00302 *
00303       IF( LSAME( SIM, 'T' ) ) THEN
00304          ISIM = 1
00305       ELSE IF( LSAME( SIM, 'F' ) ) THEN
00306          ISIM = 0
00307       ELSE
00308          ISIM = -1
00309       END IF
00310 *
00311 *     Check DS, if MODES=0 and ISIM=1
00312 *
00313       BADS = .FALSE.
00314       IF( MODES.EQ.0 .AND. ISIM.EQ.1 ) THEN
00315          DO 10 J = 1, N
00316             IF( DS( J ).EQ.ZERO )
00317      $         BADS = .TRUE.
00318    10    CONTINUE
00319       END IF
00320 *
00321 *     Set INFO if an error
00322 *
00323       IF( N.LT.0 ) THEN
00324          INFO = -1
00325       ELSE IF( IDIST.EQ.-1 ) THEN
00326          INFO = -2
00327       ELSE IF( ABS( MODE ).GT.6 ) THEN
00328          INFO = -5
00329       ELSE IF( ( MODE.NE.0 .AND. ABS( MODE ).NE.6 ) .AND. COND.LT.ONE )
00330      $          THEN
00331          INFO = -6
00332       ELSE IF( IRSIGN.EQ.-1 ) THEN
00333          INFO = -9
00334       ELSE IF( IUPPER.EQ.-1 ) THEN
00335          INFO = -10
00336       ELSE IF( ISIM.EQ.-1 ) THEN
00337          INFO = -11
00338       ELSE IF( BADS ) THEN
00339          INFO = -12
00340       ELSE IF( ISIM.EQ.1 .AND. ABS( MODES ).GT.5 ) THEN
00341          INFO = -13
00342       ELSE IF( ISIM.EQ.1 .AND. MODES.NE.0 .AND. CONDS.LT.ONE ) THEN
00343          INFO = -14
00344       ELSE IF( KL.LT.1 ) THEN
00345          INFO = -15
00346       ELSE IF( KU.LT.1 .OR. ( KU.LT.N-1 .AND. KL.LT.N-1 ) ) THEN
00347          INFO = -16
00348       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00349          INFO = -19
00350       END IF
00351 *
00352       IF( INFO.NE.0 ) THEN
00353          CALL XERBLA( 'ZLATME', -INFO )
00354          RETURN
00355       END IF
00356 *
00357 *     Initialize random number generator
00358 *
00359       DO 20 I = 1, 4
00360          ISEED( I ) = MOD( ABS( ISEED( I ) ), 4096 )
00361    20 CONTINUE
00362 *
00363       IF( MOD( ISEED( 4 ), 2 ).NE.1 )
00364      $   ISEED( 4 ) = ISEED( 4 ) + 1
00365 *
00366 *     2)      Set up diagonal of A
00367 *
00368 *             Compute D according to COND and MODE
00369 *
00370       CALL ZLATM1( MODE, COND, IRSIGN, IDIST, ISEED, D, N, IINFO )
00371       IF( IINFO.NE.0 ) THEN
00372          INFO = 1
00373          RETURN
00374       END IF
00375       IF( MODE.NE.0 .AND. ABS( MODE ).NE.6 ) THEN
00376 *
00377 *        Scale by DMAX
00378 *
00379          TEMP = ABS( D( 1 ) )
00380          DO 30 I = 2, N
00381             TEMP = MAX( TEMP, ABS( D( I ) ) )
00382    30    CONTINUE
00383 *
00384          IF( TEMP.GT.ZERO ) THEN
00385             ALPHA = DMAX / TEMP
00386          ELSE
00387             INFO = 2
00388             RETURN
00389          END IF
00390 *
00391          CALL ZSCAL( N, ALPHA, D, 1 )
00392 *
00393       END IF
00394 *
00395       CALL ZLASET( 'Full', N, N, CZERO, CZERO, A, LDA )
00396       CALL ZCOPY( N, D, 1, A, LDA+1 )
00397 *
00398 *     3)      If UPPER='T', set upper triangle of A to random numbers.
00399 *
00400       IF( IUPPER.NE.0 ) THEN
00401          DO 40 JC = 2, N
00402             CALL ZLARNV( IDIST, ISEED, JC-1, A( 1, JC ) )
00403    40    CONTINUE
00404       END IF
00405 *
00406 *     4)      If SIM='T', apply similarity transformation.
00407 *
00408 *                                -1
00409 *             Transform is  X A X  , where X = U S V, thus
00410 *
00411 *             it is  U S V A V' (1/S) U'
00412 *
00413       IF( ISIM.NE.0 ) THEN
00414 *
00415 *        Compute S (singular values of the eigenvector matrix)
00416 *        according to CONDS and MODES
00417 *
00418          CALL DLATM1( MODES, CONDS, 0, 0, ISEED, DS, N, IINFO )
00419          IF( IINFO.NE.0 ) THEN
00420             INFO = 3
00421             RETURN
00422          END IF
00423 *
00424 *        Multiply by V and V'
00425 *
00426          CALL ZLARGE( N, A, LDA, ISEED, WORK, IINFO )
00427          IF( IINFO.NE.0 ) THEN
00428             INFO = 4
00429             RETURN
00430          END IF
00431 *
00432 *        Multiply by S and (1/S)
00433 *
00434          DO 50 J = 1, N
00435             CALL ZDSCAL( N, DS( J ), A( J, 1 ), LDA )
00436             IF( DS( J ).NE.ZERO ) THEN
00437                CALL ZDSCAL( N, ONE / DS( J ), A( 1, J ), 1 )
00438             ELSE
00439                INFO = 5
00440                RETURN
00441             END IF
00442    50    CONTINUE
00443 *
00444 *        Multiply by U and U'
00445 *
00446          CALL ZLARGE( N, A, LDA, ISEED, WORK, IINFO )
00447          IF( IINFO.NE.0 ) THEN
00448             INFO = 4
00449             RETURN
00450          END IF
00451       END IF
00452 *
00453 *     5)      Reduce the bandwidth.
00454 *
00455       IF( KL.LT.N-1 ) THEN
00456 *
00457 *        Reduce bandwidth -- kill column
00458 *
00459          DO 60 JCR = KL + 1, N - 1
00460             IC = JCR - KL
00461             IROWS = N + 1 - JCR
00462             ICOLS = N + KL - JCR
00463 *
00464             CALL ZCOPY( IROWS, A( JCR, IC ), 1, WORK, 1 )
00465             XNORMS = WORK( 1 )
00466             CALL ZLARFG( IROWS, XNORMS, WORK( 2 ), 1, TAU )
00467             TAU = DCONJG( TAU )
00468             WORK( 1 ) = CONE
00469             ALPHA = ZLARND( 5, ISEED )
00470 *
00471             CALL ZGEMV( 'C', IROWS, ICOLS, CONE, A( JCR, IC+1 ), LDA,
00472      $                  WORK, 1, CZERO, WORK( IROWS+1 ), 1 )
00473             CALL ZGERC( IROWS, ICOLS, -TAU, WORK, 1, WORK( IROWS+1 ), 1,
00474      $                  A( JCR, IC+1 ), LDA )
00475 *
00476             CALL ZGEMV( 'N', N, IROWS, CONE, A( 1, JCR ), LDA, WORK, 1,
00477      $                  CZERO, WORK( IROWS+1 ), 1 )
00478             CALL ZGERC( N, IROWS, -DCONJG( TAU ), WORK( IROWS+1 ), 1,
00479      $                  WORK, 1, A( 1, JCR ), LDA )
00480 *
00481             A( JCR, IC ) = XNORMS
00482             CALL ZLASET( 'Full', IROWS-1, 1, CZERO, CZERO,
00483      $                   A( JCR+1, IC ), LDA )
00484 *
00485             CALL ZSCAL( ICOLS+1, ALPHA, A( JCR, IC ), LDA )
00486             CALL ZSCAL( N, DCONJG( ALPHA ), A( 1, JCR ), 1 )
00487    60    CONTINUE
00488       ELSE IF( KU.LT.N-1 ) THEN
00489 *
00490 *        Reduce upper bandwidth -- kill a row at a time.
00491 *
00492          DO 70 JCR = KU + 1, N - 1
00493             IR = JCR - KU
00494             IROWS = N + KU - JCR
00495             ICOLS = N + 1 - JCR
00496 *
00497             CALL ZCOPY( ICOLS, A( IR, JCR ), LDA, WORK, 1 )
00498             XNORMS = WORK( 1 )
00499             CALL ZLARFG( ICOLS, XNORMS, WORK( 2 ), 1, TAU )
00500             TAU = DCONJG( TAU )
00501             WORK( 1 ) = CONE
00502             CALL ZLACGV( ICOLS-1, WORK( 2 ), 1 )
00503             ALPHA = ZLARND( 5, ISEED )
00504 *
00505             CALL ZGEMV( 'N', IROWS, ICOLS, CONE, A( IR+1, JCR ), LDA,
00506      $                  WORK, 1, CZERO, WORK( ICOLS+1 ), 1 )
00507             CALL ZGERC( IROWS, ICOLS, -TAU, WORK( ICOLS+1 ), 1, WORK, 1,
00508      $                  A( IR+1, JCR ), LDA )
00509 *
00510             CALL ZGEMV( 'C', ICOLS, N, CONE, A( JCR, 1 ), LDA, WORK, 1,
00511      $                  CZERO, WORK( ICOLS+1 ), 1 )
00512             CALL ZGERC( ICOLS, N, -DCONJG( TAU ), WORK, 1,
00513      $                  WORK( ICOLS+1 ), 1, A( JCR, 1 ), LDA )
00514 *
00515             A( IR, JCR ) = XNORMS
00516             CALL ZLASET( 'Full', 1, ICOLS-1, CZERO, CZERO,
00517      $                   A( IR, JCR+1 ), LDA )
00518 *
00519             CALL ZSCAL( IROWS+1, ALPHA, A( IR, JCR ), 1 )
00520             CALL ZSCAL( N, DCONJG( ALPHA ), A( JCR, 1 ), LDA )
00521    70    CONTINUE
00522       END IF
00523 *
00524 *     Scale the matrix to have norm ANORM
00525 *
00526       IF( ANORM.GE.ZERO ) THEN
00527          TEMP = ZLANGE( 'M', N, N, A, LDA, TEMPA )
00528          IF( TEMP.GT.ZERO ) THEN
00529             RALPHA = ANORM / TEMP
00530             DO 80 J = 1, N
00531                CALL ZDSCAL( N, RALPHA, A( 1, J ), 1 )
00532    80       CONTINUE
00533          END IF
00534       END IF
00535 *
00536       RETURN
00537 *
00538 *     End of ZLATME
00539 *
00540       END
 All Files Functions