LAPACK 3.3.0

zqrt12.f

Go to the documentation of this file.
00001       DOUBLE PRECISION FUNCTION ZQRT12( M, N, A, LDA, S, WORK, LWORK,
00002      $                 RWORK )
00003 *
00004 *  -- LAPACK test routine (version 3.1) --
00005 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
00006 *     November 2006
00007 *
00008 *     .. Scalar Arguments ..
00009       INTEGER            LDA, LWORK, M, N
00010 *     ..
00011 *     .. Array Arguments ..
00012       DOUBLE PRECISION   RWORK( * ), S( * )
00013       COMPLEX*16         A( LDA, * ), WORK( LWORK )
00014 *     ..
00015 *
00016 *  Purpose
00017 *  =======
00018 *
00019 *  ZQRT12 computes the singular values `svlues' of the upper trapezoid
00020 *  of A(1:M,1:N) and returns the ratio
00021 *
00022 *       || s - svlues||/(||svlues||*eps*max(M,N))
00023 *
00024 *  Arguments
00025 *  =========
00026 *
00027 *  M       (input) INTEGER
00028 *          The number of rows of the matrix A.
00029 *
00030 *  N       (input) INTEGER
00031 *          The number of columns of the matrix A.
00032 *
00033 *  A       (input) COMPLEX*16 array, dimension (LDA,N)
00034 *          The M-by-N matrix A. Only the upper trapezoid is referenced.
00035 *
00036 *  LDA     (input) INTEGER
00037 *          The leading dimension of the array A.
00038 *
00039 *  S       (input) DOUBLE PRECISION array, dimension (min(M,N))
00040 *          The singular values of the matrix A.
00041 *
00042 *  WORK    (workspace) COMPLEX*16 array, dimension (LWORK)
00043 *
00044 *  LWORK   (input) INTEGER
00045 *          The length of the array WORK. LWORK >= M*N + 2*min(M,N) +
00046 *          max(M,N).
00047 *
00048 *  RWORK   (workspace) DOUBLE PRECISION array, dimension (2*min(M,N))
00049 *
00050 *  =====================================================================
00051 *
00052 *     .. Parameters ..
00053       DOUBLE PRECISION   ZERO, ONE
00054       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
00055 *     ..
00056 *     .. Local Scalars ..
00057       INTEGER            I, INFO, ISCL, J, MN
00058       DOUBLE PRECISION   ANRM, BIGNUM, NRMSVL, SMLNUM
00059 *     ..
00060 *     .. Local Arrays ..
00061       DOUBLE PRECISION   DUMMY( 1 )
00062 *     ..
00063 *     .. External Functions ..
00064       DOUBLE PRECISION   DASUM, DLAMCH, DNRM2, ZLANGE
00065       EXTERNAL           DASUM, DLAMCH, DNRM2, ZLANGE
00066 *     ..
00067 *     .. External Subroutines ..
00068       EXTERNAL           DAXPY, DBDSQR, DLABAD, DLASCL, XERBLA, ZGEBD2,
00069      $                   ZLASCL, ZLASET
00070 *     ..
00071 *     .. Intrinsic Functions ..
00072       INTRINSIC          DBLE, DCMPLX, MAX, MIN
00073 *     ..
00074 *     .. Executable Statements ..
00075 *
00076       ZQRT12 = ZERO
00077 *
00078 *     Test that enough workspace is supplied
00079 *
00080       IF( LWORK.LT.M*N+2*MIN( M, N )+MAX( M, N ) ) THEN
00081          CALL XERBLA( 'ZQRT12', 7 )
00082          RETURN
00083       END IF
00084 *
00085 *     Quick return if possible
00086 *
00087       MN = MIN( M, N )
00088       IF( MN.LE.ZERO )
00089      $   RETURN
00090 *
00091       NRMSVL = DNRM2( MN, S, 1 )
00092 *
00093 *     Copy upper triangle of A into work
00094 *
00095       CALL ZLASET( 'Full', M, N, DCMPLX( ZERO ), DCMPLX( ZERO ), WORK,
00096      $             M )
00097       DO 20 J = 1, N
00098          DO 10 I = 1, MIN( J, M )
00099             WORK( ( J-1 )*M+I ) = A( I, J )
00100    10    CONTINUE
00101    20 CONTINUE
00102 *
00103 *     Get machine parameters
00104 *
00105       SMLNUM = DLAMCH( 'S' ) / DLAMCH( 'P' )
00106       BIGNUM = ONE / SMLNUM
00107       CALL DLABAD( SMLNUM, BIGNUM )
00108 *
00109 *     Scale work if max entry outside range [SMLNUM,BIGNUM]
00110 *
00111       ANRM = ZLANGE( 'M', M, N, WORK, M, DUMMY )
00112       ISCL = 0
00113       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00114 *
00115 *        Scale matrix norm up to SMLNUM
00116 *
00117          CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, WORK, M, INFO )
00118          ISCL = 1
00119       ELSE IF( ANRM.GT.BIGNUM ) THEN
00120 *
00121 *        Scale matrix norm down to BIGNUM
00122 *
00123          CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, WORK, M, INFO )
00124          ISCL = 1
00125       END IF
00126 *
00127       IF( ANRM.NE.ZERO ) THEN
00128 *
00129 *        Compute SVD of work
00130 *
00131          CALL ZGEBD2( M, N, WORK, M, RWORK( 1 ), RWORK( MN+1 ),
00132      $                WORK( M*N+1 ), WORK( M*N+MN+1 ),
00133      $                WORK( M*N+2*MN+1 ), INFO )
00134          CALL DBDSQR( 'Upper', MN, 0, 0, 0, RWORK( 1 ), RWORK( MN+1 ),
00135      $                DUMMY, MN, DUMMY, 1, DUMMY, MN, RWORK( 2*MN+1 ), 
00136      $                INFO )
00137 *
00138          IF( ISCL.EQ.1 ) THEN
00139             IF( ANRM.GT.BIGNUM ) THEN
00140                CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MN, 1, RWORK( 1 ),
00141      $                      MN, INFO )
00142             END IF
00143             IF( ANRM.LT.SMLNUM ) THEN
00144                CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MN, 1, RWORK( 1 ),
00145      $                      MN, INFO )
00146             END IF
00147          END IF
00148 *
00149       ELSE
00150 *
00151          DO 30 I = 1, MN
00152             RWORK( I ) = ZERO
00153    30    CONTINUE
00154       END IF
00155 *
00156 *     Compare s and singular values of work
00157 *
00158       CALL DAXPY( MN, -ONE, S, 1, RWORK( 1 ), 1 )
00159       ZQRT12 = DASUM( MN, RWORK( 1 ), 1 ) /
00160      $         ( DLAMCH( 'Epsilon' )*DBLE( MAX( M, N ) ) )
00161       IF( NRMSVL.NE.ZERO )
00162      $   ZQRT12 = ZQRT12 / NRMSVL
00163 *
00164       RETURN
00165 *
00166 *     End of ZQRT12
00167 *
00168       END
 All Files Functions