home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
fortran
/
linpklib.arc
/
SSIFA.FOR
< prev
next >
Wrap
Text File
|
1984-01-07
|
7KB
|
224 lines
SUBROUTINE SSIFA(A,LDA,N,KPVT,INFO)
INTEGER LDA,N,KPVT(1),INFO
REAL A(LDA,1)
C
C SSIFA FACTORS A REAL SYMMETRIC MATRIX BY ELIMINATION
C WITH SYMMETRIC PIVOTING.
C
C TO SOLVE A*X = B , FOLLOW SSIFA BY SSISL.
C TO COMPUTE INVERSE(A)*C , FOLLOW SSIFA BY SSISL.
C TO COMPUTE DETERMINANT(A) , FOLLOW SSIFA BY SSIDI.
C TO COMPUTE INERTIA(A) , FOLLOW SSIFA BY SSIDI.
C TO COMPUTE INVERSE(A) , FOLLOW SSIFA BY SSIDI.
C
C ON ENTRY
C
C A REAL(LDA,N)
C THE SYMMETRIC MATRIX TO BE FACTORED.
C ONLY THE DIAGONAL AND UPPER TRIANGLE ARE USED.
C
C LDA INTEGER
C THE LEADING DIMENSION OF THE ARRAY A .
C
C N INTEGER
C THE ORDER OF THE MATRIX A .
C
C ON RETURN
C
C A A BLOCK DIAGONAL MATRIX AND THE MULTIPLIERS WHICH
C WERE USED TO OBTAIN IT.
C THE FACTORIZATION CAN BE WRITTEN A = U*D*TRANS(U)
C WHERE U IS A PRODUCT OF PERMUTATION AND UNIT
C UPPER TRIANGULAR MATRICES , TRANS(U) IS THE
C TRANSPOSE OF U , AND D IS BLOCK DIAGONAL
C WITH 1 BY 1 AND 2 BY 2 BLOCKS.
C
C KPVT INTEGER(N)
C AN INTEGER VECTOR OF PIVOT INDICES.
C
C INFO INTEGER
C = 0 NORMAL VALUE.
C = K IF THE K-TH PIVOT BLOCK IS SINGULAR. THIS IS
C NOT AN ERROR CONDITION FOR THIS SUBROUTINE,
C BUT IT DOES INDICATE THAT SSISL OR SSIDI MAY
C DIVIDE BY ZERO IF CALLED.
C
C LINPACK. THIS VERSION DATED 08/14/78 .
C JAMES BUNCH, UNIV. CALIF. SAN DIEGO, ARGONNE NAT. LAB.
C
C SUBROUTINES AND FUNCTIONS
C
C BLAS SAXPY,SSWAP,ISAMAX
C FORTRAN ABS,AMAX1,SQRT
C
C INTERNAL VARIABLES
C
REAL AK,AKM1,BK,BKM1,DENOM,MULK,MULKM1,T
REAL ABSAKK,ALPHA,COLMAX,ROWMAX
INTEGER IMAX,IMAXP1,J,JJ,JMAX,K,KM1,KM2,KSTEP,ISAMAX
LOGICAL SWAP
C
C
C INITIALIZE
C
C ALPHA IS USED IN CHOOSING PIVOT BLOCK SIZE.
ALPHA = (1.0E0 + SQRT(17.0E0))/8.0E0
C
INFO = 0
C
C MAIN LOOP ON K, WHICH GOES FROM N TO 1.
C
K = N
10 CONTINUE
C
C LEAVE THE LOOP IF K=0 OR K=1.
C
C ...EXIT
IF (K .EQ. 0) GO TO 200
IF (K .GT. 1) GO TO 20
KPVT(1) = 1
IF (A(1,1) .EQ. 0.0E0) INFO = 1
C ......EXIT
GO TO 200
20 CONTINUE
C
C THIS SECTION OF CODE DETERMINES THE KIND OF
C ELIMINATION TO BE PERFORMED. WHEN IT IS COMPLETED,
C KSTEP WILL BE SET TO THE SIZE OF THE PIVOT BLOCK, AND
C SWAP WILL BE SET TO .TRUE. IF AN INTERCHANGE IS
C REQUIRED.
C
KM1 = K - 1
ABSAKK = ABS(A(K,K))
C
C DETERMINE THE LARGEST OFF-DIAGONAL ELEMENT IN
C COLUMN K.
C
IMAX = ISAMAX(K-1,A(1,K),1)
COLMAX = ABS(A(IMAX,K))
IF (ABSAKK .LT. ALPHA*COLMAX) GO TO 30
KSTEP = 1
SWAP = .FALSE.
GO TO 90
30 CONTINUE
C
C DETERMINE THE LARGEST OFF-DIAGONAL ELEMENT IN
C ROW IMAX.
C
ROWMAX = 0.0E0
IMAXP1 = IMAX + 1
DO 40 J = IMAXP1, K
ROWMAX = AMAX1(ROWMAX,ABS(A(IMAX,J)))
40 CONTINUE
IF (IMAX .EQ. 1) GO TO 50
JMAX = ISAMAX(IMAX-1,A(1,IMAX),1)
ROWMAX = AMAX1(ROWMAX,ABS(A(JMAX,IMAX)))
50 CONTINUE
IF (ABS(A(IMAX,IMAX)) .LT. ALPHA*ROWMAX) GO TO 60
KSTEP = 1
SWAP = .TRUE.
GO TO 80
60 CONTINUE
IF (ABSAKK .LT. ALPHA*COLMAX*(COLMAX/ROWMAX)) GO TO 70
KSTEP = 1
SWAP = .FALSE.
GO TO 80
70 CONTINUE
KSTEP = 2
SWAP = IMAX .NE. KM1
80 CONTINUE
90 CONTINUE
IF (AMAX1(ABSAKK,COLMAX) .NE. 0.0E0) GO TO 100
C
C COLUMN K IS ZERO. SET INFO AND ITERATE THE LOOP.
C
KPVT(K) = K
INFO = K
GO TO 190
100 CONTINUE
IF (KSTEP .EQ. 2) GO TO 140
C
C 1 X 1 PIVOT BLOCK.
C
IF (.NOT.SWAP) GO TO 120
C
C PERFORM AN INTERCHANGE.
C
CALL SSWAP(IMAX,A(1,IMAX),1,A(1,K),1)
DO 110 JJ = IMAX, K
J = K + IMAX - JJ
T = A(J,K)
A(J,K) = A(IMAX,J)
A(IMAX,J) = T
110 CONTINUE
120 CONTINUE
C
C PERFORM THE ELIMINATION.
C
DO 130 JJ = 1, KM1
J = K - JJ
MULK = -A(J,K)/A(K,K)
T = MULK
CALL SAXPY(J,T,A(1,K),1,A(1,J),1)
A(J,K) = MULK
130 CONTINUE
C
C SET THE PIVOT ARRAY.
C
KPVT(K) = K
IF (SWAP) KPVT(K) = IMAX
GO TO 190
140 CONTINUE
C
C 2 X 2 PIVOT BLOCK.
C
IF (.NOT.SWAP) GO TO 160
C
C PERFORM AN INTERCHANGE.
C
CALL SSWAP(IMAX,A(1,IMAX),1,A(1,K-1),1)
DO 150 JJ = IMAX, KM1
J = KM1 + IMAX - JJ
T = A(J,K-1)
A(J,K-1) = A(IMAX,J)
A(IMAX,J) = T
150 CONTINUE
T = A(K-1,K)
A(K-1,K) = A(IMAX,K)
A(IMAX,K) = T
160 CONTINUE
C
C PERFORM THE ELIMINATION.
C
KM2 = K - 2
IF (KM2 .EQ. 0) GO TO 180
AK = A(K,K)/A(K-1,K)
AKM1 = A(K-1,K-1)/A(K-1,K)
DENOM = 1.0E0 - AK*AKM1
DO 170 JJ = 1, KM2
J = KM1 - JJ
BK = A(J,K)/A(K-1,K)
BKM1 = A(J,K-1)/A(K-1,K)
MULK = (AKM1*BK - BKM1)/DENOM
MULKM1 = (AK*BKM1 - BK)/DENOM
T = MULK
CALL SAXPY(J,T,A(1,K),1,A(1,J),1)
T = MULKM1
CALL SAXPY(J,T,A(1,K-1),1,A(1,J),1)
A(J,K) = MULK
A(J,K-1) = MULKM1
170 CONTINUE
180 CONTINUE
C
C SET THE PIVOT ARRAY.
C
KPVT(K) = 1 - K
IF (SWAP) KPVT(K) = -IMAX
KPVT(K-1) = KPVT(K)
190 CONTINUE
K = K - KSTEP
GO TO 10
200 CONTINUE
RETURN
END