summaryrefslogtreecommitdiff
path: root/SRC/slagts.f
diff options
context:
space:
mode:
Diffstat (limited to 'SRC/slagts.f')
-rw-r--r--SRC/slagts.f304
1 files changed, 304 insertions, 0 deletions
diff --git a/SRC/slagts.f b/SRC/slagts.f
new file mode 100644
index 00000000..e2f43bee
--- /dev/null
+++ b/SRC/slagts.f
@@ -0,0 +1,304 @@
+ SUBROUTINE SLAGTS( JOB, N, A, B, C, D, IN, Y, TOL, INFO )
+*
+* -- LAPACK auxiliary routine (version 3.1) --
+* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
+* November 2006
+*
+* .. Scalar Arguments ..
+ INTEGER INFO, JOB, N
+ REAL TOL
+* ..
+* .. Array Arguments ..
+ INTEGER IN( * )
+ REAL A( * ), B( * ), C( * ), D( * ), Y( * )
+* ..
+*
+* Purpose
+* =======
+*
+* SLAGTS may be used to solve one of the systems of equations
+*
+* (T - lambda*I)*x = y or (T - lambda*I)'*x = y,
+*
+* where T is an n by n tridiagonal matrix, for x, following the
+* factorization of (T - lambda*I) as
+*
+* (T - lambda*I) = P*L*U ,
+*
+* by routine SLAGTF. The choice of equation to be solved is
+* controlled by the argument JOB, and in each case there is an option
+* to perturb zero or very small diagonal elements of U, this option
+* being intended for use in applications such as inverse iteration.
+*
+* Arguments
+* =========
+*
+* JOB (input) INTEGER
+* Specifies the job to be performed by SLAGTS as follows:
+* = 1: The equations (T - lambda*I)x = y are to be solved,
+* but diagonal elements of U are not to be perturbed.
+* = -1: The equations (T - lambda*I)x = y are to be solved
+* and, if overflow would otherwise occur, the diagonal
+* elements of U are to be perturbed. See argument TOL
+* below.
+* = 2: The equations (T - lambda*I)'x = y are to be solved,
+* but diagonal elements of U are not to be perturbed.
+* = -2: The equations (T - lambda*I)'x = y are to be solved
+* and, if overflow would otherwise occur, the diagonal
+* elements of U are to be perturbed. See argument TOL
+* below.
+*
+* N (input) INTEGER
+* The order of the matrix T.
+*
+* A (input) REAL array, dimension (N)
+* On entry, A must contain the diagonal elements of U as
+* returned from SLAGTF.
+*
+* B (input) REAL array, dimension (N-1)
+* On entry, B must contain the first super-diagonal elements of
+* U as returned from SLAGTF.
+*
+* C (input) REAL array, dimension (N-1)
+* On entry, C must contain the sub-diagonal elements of L as
+* returned from SLAGTF.
+*
+* D (input) REAL array, dimension (N-2)
+* On entry, D must contain the second super-diagonal elements
+* of U as returned from SLAGTF.
+*
+* IN (input) INTEGER array, dimension (N)
+* On entry, IN must contain details of the matrix P as returned
+* from SLAGTF.
+*
+* Y (input/output) REAL array, dimension (N)
+* On entry, the right hand side vector y.
+* On exit, Y is overwritten by the solution vector x.
+*
+* TOL (input/output) REAL
+* On entry, with JOB .lt. 0, TOL should be the minimum
+* perturbation to be made to very small diagonal elements of U.
+* TOL should normally be chosen as about eps*norm(U), where eps
+* is the relative machine precision, but if TOL is supplied as
+* non-positive, then it is reset to eps*max( abs( u(i,j) ) ).
+* If JOB .gt. 0 then TOL is not referenced.
+*
+* On exit, TOL is changed as described above, only if TOL is
+* non-positive on entry. Otherwise TOL is unchanged.
+*
+* INFO (output) INTEGER
+* = 0 : successful exit
+* .lt. 0: if INFO = -i, the i-th argument had an illegal value
+* .gt. 0: overflow would occur when computing the INFO(th)
+* element of the solution vector x. This can only occur
+* when JOB is supplied as positive and either means
+* that a diagonal element of U is very small, or that
+* the elements of the right-hand side vector y are very
+* large.
+*
+* =====================================================================
+*
+* .. Parameters ..
+ REAL ONE, ZERO
+ PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 )
+* ..
+* .. Local Scalars ..
+ INTEGER K
+ REAL ABSAK, AK, BIGNUM, EPS, PERT, SFMIN, TEMP
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC ABS, MAX, SIGN
+* ..
+* .. External Functions ..
+ REAL SLAMCH
+ EXTERNAL SLAMCH
+* ..
+* .. External Subroutines ..
+ EXTERNAL XERBLA
+* ..
+* .. Executable Statements ..
+*
+ INFO = 0
+ IF( ( ABS( JOB ).GT.2 ) .OR. ( JOB.EQ.0 ) ) THEN
+ INFO = -1
+ ELSE IF( N.LT.0 ) THEN
+ INFO = -2
+ END IF
+ IF( INFO.NE.0 ) THEN
+ CALL XERBLA( 'SLAGTS', -INFO )
+ RETURN
+ END IF
+*
+ IF( N.EQ.0 )
+ $ RETURN
+*
+ EPS = SLAMCH( 'Epsilon' )
+ SFMIN = SLAMCH( 'Safe minimum' )
+ BIGNUM = ONE / SFMIN
+*
+ IF( JOB.LT.0 ) THEN
+ IF( TOL.LE.ZERO ) THEN
+ TOL = ABS( A( 1 ) )
+ IF( N.GT.1 )
+ $ TOL = MAX( TOL, ABS( A( 2 ) ), ABS( B( 1 ) ) )
+ DO 10 K = 3, N
+ TOL = MAX( TOL, ABS( A( K ) ), ABS( B( K-1 ) ),
+ $ ABS( D( K-2 ) ) )
+ 10 CONTINUE
+ TOL = TOL*EPS
+ IF( TOL.EQ.ZERO )
+ $ TOL = EPS
+ END IF
+ END IF
+*
+ IF( ABS( JOB ).EQ.1 ) THEN
+ DO 20 K = 2, N
+ IF( IN( K-1 ).EQ.0 ) THEN
+ Y( K ) = Y( K ) - C( K-1 )*Y( K-1 )
+ ELSE
+ TEMP = Y( K-1 )
+ Y( K-1 ) = Y( K )
+ Y( K ) = TEMP - C( K-1 )*Y( K )
+ END IF
+ 20 CONTINUE
+ IF( JOB.EQ.1 ) THEN
+ DO 30 K = N, 1, -1
+ IF( K.LE.N-2 ) THEN
+ TEMP = Y( K ) - B( K )*Y( K+1 ) - D( K )*Y( K+2 )
+ ELSE IF( K.EQ.N-1 ) THEN
+ TEMP = Y( K ) - B( K )*Y( K+1 )
+ ELSE
+ TEMP = Y( K )
+ END IF
+ AK = A( K )
+ ABSAK = ABS( AK )
+ IF( ABSAK.LT.ONE ) THEN
+ IF( ABSAK.LT.SFMIN ) THEN
+ IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )
+ $ THEN
+ INFO = K
+ RETURN
+ ELSE
+ TEMP = TEMP*BIGNUM
+ AK = AK*BIGNUM
+ END IF
+ ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN
+ INFO = K
+ RETURN
+ END IF
+ END IF
+ Y( K ) = TEMP / AK
+ 30 CONTINUE
+ ELSE
+ DO 50 K = N, 1, -1
+ IF( K.LE.N-2 ) THEN
+ TEMP = Y( K ) - B( K )*Y( K+1 ) - D( K )*Y( K+2 )
+ ELSE IF( K.EQ.N-1 ) THEN
+ TEMP = Y( K ) - B( K )*Y( K+1 )
+ ELSE
+ TEMP = Y( K )
+ END IF
+ AK = A( K )
+ PERT = SIGN( TOL, AK )
+ 40 CONTINUE
+ ABSAK = ABS( AK )
+ IF( ABSAK.LT.ONE ) THEN
+ IF( ABSAK.LT.SFMIN ) THEN
+ IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )
+ $ THEN
+ AK = AK + PERT
+ PERT = 2*PERT
+ GO TO 40
+ ELSE
+ TEMP = TEMP*BIGNUM
+ AK = AK*BIGNUM
+ END IF
+ ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN
+ AK = AK + PERT
+ PERT = 2*PERT
+ GO TO 40
+ END IF
+ END IF
+ Y( K ) = TEMP / AK
+ 50 CONTINUE
+ END IF
+ ELSE
+*
+* Come to here if JOB = 2 or -2
+*
+ IF( JOB.EQ.2 ) THEN
+ DO 60 K = 1, N
+ IF( K.GE.3 ) THEN
+ TEMP = Y( K ) - B( K-1 )*Y( K-1 ) - D( K-2 )*Y( K-2 )
+ ELSE IF( K.EQ.2 ) THEN
+ TEMP = Y( K ) - B( K-1 )*Y( K-1 )
+ ELSE
+ TEMP = Y( K )
+ END IF
+ AK = A( K )
+ ABSAK = ABS( AK )
+ IF( ABSAK.LT.ONE ) THEN
+ IF( ABSAK.LT.SFMIN ) THEN
+ IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )
+ $ THEN
+ INFO = K
+ RETURN
+ ELSE
+ TEMP = TEMP*BIGNUM
+ AK = AK*BIGNUM
+ END IF
+ ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN
+ INFO = K
+ RETURN
+ END IF
+ END IF
+ Y( K ) = TEMP / AK
+ 60 CONTINUE
+ ELSE
+ DO 80 K = 1, N
+ IF( K.GE.3 ) THEN
+ TEMP = Y( K ) - B( K-1 )*Y( K-1 ) - D( K-2 )*Y( K-2 )
+ ELSE IF( K.EQ.2 ) THEN
+ TEMP = Y( K ) - B( K-1 )*Y( K-1 )
+ ELSE
+ TEMP = Y( K )
+ END IF
+ AK = A( K )
+ PERT = SIGN( TOL, AK )
+ 70 CONTINUE
+ ABSAK = ABS( AK )
+ IF( ABSAK.LT.ONE ) THEN
+ IF( ABSAK.LT.SFMIN ) THEN
+ IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )
+ $ THEN
+ AK = AK + PERT
+ PERT = 2*PERT
+ GO TO 70
+ ELSE
+ TEMP = TEMP*BIGNUM
+ AK = AK*BIGNUM
+ END IF
+ ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN
+ AK = AK + PERT
+ PERT = 2*PERT
+ GO TO 70
+ END IF
+ END IF
+ Y( K ) = TEMP / AK
+ 80 CONTINUE
+ END IF
+*
+ DO 90 K = N, 2, -1
+ IF( IN( K-1 ).EQ.0 ) THEN
+ Y( K-1 ) = Y( K-1 ) - C( K-1 )*Y( K )
+ ELSE
+ TEMP = Y( K-1 )
+ Y( K-1 ) = Y( K )
+ Y( K ) = TEMP - C( K-1 )*Y( K )
+ END IF
+ 90 CONTINUE
+ END IF
+*
+* End of SLAGTS
+*
+ END