LAPACK 3.3.1
Linear Algebra PACKage

cdrvbd.f

Go to the documentation of this file.
00001       SUBROUTINE CDRVBD( NSIZES, MM, NN, NTYPES, DOTYPE, ISEED, THRESH,
00002      $                   A, LDA, U, LDU, VT, LDVT, ASAV, USAV, VTSAV, S,
00003      $                   SSAV, E, WORK, LWORK, RWORK, IWORK, NOUNIT,
00004      $                   INFO )
00005 *
00006 *  -- LAPACK test routine (version 3.1) --
00007 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
00008 *     November 2006
00009 *
00010 *     .. Scalar Arguments ..
00011       INTEGER            INFO, LDA, LDU, LDVT, LWORK, NOUNIT, NSIZES,
00012      $                   NTYPES
00013       REAL               THRESH
00014 *     ..
00015 *     .. Array Arguments ..
00016       LOGICAL            DOTYPE( * )
00017       INTEGER            ISEED( 4 ), IWORK( * ), MM( * ), NN( * )
00018       REAL               E( * ), RWORK( * ), S( * ), SSAV( * )
00019       COMPLEX            A( LDA, * ), ASAV( LDA, * ), U( LDU, * ),
00020      $                   USAV( LDU, * ), VT( LDVT, * ),
00021      $                   VTSAV( LDVT, * ), WORK( * )
00022 *     ..
00023 *
00024 *  Purpose
00025 *  =======
00026 *
00027 *  CDRVBD checks the singular value decomposition (SVD) driver CGESVD
00028 *  and CGESDD.
00029 *  CGESVD and CGESDD factors A = U diag(S) VT, where U and VT are
00030 *  unitary and diag(S) is diagonal with the entries of the array S on
00031 *  its diagonal. The entries of S are the singular values, nonnegative
00032 *  and stored in decreasing order.  U and VT can be optionally not
00033 *  computed, overwritten on A, or computed partially.
00034 *
00035 *  A is M by N. Let MNMIN = min( M, N ). S has dimension MNMIN.
00036 *  U can be M by M or M by MNMIN. VT can be N by N or MNMIN by N.
00037 *
00038 *  When CDRVBD is called, a number of matrix "sizes" (M's and N's)
00039 *  and a number of matrix "types" are specified.  For each size (M,N)
00040 *  and each type of matrix, and for the minimal workspace as well as
00041 *  workspace adequate to permit blocking, an  M x N  matrix "A" will be
00042 *  generated and used to test the SVD routines.  For each matrix, A will
00043 *  be factored as A = U diag(S) VT and the following 12 tests computed:
00044 *
00045 *  Test for CGESVD:
00046 *
00047 *  (1)   | A - U diag(S) VT | / ( |A| max(M,N) ulp )
00048 *
00049 *  (2)   | I - U'U | / ( M ulp )
00050 *
00051 *  (3)   | I - VT VT' | / ( N ulp )
00052 *
00053 *  (4)   S contains MNMIN nonnegative values in decreasing order.
00054 *        (Return 0 if true, 1/ULP if false.)
00055 *
00056 *  (5)   | U - Upartial | / ( M ulp ) where Upartial is a partially
00057 *        computed U.
00058 *
00059 *  (6)   | VT - VTpartial | / ( N ulp ) where VTpartial is a partially
00060 *        computed VT.
00061 *
00062 *  (7)   | S - Spartial | / ( MNMIN ulp |S| ) where Spartial is the
00063 *        vector of singular values from the partial SVD
00064 *
00065 *  Test for CGESDD:
00066 *
00067 *  (1)   | A - U diag(S) VT | / ( |A| max(M,N) ulp )
00068 *
00069 *  (2)   | I - U'U | / ( M ulp )
00070 *
00071 *  (3)   | I - VT VT' | / ( N ulp )
00072 *
00073 *  (4)   S contains MNMIN nonnegative values in decreasing order.
00074 *        (Return 0 if true, 1/ULP if false.)
00075 *
00076 *  (5)   | U - Upartial | / ( M ulp ) where Upartial is a partially
00077 *        computed U.
00078 *
00079 *  (6)   | VT - VTpartial | / ( N ulp ) where VTpartial is a partially
00080 *        computed VT.
00081 *
00082 *  (7)   | S - Spartial | / ( MNMIN ulp |S| ) where Spartial is the
00083 *        vector of singular values from the partial SVD
00084 *
00085 *  The "sizes" are specified by the arrays MM(1:NSIZES) and
00086 *  NN(1:NSIZES); the value of each element pair (MM(j),NN(j))
00087 *  specifies one size.  The "types" are specified by a logical array
00088 *  DOTYPE( 1:NTYPES ); if DOTYPE(j) is .TRUE., then matrix type "j"
00089 *  will be generated.
00090 *  Currently, the list of possible types is:
00091 *
00092 *  (1)  The zero matrix.
00093 *  (2)  The identity matrix.
00094 *  (3)  A matrix of the form  U D V, where U and V are unitary and
00095 *       D has evenly spaced entries 1, ..., ULP with random signs
00096 *       on the diagonal.
00097 *  (4)  Same as (3), but multiplied by the underflow-threshold / ULP.
00098 *  (5)  Same as (3), but multiplied by the overflow-threshold * ULP.
00099 *
00100 *  Arguments
00101 *  ==========
00102 *
00103 *  NSIZES  (input) INTEGER
00104 *          The number of sizes of matrices to use.  If it is zero,
00105 *          CDRVBD does nothing.  It must be at least zero.
00106 *
00107 *  MM      (input) INTEGER array, dimension (NSIZES)
00108 *          An array containing the matrix "heights" to be used.  For
00109 *          each j=1,...,NSIZES, if MM(j) is zero, then MM(j) and NN(j)
00110 *          will be ignored.  The MM(j) values must be at least zero.
00111 *
00112 *  NN      (input) INTEGER array, dimension (NSIZES)
00113 *          An array containing the matrix "widths" to be used.  For
00114 *          each j=1,...,NSIZES, if NN(j) is zero, then MM(j) and NN(j)
00115 *          will be ignored.  The NN(j) values must be at least zero.
00116 *
00117 *  NTYPES  (input) INTEGER
00118 *          The number of elements in DOTYPE.   If it is zero, CDRVBD
00119 *          does nothing.  It must be at least zero.  If it is MAXTYP+1
00120 *          and NSIZES is 1, then an additional type, MAXTYP+1 is
00121 *          defined, which is to use whatever matrices are in A and B.
00122 *          This is only useful if DOTYPE(1:MAXTYP) is .FALSE. and
00123 *          DOTYPE(MAXTYP+1) is .TRUE. .
00124 *
00125 *  DOTYPE  (input) LOGICAL array, dimension (NTYPES)
00126 *          If DOTYPE(j) is .TRUE., then for each size (m,n), a matrix
00127 *          of type j will be generated.  If NTYPES is smaller than the
00128 *          maximum number of types defined (PARAMETER MAXTYP), then
00129 *          types NTYPES+1 through MAXTYP will not be generated.  If
00130 *          NTYPES is larger than MAXTYP, DOTYPE(MAXTYP+1) through
00131 *          DOTYPE(NTYPES) will be ignored.
00132 *
00133 *  ISEED   (input/output) INTEGER array, dimension (4)
00134 *          On entry ISEED specifies the seed of the random number
00135 *          generator. The array elements should be between 0 and 4095;
00136 *          if not they will be reduced mod 4096.  Also, ISEED(4) must
00137 *          be odd.  The random number generator uses a linear
00138 *          congruential sequence limited to small integers, and so
00139 *          should produce machine independent random numbers. The
00140 *          values of ISEED are changed on exit, and can be used in the
00141 *          next call to CDRVBD to continue the same random number
00142 *          sequence.
00143 *
00144 *  THRESH  (input) REAL
00145 *          A test will count as "failed" if the "error", computed as
00146 *          described above, exceeds THRESH.  Note that the error
00147 *          is scaled to be O(1), so THRESH should be a reasonably
00148 *          small multiple of 1, e.g., 10 or 100.  In particular,
00149 *          it should not depend on the precision (single vs. double)
00150 *          or the size of the matrix.  It must be at least zero.
00151 *
00152 *  NOUNIT  (input) INTEGER
00153 *          The FORTRAN unit number for printing out error messages
00154 *          (e.g., if a routine returns IINFO not equal to 0.)
00155 *
00156 *  A       (output) COMPLEX array, dimension (LDA,max(NN))
00157 *          Used to hold the matrix whose singular values are to be
00158 *          computed.  On exit, A contains the last matrix actually
00159 *          used.
00160 *
00161 *  LDA     (input) INTEGER
00162 *          The leading dimension of A.  It must be at
00163 *          least 1 and at least max( MM ).
00164 *
00165 *  U       (output) COMPLEX array, dimension (LDU,max(MM))
00166 *          Used to hold the computed matrix of right singular vectors.
00167 *          On exit, U contains the last such vectors actually computed.
00168 *
00169 *  LDU     (input) INTEGER
00170 *          The leading dimension of U.  It must be at
00171 *          least 1 and at least max( MM ).
00172 *
00173 *  VT      (output) COMPLEX array, dimension (LDVT,max(NN))
00174 *          Used to hold the computed matrix of left singular vectors.
00175 *          On exit, VT contains the last such vectors actually computed.
00176 *
00177 *  LDVT    (input) INTEGER
00178 *          The leading dimension of VT.  It must be at
00179 *          least 1 and at least max( NN ).
00180 *
00181 *  ASAV    (output) COMPLEX array, dimension (LDA,max(NN))
00182 *          Used to hold a different copy of the matrix whose singular
00183 *          values are to be computed.  On exit, A contains the last
00184 *          matrix actually used.
00185 *
00186 *  USAV    (output) COMPLEX array, dimension (LDU,max(MM))
00187 *          Used to hold a different copy of the computed matrix of
00188 *          right singular vectors. On exit, USAV contains the last such
00189 *          vectors actually computed.
00190 *
00191 *  VTSAV   (output) COMPLEX array, dimension (LDVT,max(NN))
00192 *          Used to hold a different copy of the computed matrix of
00193 *          left singular vectors. On exit, VTSAV contains the last such
00194 *          vectors actually computed.
00195 *
00196 *  S       (output) REAL array, dimension (max(min(MM,NN)))
00197 *          Contains the computed singular values.
00198 *
00199 *  SSAV    (output) REAL array, dimension (max(min(MM,NN)))
00200 *          Contains another copy of the computed singular values.
00201 *
00202 *  E       (output) REAL array, dimension (max(min(MM,NN)))
00203 *          Workspace for CGESVD.
00204 *
00205 *  WORK    (workspace) COMPLEX array, dimension (LWORK)
00206 *
00207 *  LWORK   (input) INTEGER
00208 *          The number of entries in WORK.  This must be at least
00209 *          MAX(3*MIN(M,N)+MAX(M,N)**2,5*MIN(M,N),3*MAX(M,N)) for all
00210 *          pairs  (M,N)=(MM(j),NN(j))
00211 *
00212 *  RWORK   (workspace) REAL array,
00213 *                      dimension ( 5*max(max(MM,NN)) )
00214 *
00215 *  IWORK   (workspace) INTEGER array, dimension at least 8*min(M,N)
00216 *
00217 *  RESULT  (output) REAL array, dimension (7)
00218 *          The values computed by the 7 tests described above.
00219 *          The values are currently limited to 1/ULP, to avoid
00220 *          overflow.
00221 *
00222 *  INFO    (output) INTEGER
00223 *          If 0, then everything ran OK.
00224 *           -1: NSIZES < 0
00225 *           -2: Some MM(j) < 0
00226 *           -3: Some NN(j) < 0
00227 *           -4: NTYPES < 0
00228 *           -7: THRESH < 0
00229 *          -10: LDA < 1 or LDA < MMAX, where MMAX is max( MM(j) ).
00230 *          -12: LDU < 1 or LDU < MMAX.
00231 *          -14: LDVT < 1 or LDVT < NMAX, where NMAX is max( NN(j) ).
00232 *          -21: LWORK too small.
00233 *          If  CLATMS, or CGESVD returns an error code, the
00234 *              absolute value of it is returned.
00235 *
00236 *  =====================================================================
00237 *
00238 *     .. Parameters ..
00239       REAL               ZERO, ONE
00240       PARAMETER          ( ZERO = 0.0E+0, ONE = 1.0E+0 )
00241       COMPLEX            CZERO, CONE
00242       PARAMETER          ( CZERO = ( 0.0E+0, 0.0E+0 ),
00243      $                   CONE = ( 1.0E+0, 0.0E+0 ) )
00244       INTEGER            MAXTYP
00245       PARAMETER          ( MAXTYP = 5 )
00246 *     ..
00247 *     .. Local Scalars ..
00248       LOGICAL            BADMM, BADNN
00249       CHARACTER          JOBQ, JOBU, JOBVT
00250       INTEGER            I, IINFO, IJQ, IJU, IJVT, IWSPC, IWTMP, J,
00251      $                   JSIZE, JTYPE, LSWORK, M, MINWRK, MMAX, MNMAX,
00252      $                   MNMIN, MTYPES, N, NERRS, NFAIL, NMAX, NTEST,
00253      $                   NTESTF, NTESTT
00254       REAL               ANORM, DIF, DIV, OVFL, ULP, ULPINV, UNFL
00255 *     ..
00256 *     .. Local Arrays ..
00257       CHARACTER          CJOB( 4 )
00258       INTEGER            IOLDSD( 4 )
00259       REAL               RESULT( 14 )
00260 *     ..
00261 *     .. External Functions ..
00262       REAL               SLAMCH
00263       EXTERNAL           SLAMCH
00264 *     ..
00265 *     .. External Subroutines ..
00266       EXTERNAL           ALASVM, CBDT01, CGESDD, CGESVD, CLACPY, CLASET,
00267      $                   CLATMS, CUNT01, CUNT03, XERBLA
00268 *     ..
00269 *     .. Intrinsic Functions ..
00270       INTRINSIC          ABS, MAX, MIN, REAL
00271 *     ..
00272 *     .. Data statements ..
00273       DATA               CJOB / 'N', 'O', 'S', 'A' /
00274 *     ..
00275 *     .. Executable Statements ..
00276 *
00277 *     Check for errors
00278 *
00279       INFO = 0
00280 *
00281 *     Important constants
00282 *
00283       NERRS = 0
00284       NTESTT = 0
00285       NTESTF = 0
00286       BADMM = .FALSE.
00287       BADNN = .FALSE.
00288       MMAX = 1
00289       NMAX = 1
00290       MNMAX = 1
00291       MINWRK = 1
00292       DO 10 J = 1, NSIZES
00293          MMAX = MAX( MMAX, MM( J ) )
00294          IF( MM( J ).LT.0 )
00295      $      BADMM = .TRUE.
00296          NMAX = MAX( NMAX, NN( J ) )
00297          IF( NN( J ).LT.0 )
00298      $      BADNN = .TRUE.
00299          MNMAX = MAX( MNMAX, MIN( MM( J ), NN( J ) ) )
00300          MINWRK = MAX( MINWRK, MAX( 3*MIN( MM( J ),
00301      $            NN( J ) )+MAX( MM( J ), NN( J ) )**2, 5*MIN( MM( J ),
00302      $            NN( J ) ), 3*MAX( MM( J ), NN( J ) ) ) )
00303    10 CONTINUE
00304 *
00305 *     Check for errors
00306 *
00307       IF( NSIZES.LT.0 ) THEN
00308          INFO = -1
00309       ELSE IF( BADMM ) THEN
00310          INFO = -2
00311       ELSE IF( BADNN ) THEN
00312          INFO = -3
00313       ELSE IF( NTYPES.LT.0 ) THEN
00314          INFO = -4
00315       ELSE IF( LDA.LT.MAX( 1, MMAX ) ) THEN
00316          INFO = -10
00317       ELSE IF( LDU.LT.MAX( 1, MMAX ) ) THEN
00318          INFO = -12
00319       ELSE IF( LDVT.LT.MAX( 1, NMAX ) ) THEN
00320          INFO = -14
00321       ELSE IF( MINWRK.GT.LWORK ) THEN
00322          INFO = -21
00323       END IF
00324 *
00325       IF( INFO.NE.0 ) THEN
00326          CALL XERBLA( 'CDRVBD', -INFO )
00327          RETURN
00328       END IF
00329 *
00330 *     Quick return if nothing to do
00331 *
00332       IF( NSIZES.EQ.0 .OR. NTYPES.EQ.0 )
00333      $   RETURN
00334 *
00335 *     More Important constants
00336 *
00337       UNFL = SLAMCH( 'S' )
00338       OVFL = ONE / UNFL
00339       ULP = SLAMCH( 'E' )
00340       ULPINV = ONE / ULP
00341 *
00342 *     Loop over sizes, types
00343 *
00344       NERRS = 0
00345 *
00346       DO 180 JSIZE = 1, NSIZES
00347          M = MM( JSIZE )
00348          N = NN( JSIZE )
00349          MNMIN = MIN( M, N )
00350 *
00351          IF( NSIZES.NE.1 ) THEN
00352             MTYPES = MIN( MAXTYP, NTYPES )
00353          ELSE
00354             MTYPES = MIN( MAXTYP+1, NTYPES )
00355          END IF
00356 *
00357          DO 170 JTYPE = 1, MTYPES
00358             IF( .NOT.DOTYPE( JTYPE ) )
00359      $         GO TO 170
00360             NTEST = 0
00361 *
00362             DO 20 J = 1, 4
00363                IOLDSD( J ) = ISEED( J )
00364    20       CONTINUE
00365 *
00366 *           Compute "A"
00367 *
00368             IF( MTYPES.GT.MAXTYP )
00369      $         GO TO 50
00370 *
00371             IF( JTYPE.EQ.1 ) THEN
00372 *
00373 *              Zero matrix
00374 *
00375                CALL CLASET( 'Full', M, N, CZERO, CZERO, A, LDA )
00376                DO 30 I = 1, MIN( M, N )
00377                   S( I ) = ZERO
00378    30          CONTINUE
00379 *
00380             ELSE IF( JTYPE.EQ.2 ) THEN
00381 *
00382 *              Identity matrix
00383 *
00384                CALL CLASET( 'Full', M, N, CZERO, CONE, A, LDA )
00385                DO 40 I = 1, MIN( M, N )
00386                   S( I ) = ONE
00387    40          CONTINUE
00388 *
00389             ELSE
00390 *
00391 *              (Scaled) random matrix
00392 *
00393                IF( JTYPE.EQ.3 )
00394      $            ANORM = ONE
00395                IF( JTYPE.EQ.4 )
00396      $            ANORM = UNFL / ULP
00397                IF( JTYPE.EQ.5 )
00398      $            ANORM = OVFL*ULP
00399                CALL CLATMS( M, N, 'U', ISEED, 'N', S, 4, REAL( MNMIN ),
00400      $                      ANORM, M-1, N-1, 'N', A, LDA, WORK, IINFO )
00401                IF( IINFO.NE.0 ) THEN
00402                   WRITE( NOUNIT, FMT = 9996 )'Generator', IINFO, M, N,
00403      $               JTYPE, IOLDSD
00404                   INFO = ABS( IINFO )
00405                   RETURN
00406                END IF
00407             END IF
00408 *
00409    50       CONTINUE
00410             CALL CLACPY( 'F', M, N, A, LDA, ASAV, LDA )
00411 *
00412 *           Do for minimal and adequate (for blocking) workspace
00413 *
00414             DO 160 IWSPC = 1, 4
00415 *
00416 *              Test for CGESVD
00417 *
00418                IWTMP = 2*MIN( M, N )+MAX( M, N )
00419                LSWORK = IWTMP + ( IWSPC-1 )*( LWORK-IWTMP ) / 3
00420                LSWORK = MIN( LSWORK, LWORK )
00421                LSWORK = MAX( LSWORK, 1 )
00422                IF( IWSPC.EQ.4 )
00423      $            LSWORK = LWORK
00424 *
00425                DO 60 J = 1, 14
00426                   RESULT( J ) = -ONE
00427    60          CONTINUE
00428 *
00429 *              Factorize A
00430 *
00431                IF( IWSPC.GT.1 )
00432      $            CALL CLACPY( 'F', M, N, ASAV, LDA, A, LDA )
00433                CALL CGESVD( 'A', 'A', M, N, A, LDA, SSAV, USAV, LDU,
00434      $                      VTSAV, LDVT, WORK, LSWORK, RWORK, IINFO )
00435                IF( IINFO.NE.0 ) THEN
00436                   WRITE( NOUNIT, FMT = 9995 )'GESVD', IINFO, M, N,
00437      $               JTYPE, LSWORK, IOLDSD
00438                   INFO = ABS( IINFO )
00439                   RETURN
00440                END IF
00441 *
00442 *              Do tests 1--4
00443 *
00444                CALL CBDT01( M, N, 0, ASAV, LDA, USAV, LDU, SSAV, E,
00445      $                      VTSAV, LDVT, WORK, RWORK, RESULT( 1 ) )
00446                IF( M.NE.0 .AND. N.NE.0 ) THEN
00447                   CALL CUNT01( 'Columns', MNMIN, M, USAV, LDU, WORK,
00448      $                         LWORK, RWORK, RESULT( 2 ) )
00449                   CALL CUNT01( 'Rows', MNMIN, N, VTSAV, LDVT, WORK,
00450      $                         LWORK, RWORK, RESULT( 3 ) )
00451                END IF
00452                RESULT( 4 ) = 0
00453                DO 70 I = 1, MNMIN - 1
00454                   IF( SSAV( I ).LT.SSAV( I+1 ) )
00455      $               RESULT( 4 ) = ULPINV
00456                   IF( SSAV( I ).LT.ZERO )
00457      $               RESULT( 4 ) = ULPINV
00458    70          CONTINUE
00459                IF( MNMIN.GE.1 ) THEN
00460                   IF( SSAV( MNMIN ).LT.ZERO )
00461      $               RESULT( 4 ) = ULPINV
00462                END IF
00463 *
00464 *              Do partial SVDs, comparing to SSAV, USAV, and VTSAV
00465 *
00466                RESULT( 5 ) = ZERO
00467                RESULT( 6 ) = ZERO
00468                RESULT( 7 ) = ZERO
00469                DO 100 IJU = 0, 3
00470                   DO 90 IJVT = 0, 3
00471                      IF( ( IJU.EQ.3 .AND. IJVT.EQ.3 ) .OR.
00472      $                   ( IJU.EQ.1 .AND. IJVT.EQ.1 ) )GO TO 90
00473                      JOBU = CJOB( IJU+1 )
00474                      JOBVT = CJOB( IJVT+1 )
00475                      CALL CLACPY( 'F', M, N, ASAV, LDA, A, LDA )
00476                      CALL CGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU,
00477      $                            VT, LDVT, WORK, LSWORK, RWORK, IINFO )
00478 *
00479 *                    Compare U
00480 *
00481                      DIF = ZERO
00482                      IF( M.GT.0 .AND. N.GT.0 ) THEN
00483                         IF( IJU.EQ.1 ) THEN
00484                            CALL CUNT03( 'C', M, MNMIN, M, MNMIN, USAV,
00485      $                                  LDU, A, LDA, WORK, LWORK, RWORK,
00486      $                                  DIF, IINFO )
00487                         ELSE IF( IJU.EQ.2 ) THEN
00488                            CALL CUNT03( 'C', M, MNMIN, M, MNMIN, USAV,
00489      $                                  LDU, U, LDU, WORK, LWORK, RWORK,
00490      $                                  DIF, IINFO )
00491                         ELSE IF( IJU.EQ.3 ) THEN
00492                            CALL CUNT03( 'C', M, M, M, MNMIN, USAV, LDU,
00493      $                                  U, LDU, WORK, LWORK, RWORK, DIF,
00494      $                                  IINFO )
00495                         END IF
00496                      END IF
00497                      RESULT( 5 ) = MAX( RESULT( 5 ), DIF )
00498 *
00499 *                    Compare VT
00500 *
00501                      DIF = ZERO
00502                      IF( M.GT.0 .AND. N.GT.0 ) THEN
00503                         IF( IJVT.EQ.1 ) THEN
00504                            CALL CUNT03( 'R', N, MNMIN, N, MNMIN, VTSAV,
00505      $                                  LDVT, A, LDA, WORK, LWORK,
00506      $                                  RWORK, DIF, IINFO )
00507                         ELSE IF( IJVT.EQ.2 ) THEN
00508                            CALL CUNT03( 'R', N, MNMIN, N, MNMIN, VTSAV,
00509      $                                  LDVT, VT, LDVT, WORK, LWORK,
00510      $                                  RWORK, DIF, IINFO )
00511                         ELSE IF( IJVT.EQ.3 ) THEN
00512                            CALL CUNT03( 'R', N, N, N, MNMIN, VTSAV,
00513      $                                  LDVT, VT, LDVT, WORK, LWORK,
00514      $                                  RWORK, DIF, IINFO )
00515                         END IF
00516                      END IF
00517                      RESULT( 6 ) = MAX( RESULT( 6 ), DIF )
00518 *
00519 *                    Compare S
00520 *
00521                      DIF = ZERO
00522                      DIV = MAX( REAL( MNMIN )*ULP*S( 1 ),
00523      $                     SLAMCH( 'Safe minimum' ) )
00524                      DO 80 I = 1, MNMIN - 1
00525                         IF( SSAV( I ).LT.SSAV( I+1 ) )
00526      $                     DIF = ULPINV
00527                         IF( SSAV( I ).LT.ZERO )
00528      $                     DIF = ULPINV
00529                         DIF = MAX( DIF, ABS( SSAV( I )-S( I ) ) / DIV )
00530    80                CONTINUE
00531                      RESULT( 7 ) = MAX( RESULT( 7 ), DIF )
00532    90             CONTINUE
00533   100          CONTINUE
00534 *
00535 *              Test for CGESDD
00536 *
00537                IWTMP = 2*MNMIN*MNMIN + 2*MNMIN + MAX( M, N )
00538                LSWORK = IWTMP + ( IWSPC-1 )*( LWORK-IWTMP ) / 3
00539                LSWORK = MIN( LSWORK, LWORK )
00540                LSWORK = MAX( LSWORK, 1 )
00541                IF( IWSPC.EQ.4 )
00542      $            LSWORK = LWORK
00543 *
00544 *              Factorize A
00545 *
00546                CALL CLACPY( 'F', M, N, ASAV, LDA, A, LDA )
00547                CALL CGESDD( 'A', M, N, A, LDA, SSAV, USAV, LDU, VTSAV,
00548      $                      LDVT, WORK, LSWORK, RWORK, IWORK, IINFO )
00549                IF( IINFO.NE.0 ) THEN
00550                   WRITE( NOUNIT, FMT = 9995 )'GESDD', IINFO, M, N,
00551      $               JTYPE, LSWORK, IOLDSD
00552                   INFO = ABS( IINFO )
00553                   RETURN
00554                END IF
00555 *
00556 *              Do tests 1--4
00557 *
00558                CALL CBDT01( M, N, 0, ASAV, LDA, USAV, LDU, SSAV, E,
00559      $                      VTSAV, LDVT, WORK, RWORK, RESULT( 8 ) )
00560                IF( M.NE.0 .AND. N.NE.0 ) THEN
00561                   CALL CUNT01( 'Columns', MNMIN, M, USAV, LDU, WORK,
00562      $                         LWORK, RWORK, RESULT( 9 ) )
00563                   CALL CUNT01( 'Rows', MNMIN, N, VTSAV, LDVT, WORK,
00564      $                         LWORK, RWORK, RESULT( 10 ) )
00565                END IF
00566                RESULT( 11 ) = 0
00567                DO 110 I = 1, MNMIN - 1
00568                   IF( SSAV( I ).LT.SSAV( I+1 ) )
00569      $               RESULT( 11 ) = ULPINV
00570                   IF( SSAV( I ).LT.ZERO )
00571      $               RESULT( 11 ) = ULPINV
00572   110          CONTINUE
00573                IF( MNMIN.GE.1 ) THEN
00574                   IF( SSAV( MNMIN ).LT.ZERO )
00575      $               RESULT( 11 ) = ULPINV
00576                END IF
00577 *
00578 *              Do partial SVDs, comparing to SSAV, USAV, and VTSAV
00579 *
00580                RESULT( 12 ) = ZERO
00581                RESULT( 13 ) = ZERO
00582                RESULT( 14 ) = ZERO
00583                DO 130 IJQ = 0, 2
00584                   JOBQ = CJOB( IJQ+1 )
00585                   CALL CLACPY( 'F', M, N, ASAV, LDA, A, LDA )
00586                   CALL CGESDD( JOBQ, M, N, A, LDA, S, U, LDU, VT, LDVT,
00587      $                         WORK, LSWORK, RWORK, IWORK, IINFO )
00588 *
00589 *                 Compare U
00590 *
00591                   DIF = ZERO
00592                   IF( M.GT.0 .AND. N.GT.0 ) THEN
00593                      IF( IJQ.EQ.1 ) THEN
00594                         IF( M.GE.N ) THEN
00595                            CALL CUNT03( 'C', M, MNMIN, M, MNMIN, USAV,
00596      $                                  LDU, A, LDA, WORK, LWORK, RWORK,
00597      $                                  DIF, IINFO )
00598                         ELSE
00599                            CALL CUNT03( 'C', M, MNMIN, M, MNMIN, USAV,
00600      $                                  LDU, U, LDU, WORK, LWORK, RWORK,
00601      $                                  DIF, IINFO )
00602                         END IF
00603                      ELSE IF( IJQ.EQ.2 ) THEN
00604                         CALL CUNT03( 'C', M, MNMIN, M, MNMIN, USAV, LDU,
00605      $                               U, LDU, WORK, LWORK, RWORK, DIF,
00606      $                               IINFO )
00607                      END IF
00608                   END IF
00609                   RESULT( 12 ) = MAX( RESULT( 12 ), DIF )
00610 *
00611 *                 Compare VT
00612 *
00613                   DIF = ZERO
00614                   IF( M.GT.0 .AND. N.GT.0 ) THEN
00615                      IF( IJQ.EQ.1 ) THEN
00616                         IF( M.GE.N ) THEN
00617                            CALL CUNT03( 'R', N, MNMIN, N, MNMIN, VTSAV,
00618      $                                  LDVT, VT, LDVT, WORK, LWORK,
00619      $                                  RWORK, DIF, IINFO )
00620                         ELSE
00621                            CALL CUNT03( 'R', N, MNMIN, N, MNMIN, VTSAV,
00622      $                                  LDVT, A, LDA, WORK, LWORK,
00623      $                                  RWORK, DIF, IINFO )
00624                         END IF
00625                      ELSE IF( IJQ.EQ.2 ) THEN
00626                         CALL CUNT03( 'R', N, MNMIN, N, MNMIN, VTSAV,
00627      $                               LDVT, VT, LDVT, WORK, LWORK, RWORK,
00628      $                               DIF, IINFO )
00629                      END IF
00630                   END IF
00631                   RESULT( 13 ) = MAX( RESULT( 13 ), DIF )
00632 *
00633 *                 Compare S
00634 *
00635                   DIF = ZERO
00636                   DIV = MAX( REAL( MNMIN )*ULP*S( 1 ),
00637      $                  SLAMCH( 'Safe minimum' ) )
00638                   DO 120 I = 1, MNMIN - 1
00639                      IF( SSAV( I ).LT.SSAV( I+1 ) )
00640      $                  DIF = ULPINV
00641                      IF( SSAV( I ).LT.ZERO )
00642      $                  DIF = ULPINV
00643                      DIF = MAX( DIF, ABS( SSAV( I )-S( I ) ) / DIV )
00644   120             CONTINUE
00645                   RESULT( 14 ) = MAX( RESULT( 14 ), DIF )
00646   130          CONTINUE
00647 *
00648 *              End of Loop -- Check for RESULT(j) > THRESH
00649 *
00650                NTEST = 0
00651                NFAIL = 0
00652                DO 140 J = 1, 14
00653                   IF( RESULT( J ).GE.ZERO )
00654      $               NTEST = NTEST + 1
00655                   IF( RESULT( J ).GE.THRESH )
00656      $               NFAIL = NFAIL + 1
00657   140          CONTINUE
00658 *
00659                IF( NFAIL.GT.0 )
00660      $            NTESTF = NTESTF + 1
00661                IF( NTESTF.EQ.1 ) THEN
00662                   WRITE( NOUNIT, FMT = 9999 )
00663                   WRITE( NOUNIT, FMT = 9998 )THRESH
00664                   NTESTF = 2
00665                END IF
00666 *
00667                DO 150 J = 1, 14
00668                   IF( RESULT( J ).GE.THRESH ) THEN
00669                      WRITE( NOUNIT, FMT = 9997 )M, N, JTYPE, IWSPC,
00670      $                  IOLDSD, J, RESULT( J )
00671                   END IF
00672   150          CONTINUE
00673 *
00674                NERRS = NERRS + NFAIL
00675                NTESTT = NTESTT + NTEST
00676 *
00677   160       CONTINUE
00678 *
00679   170    CONTINUE
00680   180 CONTINUE
00681 *
00682 *     Summary
00683 *
00684       CALL ALASVM( 'CBD', NOUNIT, NERRS, NTESTT, 0 )
00685 *
00686  9999 FORMAT( ' SVD -- Complex Singular Value Decomposition Driver ',
00687      $      / ' Matrix types (see CDRVBD for details):',
00688      $      / / ' 1 = Zero matrix', / ' 2 = Identity matrix',
00689      $      / ' 3 = Evenly spaced singular values near 1',
00690      $      / ' 4 = Evenly spaced singular values near underflow',
00691      $      / ' 5 = Evenly spaced singular values near overflow',
00692      $      / / ' Tests performed: ( A is dense, U and V are unitary,',
00693      $      / 19X, ' S is an array, and Upartial, VTpartial, and',
00694      $      / 19X, ' Spartial are partially computed U, VT and S),', / )
00695  9998 FORMAT( ' Tests performed with Test Threshold = ', F8.2,
00696      $      / ' CGESVD: ', /
00697      $      ' 1 = | A - U diag(S) VT | / ( |A| max(M,N) ulp ) ',
00698      $      / ' 2 = | I - U**T U | / ( M ulp ) ',
00699      $      / ' 3 = | I - VT VT**T | / ( N ulp ) ',
00700      $      / ' 4 = 0 if S contains min(M,N) nonnegative values in',
00701      $      ' decreasing order, else 1/ulp',
00702      $      / ' 5 = | U - Upartial | / ( M ulp )',
00703      $      / ' 6 = | VT - VTpartial | / ( N ulp )',
00704      $      / ' 7 = | S - Spartial | / ( min(M,N) ulp |S| )',
00705      $      / ' CGESDD: ', /
00706      $      ' 8 = | A - U diag(S) VT | / ( |A| max(M,N) ulp ) ',
00707      $      / ' 9 = | I - U**T U | / ( M ulp ) ',
00708      $      / '10 = | I - VT VT**T | / ( N ulp ) ',
00709      $      / '11 = 0 if S contains min(M,N) nonnegative values in',
00710      $      ' decreasing order, else 1/ulp',
00711      $      / '12 = | U - Upartial | / ( M ulp )',
00712      $      / '13 = | VT - VTpartial | / ( N ulp )',
00713      $      / '14 = | S - Spartial | / ( min(M,N) ulp |S| )', / / )
00714  9997 FORMAT( ' M=', I5, ', N=', I5, ', type ', I1, ', IWS=', I1,
00715      $      ', seed=', 4( I4, ',' ), ' test(', I1, ')=', G11.4 )
00716  9996 FORMAT( ' CDRVBD: ', A, ' returned INFO=', I6, '.', / 9X, 'M=',
00717      $      I6, ', N=', I6, ', JTYPE=', I6, ', ISEED=(', 3( I5, ',' ),
00718      $      I5, ')' )
00719  9995 FORMAT( ' CDRVBD: ', A, ' returned INFO=', I6, '.', / 9X, 'M=',
00720      $      I6, ', N=', I6, ', JTYPE=', I6, ', LSWORK=', I6, / 9X,
00721      $      'ISEED=(', 3( I5, ',' ), I5, ')' )
00722 *
00723       RETURN
00724 *
00725 *     End of CDRVBD
00726 *
00727       END
 All Files Functions