C
C      ________________________________________________________
C     |                                                        |
C     |       SOLVE A LINEAR SYSTEM USING PRECONDITIONED       |
C     |                   CONJUGATE GRADIENTS                  |
C     |                                                        |
C     |    INPUT:                                              |
C     |                                                        |
C     |         X     --STARTING GUESS                         |
C     |                                                        |
C     |         NDIGIT--DESIRED NUMBER OF CORRECT DIGITS       |
C     |                                                        |
C     |         LIMIT --MAXIMUM NUMBER OF ITERATIONS           |
C     |                                                        |
C     |         B     --RIGHT SIDE (DESTROYED IN COMPUTATIONS) |
C     |                                                        |
C     |         N     --NUMBER OF EQUATIONS                    |
C     |                                                        |
C     |         MULT  --NAME OF SUBROUTINE TO MULTIPLY MATRIX  |
C     |                 BY VECTOR (NAME EXTERNAL IN MAIN PROG.)|
C     |                 MULT(Y,X) EVALUATES Y = AX             |
C     |                                                        |
C     |         PRE   --NAME OF SUBROUTINE WHICH IMPLEMENTS THE|
C     |                 PRECONDITIONER (NAME EXTERNAL IN MAIN  |
C     |                 PROGRAM). PRE(X,R) EVALUATES X =       |
C     |                 P INVERSE R WHERE P IS PRECONDITIONER  |
C     |                                                        |
C     |         W     --WORK ARRAY (AT LEAST 2N ELEMENTS)      |
C     |                                                        |
C     |  OUTPUT:                                               |
C     |                                                        |
C     |         X     --SOLUTION                               |
C     |                                                        |
C     |         DIF   --INPUT FOR SUBROUTINE WHATIS            |
C     |                                                        |
C     |         SIZE  --INPUT FOR SUBROUTINE WHATIS            |
C     |________________________________________________________|
C
      SUBROUTINE PRECG(X,DIF,SIZE,NDIGIT,LIMIT,B,N,MULT,PRE,W)
      REAL B(1),X(1),W(N,1),R,S,T,DIF,SIZE
C     ------------------------------
C     |*** INITIALIZE VARIABLES ***|
C     ------------------------------
      CALL MULT(W,X)
      DO 10 I = 1,N
10         W(I,1) = B(I) - W(I,1)
      CALL PRE(W(1,2),W)
      S = 0.
      DO 20 I = 1,N
20         S = S + W(I,1)*W(I,2)
      IF ( S .GT. 0. ) GOTO 30
      DIF = 0.
      SIZE = 0.
      GOTO 80
C     --------------------------
C     |*** START ITERATIONS ***|
C     --------------------------
30    CALL MULT(B,W(1,2))
      T = 0.
      DO 40 I = 1,N
40         T = T + W(I,2)*B(I)
      DIF = 0.
      SIZE = 0.
      IF ( T .EQ. 0. ) GOTO 80
      R = S/T
      DO 50 I = 1,N
           T = R*W(I,2)
           DIF = DIF + ABS(T)
           X(I) = X(I) + T
           SIZE = SIZE + ABS(X(I))
50         W(I,1) = W(I,1) - R*B(I)
      CALL PRE(B,W)
      T = 0.
      DO 60 I = 1,N
60         T = T + B(I)*W(I,1)
      R = T/S
      DO 70 I = 1,N
70         W(I,2) = B(I) + R*W(I,2)
      S = T
80    CALL STOPIT(DIF,SIZE,NDIGIT,LIMIT)
      IF ( DIF .GT. 0. ) GOTO 30
      RETURN
      END
