SUBROUTINE SSTEVR_F95( D, E, W, Z, VL, VU, IL, IU, M, ISUPPZ, & & ABSTOL, INFO ) ! ! -- LAPACK95 interface driver routine (version 3.0) -- ! UNI-C, Denmark; Univ. of Tennessee, USA; NAG Ltd., UK ! September, 2000 ! ! .. USE STATEMENTS .. USE LA_PRECISION, ONLY: WP => SP USE LA_AUXMOD, ONLY: ERINFO USE F77_LAPACK, ONLY: STEVR_F77 => LA_STEVR, LAMCH_F77 => SLAMCH ! .. IMPLICIT STATEMENT .. IMPLICIT NONE ! .. SCALAR ARGUMENTS .. INTEGER, INTENT(IN), OPTIONAL :: IL, IU INTEGER, INTENT(OUT), OPTIONAL :: INFO, M REAL(WP), INTENT(IN), OPTIONAL :: ABSTOL, VL, VU ! .. ARRAY ARGUMENTS .. INTEGER, INTENT(OUT), OPTIONAL, TARGET :: ISUPPZ(:) REAL(WP), INTENT(OUT), OPTIONAL, TARGET :: Z(:,:) REAL(WP), INTENT(INOUT) :: D(:), E(:) REAL(WP), INTENT(OUT) :: W(:) !---------------------------------------------------------------------- ! ! Purpose ! ======= ! LA_STEVR computes selected eigenvalues and, optionally, the ! corresponding eigenvectors of a real symmetric tridiagonal matrix A. ! Eigenvalues and eigenvectors can be selected by specifying either a ! range of values or a range of indices for the desired eigenvalues. ! LA_STEVR uses a relatively robust representation (RRR) algorithm. ! It is usually the fastest algorithm of all and uses the least ! workspace. ! ! ========= ! ! SUBROUTINE LA_STEVR ( D, E, W, Z=z, VL=vl, VU=vu, & ! IL=il, IU=iu, M=m, ISUPPZ=isuppz, & ! ABSTOL=abstol, INFO=info ) ! REAL(), INTENT(INOUT) :: D(:), E(:) ! REAL(), INTENT(OUT) :: W(:) ! REAL(), INTENT(OUT), OPTIONAL :: Z(:,:) ! INTEGER, INTENT(OUT), OPTIONAL :: ISUPPZ(:) ! REAL(), INTENT(IN), OPTIONAL :: VL, VU ! INTEGER, INTENT(IN), OPTIONAL :: IL, IU ! INTEGER, INTENT(OUT), OPTIONAL :: M ! REAL(), INTENT(IN), OPTIONAL :: ABSTOL ! INTEGER, INTENT(OUT), OPTIONAL :: INFO ! where ! ::= KIND(1.0) | KIND(1.0D0) ! ! Arguments ! ========= ! ! D (input/output) REAL array, shape (:) with size(D) = n, where n ! is the order of A. ! On entry, the diagonal elements of the matrix A. ! On exit, the original contents of D possibly multiplied by a ! constant factor to avoid over/underflow in computing the ! eigenvalues. ! E (input/output) REAL array, shape (:) with size(E) = n. ! On entry, the n-1 subdiagonal elements of A in E(1) to E(n-1) . ! E(n) need not be set. ! On exit, the original contents of E possibly multiplied by a ! constant factor to avoid over/underflow in computing the ! eigenvalues. ! W (output) REAL array with size(W) = n. ! The first M elements contain the selected eigenvalues in ! ascending order. ! Z Optional (output) REAL or COMPLEX array, shape (:,:) with ! size(Z,1) = n and size(Z,2) = M. ! The first M columns of Z contain the orthonormal eigenvectors of ! A corresponding to the selected eigenvalues, with the i-th column ! of Z containing the eigenvector associated with the eigenvalue in ! W(i). ! Note: The user must ensure that at least M columns are supplied ! in the array Z. When the exact value of M is not known in advance, ! an upper bound must be used. In all cases M <= n. ! VL,VU Optional (input) REAL. ! The lower and upper bounds of the interval to be searched for ! eigenvalues. VL < VU. ! Default values: VL = -HUGE() and VU = HUGE(), where ! ::= KIND(1.0) | KIND(1.0D0). ! Note: Neither VL nor VU may be present if IL and/or IU is ! present. ! IL,IU Optional (input) INTEGER. ! The indices of the smallest and largest eigenvalues to be ! returned. The IL-th through IU-th eigenvalues will be found. ! 1 <= IL <= IU <= n. ! Default values: IL = 1 and IU = n. ! Note: Neither IL nor IU may be present if VL and/or VU is ! present. ! Note: All eigenvalues are calculated if none of the arguments ! VL, VU, IL and IU are present. ! M Optional (output) INTEGER. ! The total number of eigenvalues found. 0 <= M <= n. ! Note: If IL and IU are present then M = IU - IL + 1. ! ISUPPZ Optional (output) INTEGER array, shape (:) with ! size(ISUPPZ) = 2*max(1,M). ! The support of the eigenvectors in A, i.e., the indices ! indicating the nonzero elements. The i-th eigenvector is nonzero ! only in elements ISUPPZ(2*i-1) through ISUPPZ(2*i). ! ABSTOL Optional (input) REAL. ! The absolute error tolerance for the eigenvalues. An approximate ! eigenvalue is accepted as converged when it is determined to lie ! in an interval [a, b] of width less than or equal to ! ABSTOL + EPSILON(1.0_) * max(| a |, | b |), ! where is the working precision. If ABSTOL <= 0, then ! EPSILON(1.0_)*||A||1 will be used in its place. Eigenvalues ! will be computed most accurately if ABSTOL is set to ! LA_LAMCH( 1.0_, 'Safe minimum'), not zero. ! Default value: 0.0_. ! INFO Optional (output) INTEGER ! = 0: successful exit. ! < 0: if INFO = -i, the i-th argument had an illegal value. ! > 0: an internal error occurred. ! If INFO is not present and an error occurs, then the program is ! terminated with an error message. !----------------------------------------------------------------------- ! .. LOCAL PARAMETERS .. CHARACTER(LEN=8), PARAMETER :: SRNAME = 'LA_STEVR' ! .. LOCAL SCALARS .. CHARACTER(LEN=1) :: LJOBZ, LRANGE INTEGER :: N, LD, LIL, LIU, LM, SISUPPZ, S1Z, S2Z, NN INTEGER :: LINFO, ISTAT, LWORK, LIWORK REAL(WP), TARGET :: LLZ(1,1) REAL(WP) :: LABSTOL, LVL, LVU ! .. LOCAL ARRAYS .. INTEGER:: IWORKMIN(1), DUMMY(1) REAL(WP), TARGET :: WORKMIN(1) INTEGER, POINTER :: IWORK(:), LISUPPZ(:) REAL(WP), POINTER :: WORK(:) ! .. INTRINSIC FUNCTIONS .. INTRINSIC HUGE, PRESENT, SIZE ! .. EXECUTABLE STATEMENTS .. LINFO = 0; ISTAT = 0; N = SIZE(D); LD = MAX(1,N) NN=2*MAX(1,N) IF( PRESENT(ISUPPZ) )THEN; SISUPPZ = SIZE(ISUPPZ); ELSE; SISUPPZ = NN; END IF IF( PRESENT(VL) )THEN; LVL = VL; ELSE; LVL = -HUGE(LVL); ENDIF IF( PRESENT(VU) )THEN; LVU = VU; ELSE; LVU = HUGE(LVU); ENDIF IF( PRESENT(IL) )THEN; LIL = IL; ELSE; LIL = 1; ENDIF IF( PRESENT(IU) )THEN; LIU = IU; ELSE; LIU = N; ENDIF IF( PRESENT(Z) )THEN; S1Z = SIZE(Z,1); S2Z = SIZE(Z,2) ELSE; S1Z = 1; S2Z = 1; ENDIF ! .. TEST THE ARGUMENTS IF( N < 0 ) THEN; LINFO = -1 ELSE IF( SIZE( E ) /= N .AND. N/=0)THEN; LINFO = -2 ELSE IF( SIZE( W ) /= N )THEN; LINFO = -3 ELSE IF( PRESENT(Z) .AND. ( S1Z /= LD .OR. S2Z /= MAX(1,N) ) )THEN; LINFO = -4 ELSE IF( SISUPPZ /= NN .OR. PRESENT(ISUPPZ).AND..NOT.PRESENT(Z) )THEN; LINFO = -5 ELSE IF( LVU < LVL .AND. N>0)THEN; LINFO = -6 ELSE IF( (PRESENT(VL) .OR. PRESENT(VU)) .AND. & (PRESENT(IL) .OR. PRESENT(IU)) )THEN; LINFO = -7 ELSE IF (((LIU0))THEN; LINFO = -7 ELSE IF( N < LIU )THEN; LINFO = -8 ELSE IF( N > 0 )THEN IF( PRESENT(VL) .OR. PRESENT(VU) )THEN; LRANGE = 'V'; LM = N ELSE IF( PRESENT(IL) .OR. PRESENT(IU) )THEN; LRANGE = 'I'; LM = LIU-LIL+1 ELSE; LRANGE = 'A'; LM = N; END IF IF( PRESENT(Z) ) THEN; LJOBZ = 'V' ELSE; LJOBZ = 'N' ENDIF ! .. DETERMINE THE WORKSPACE .. ! .. QUERING THE SIZE OF WORKSPACE .. LWORK = -1 LIWORK = -1 IF (PRESENT(Z)) THEN CALL STEVR_F77( LJOBZ, LRANGE, N, D, E, LVL, LVU, & & LIL, LIU, LABSTOL, LM, W, Z, S1Z, DUMMY, & & WORKMIN, LWORK, IWORKMIN, LIWORK, LINFO ) ELSE CALL STEVR_F77( LJOBZ, LRANGE, N, D, E, LVL, LVU, & & LIL, LIU, LABSTOL, LM, W, LLZ, S1Z, DUMMY, & & WORKMIN, LWORK, IWORKMIN, LIWORK, LINFO ) ENDIF LWORK = WORKMIN(1) LIWORK = IWORKMIN(1) ALLOCATE(IWORK(LIWORK), STAT=ISTAT) IF (ISTAT /= 0) THEN ; LINFO = -100; GOTO 100; ENDIF ALLOCATE(LISUPPZ(NN), STAT=ISTAT) IF (ISTAT /= 0) THEN ; LINFO = -100; GOTO 200; ENDIF ALLOCATE(WORK(LWORK), STAT=ISTAT) IF (ISTAT /= 0) THEN ; LINFO = -100; GOTO 300; ENDIF IF( PRESENT(ABSTOL) )THEN; LABSTOL = ABSTOL ELSE; LABSTOL = 2*LAMCH_F77('Safe minimum'); ENDIF IF (PRESENT (Z)) THEN CALL STEVR_F77( LJOBZ, LRANGE, N, D, E, LVL, LVU, LIL, LIU, & & LABSTOL, LM, W, Z, S1Z, LISUPPZ, WORK, LWORK, & & IWORK, LIWORK, LINFO ) ELSE CALL STEVR_F77( LJOBZ, LRANGE, N, D, E, LVL, LVU, LIL, LIU, & & LABSTOL, LM, W, LLZ, S1Z, LISUPPZ, WORK, LWORK, & & IWORK, LIWORK, LINFO ) ENDIF IF( PRESENT(M) ) M = LM DEALLOCATE(WORK) 300 DEALLOCATE(LISUPPZ) 200 DEALLOCATE(IWORK) ENDIF 100 CALL ERINFO(LINFO,SRNAME,INFO,ISTAT) END SUBROUTINE SSTEVR_F95