LAPACK 3.3.1
Linear Algebra PACKage

dsytd2.f

Go to the documentation of this file.
00001       SUBROUTINE DSYTD2( UPLO, N, A, LDA, D, E, TAU, INFO )
00002 *
00003 *  -- LAPACK routine (version 3.3.1) --
00004 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00005 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00006 *  -- April 2011                                                      --
00007 *
00008 *     .. Scalar Arguments ..
00009       CHARACTER          UPLO
00010       INTEGER            INFO, LDA, N
00011 *     ..
00012 *     .. Array Arguments ..
00013       DOUBLE PRECISION   A( LDA, * ), D( * ), E( * ), TAU( * )
00014 *     ..
00015 *
00016 *  Purpose
00017 *  =======
00018 *
00019 *  DSYTD2 reduces a real symmetric matrix A to symmetric tridiagonal
00020 *  form T by an orthogonal similarity transformation: Q**T * A * Q = T.
00021 *
00022 *  Arguments
00023 *  =========
00024 *
00025 *  UPLO    (input) CHARACTER*1
00026 *          Specifies whether the upper or lower triangular part of the
00027 *          symmetric matrix A is stored:
00028 *          = 'U':  Upper triangular
00029 *          = 'L':  Lower triangular
00030 *
00031 *  N       (input) INTEGER
00032 *          The order of the matrix A.  N >= 0.
00033 *
00034 *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
00035 *          On entry, the symmetric matrix A.  If UPLO = 'U', the leading
00036 *          n-by-n upper triangular part of A contains the upper
00037 *          triangular part of the matrix A, and the strictly lower
00038 *          triangular part of A is not referenced.  If UPLO = 'L', the
00039 *          leading n-by-n lower triangular part of A contains the lower
00040 *          triangular part of the matrix A, and the strictly upper
00041 *          triangular part of A is not referenced.
00042 *          On exit, if UPLO = 'U', the diagonal and first superdiagonal
00043 *          of A are overwritten by the corresponding elements of the
00044 *          tridiagonal matrix T, and the elements above the first
00045 *          superdiagonal, with the array TAU, represent the orthogonal
00046 *          matrix Q as a product of elementary reflectors; if UPLO
00047 *          = 'L', the diagonal and first subdiagonal of A are over-
00048 *          written by the corresponding elements of the tridiagonal
00049 *          matrix T, and the elements below the first subdiagonal, with
00050 *          the array TAU, represent the orthogonal matrix Q as a product
00051 *          of elementary reflectors. See Further Details.
00052 *
00053 *  LDA     (input) INTEGER
00054 *          The leading dimension of the array A.  LDA >= max(1,N).
00055 *
00056 *  D       (output) DOUBLE PRECISION array, dimension (N)
00057 *          The diagonal elements of the tridiagonal matrix T:
00058 *          D(i) = A(i,i).
00059 *
00060 *  E       (output) DOUBLE PRECISION array, dimension (N-1)
00061 *          The off-diagonal elements of the tridiagonal matrix T:
00062 *          E(i) = A(i,i+1) if UPLO = 'U', E(i) = A(i+1,i) if UPLO = 'L'.
00063 *
00064 *  TAU     (output) DOUBLE PRECISION array, dimension (N-1)
00065 *          The scalar factors of the elementary reflectors (see Further
00066 *          Details).
00067 *
00068 *  INFO    (output) INTEGER
00069 *          = 0:  successful exit
00070 *          < 0:  if INFO = -i, the i-th argument had an illegal value.
00071 *
00072 *  Further Details
00073 *  ===============
00074 *
00075 *  If UPLO = 'U', the matrix Q is represented as a product of elementary
00076 *  reflectors
00077 *
00078 *     Q = H(n-1) . . . H(2) H(1).
00079 *
00080 *  Each H(i) has the form
00081 *
00082 *     H(i) = I - tau * v * v**T
00083 *
00084 *  where tau is a real scalar, and v is a real vector with
00085 *  v(i+1:n) = 0 and v(i) = 1; v(1:i-1) is stored on exit in
00086 *  A(1:i-1,i+1), and tau in TAU(i).
00087 *
00088 *  If UPLO = 'L', the matrix Q is represented as a product of elementary
00089 *  reflectors
00090 *
00091 *     Q = H(1) H(2) . . . H(n-1).
00092 *
00093 *  Each H(i) has the form
00094 *
00095 *     H(i) = I - tau * v * v**T
00096 *
00097 *  where tau is a real scalar, and v is a real vector with
00098 *  v(1:i) = 0 and v(i+1) = 1; v(i+2:n) is stored on exit in A(i+2:n,i),
00099 *  and tau in TAU(i).
00100 *
00101 *  The contents of A on exit are illustrated by the following examples
00102 *  with n = 5:
00103 *
00104 *  if UPLO = 'U':                       if UPLO = 'L':
00105 *
00106 *    (  d   e   v2  v3  v4 )              (  d                  )
00107 *    (      d   e   v3  v4 )              (  e   d              )
00108 *    (          d   e   v4 )              (  v1  e   d          )
00109 *    (              d   e  )              (  v1  v2  e   d      )
00110 *    (                  d  )              (  v1  v2  v3  e   d  )
00111 *
00112 *  where d and e denote diagonal and off-diagonal elements of T, and vi
00113 *  denotes an element of the vector defining H(i).
00114 *
00115 *  =====================================================================
00116 *
00117 *     .. Parameters ..
00118       DOUBLE PRECISION   ONE, ZERO, HALF
00119       PARAMETER          ( ONE = 1.0D0, ZERO = 0.0D0,
00120      $                   HALF = 1.0D0 / 2.0D0 )
00121 *     ..
00122 *     .. Local Scalars ..
00123       LOGICAL            UPPER
00124       INTEGER            I
00125       DOUBLE PRECISION   ALPHA, TAUI
00126 *     ..
00127 *     .. External Subroutines ..
00128       EXTERNAL           DAXPY, DLARFG, DSYMV, DSYR2, XERBLA
00129 *     ..
00130 *     .. External Functions ..
00131       LOGICAL            LSAME
00132       DOUBLE PRECISION   DDOT
00133       EXTERNAL           LSAME, DDOT
00134 *     ..
00135 *     .. Intrinsic Functions ..
00136       INTRINSIC          MAX, MIN
00137 *     ..
00138 *     .. Executable Statements ..
00139 *
00140 *     Test the input parameters
00141 *
00142       INFO = 0
00143       UPPER = LSAME( UPLO, 'U' )
00144       IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
00145          INFO = -1
00146       ELSE IF( N.LT.0 ) THEN
00147          INFO = -2
00148       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00149          INFO = -4
00150       END IF
00151       IF( INFO.NE.0 ) THEN
00152          CALL XERBLA( 'DSYTD2', -INFO )
00153          RETURN
00154       END IF
00155 *
00156 *     Quick return if possible
00157 *
00158       IF( N.LE.0 )
00159      $   RETURN
00160 *
00161       IF( UPPER ) THEN
00162 *
00163 *        Reduce the upper triangle of A
00164 *
00165          DO 10 I = N - 1, 1, -1
00166 *
00167 *           Generate elementary reflector H(i) = I - tau * v * v**T
00168 *           to annihilate A(1:i-1,i+1)
00169 *
00170             CALL DLARFG( I, A( I, I+1 ), A( 1, I+1 ), 1, TAUI )
00171             E( I ) = A( I, I+1 )
00172 *
00173             IF( TAUI.NE.ZERO ) THEN
00174 *
00175 *              Apply H(i) from both sides to A(1:i,1:i)
00176 *
00177                A( I, I+1 ) = ONE
00178 *
00179 *              Compute  x := tau * A * v  storing x in TAU(1:i)
00180 *
00181                CALL DSYMV( UPLO, I, TAUI, A, LDA, A( 1, I+1 ), 1, ZERO,
00182      $                     TAU, 1 )
00183 *
00184 *              Compute  w := x - 1/2 * tau * (x**T * v) * v
00185 *
00186                ALPHA = -HALF*TAUI*DDOT( I, TAU, 1, A( 1, I+1 ), 1 )
00187                CALL DAXPY( I, ALPHA, A( 1, I+1 ), 1, TAU, 1 )
00188 *
00189 *              Apply the transformation as a rank-2 update:
00190 *                 A := A - v * w**T - w * v**T
00191 *
00192                CALL DSYR2( UPLO, I, -ONE, A( 1, I+1 ), 1, TAU, 1, A,
00193      $                     LDA )
00194 *
00195                A( I, I+1 ) = E( I )
00196             END IF
00197             D( I+1 ) = A( I+1, I+1 )
00198             TAU( I ) = TAUI
00199    10    CONTINUE
00200          D( 1 ) = A( 1, 1 )
00201       ELSE
00202 *
00203 *        Reduce the lower triangle of A
00204 *
00205          DO 20 I = 1, N - 1
00206 *
00207 *           Generate elementary reflector H(i) = I - tau * v * v**T
00208 *           to annihilate A(i+2:n,i)
00209 *
00210             CALL DLARFG( N-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1,
00211      $                   TAUI )
00212             E( I ) = A( I+1, I )
00213 *
00214             IF( TAUI.NE.ZERO ) THEN
00215 *
00216 *              Apply H(i) from both sides to A(i+1:n,i+1:n)
00217 *
00218                A( I+1, I ) = ONE
00219 *
00220 *              Compute  x := tau * A * v  storing y in TAU(i:n-1)
00221 *
00222                CALL DSYMV( UPLO, N-I, TAUI, A( I+1, I+1 ), LDA,
00223      $                     A( I+1, I ), 1, ZERO, TAU( I ), 1 )
00224 *
00225 *              Compute  w := x - 1/2 * tau * (x**T * v) * v
00226 *
00227                ALPHA = -HALF*TAUI*DDOT( N-I, TAU( I ), 1, A( I+1, I ),
00228      $                 1 )
00229                CALL DAXPY( N-I, ALPHA, A( I+1, I ), 1, TAU( I ), 1 )
00230 *
00231 *              Apply the transformation as a rank-2 update:
00232 *                 A := A - v * w**T - w * v**T
00233 *
00234                CALL DSYR2( UPLO, N-I, -ONE, A( I+1, I ), 1, TAU( I ), 1,
00235      $                     A( I+1, I+1 ), LDA )
00236 *
00237                A( I+1, I ) = E( I )
00238             END IF
00239             D( I ) = A( I, I )
00240             TAU( I ) = TAUI
00241    20    CONTINUE
00242          D( N ) = A( N, N )
00243       END IF
00244 *
00245       RETURN
00246 *
00247 *     End of DSYTD2
00248 *
00249       END
 All Files Functions