*     F04YCF Example Program Text
*     Mark 20 Revised. NAG Copyright 2001.
*     .. Parameters ..
      INTEGER          NOUT
      PARAMETER        (NOUT=6)
*     .. External Subroutines ..
      EXTERNAL         EX1, EX2
*     .. Executable Statements ..
      WRITE (NOUT,*) 'F04YCF Example Program Results'
      CALL EX1
      CALL EX2
      END
*
      SUBROUTINE EX1
*     .. Parameters ..
      INTEGER          NIN, NOUT
      PARAMETER        (NIN=5,NOUT=6)
      INTEGER          NMAX, LDA
      PARAMETER        (NMAX=20,LDA=NMAX)
      DOUBLE PRECISION ZERO
      PARAMETER        (ZERO=0.0D+0)
*     .. Local Scalars ..
      DOUBLE PRECISION ANORM, COND, D1, EPS, ESTNRM
      INTEGER          I, ICASE, ID, IFAIL, J, N
*     .. Local Arrays ..
      DOUBLE PRECISION A(LDA,NMAX), P(NMAX), WORK(NMAX), X(NMAX)
      INTEGER          IWORK(NMAX)
*     .. External Functions ..
      DOUBLE PRECISION DASUM, X02AJF
      EXTERNAL         DASUM, X02AJF
*     .. External Subroutines ..
      EXTERNAL         DTRSV, F03AFF, F04YCF
*     .. Intrinsic Functions ..
      INTRINSIC        MAX
*     .. Executable Statements ..
      WRITE (NOUT,*)
      WRITE (NOUT,*)
      WRITE (NOUT,*) 'Example 1'
*     Skip heading in data file
      READ (NIN,*)
      READ (NIN,*)
      READ (NIN,*)
      READ (NIN,*) N
      WRITE (NOUT,*)
      IF (N.GT.NMAX) THEN
         WRITE (NOUT,99999) 'N is out of range: N =', N, '.'
      ELSE
         READ (NIN,*) ((A(I,J),J=1,N),I=1,N)
*        First compute the norm of A. DASUM returns the sum of the
*        absolute values of a column of A.
         ANORM = ZERO
         DO 20 J = 1, N
            ANORM = MAX(ANORM,DASUM(N,A(1,J),1))
   20    CONTINUE
         WRITE (NOUT,99998) 'Computed norm of A =', ANORM
*        Next estimate the norm of inverse(A). We do not form the
*        inverse explicitly.
         EPS = X02AJF()
         IFAIL = 1
*
*        Factorise A as P*A = L*U using F03AFF.
         CALL F03AFF(N,EPS,A,LDA,D1,ID,P,IFAIL)
         IF (IFAIL.NE.0) THEN
            WRITE (NOUT,99996) IFAIL
            GO TO 60
         END IF
*
         ICASE = 0
         IFAIL = 1
*
   40    CALL F04YCF(ICASE,N,X,ESTNRM,WORK,IWORK,IFAIL)
*
         IF (ICASE.NE.0) THEN
            IF (ICASE.EQ.1) THEN
*              Return the vector inv(P*A)*X by solving the equations
*              L*U*Y = X, overwriting Y on X. First solve L*Z = X for Z.
               CALL DTRSV('Lower','No Transpose','Non-Unit',N,A,LDA,X,1)
*              Then solve U*Y = Z for Y.
               CALL DTRSV('Upper','No Transpose','Unit',N,A,LDA,X,1)
            ELSE IF (ICASE.EQ.2) THEN
*              Return the vector inv(P*A)'*X by solving U'*L'*Y = X,
*              overwriting Y on X. First solve U'*Z = X for Z.
               CALL DTRSV('Upper','Transpose','Unit',N,A,LDA,X,1)
*              Then solve L'*Y = Z for Y.
               CALL DTRSV('Lower','Transpose','Non-Unit',N,A,LDA,X,1)
            END IF
*           Continue until ICASE is returned as 0.
            GO TO 40
         ELSE IF (IFAIL.EQ.0) THEN
            WRITE (NOUT,99998) 'Estimated norm of inverse(A) =', ESTNRM
            COND = ANORM*ESTNRM
            WRITE (NOUT,99997) 'Estimated condition number of A =', COND
            WRITE (NOUT,*)
         ELSE
            WRITE (NOUT,99995) IFAIL
         END IF
      END IF
   60 CONTINUE
*
99999 FORMAT (1X,A,I5,A)
99998 FORMAT (1X,A,F8.4)
99997 FORMAT (1X,A,F5.1)
99996 FORMAT (1X,' ** F03AFF returned with IFAIL = ',I5)
99995 FORMAT (1X,' ** F04YCF returned with IFAIL = ',I5)
      END
*
      SUBROUTINE EX2
*     .. Parameters ..
      INTEGER          NIN, NOUT
      PARAMETER        (NIN=5,NOUT=6)
      INTEGER          NMAX, NZMAX, LICN, LIRN
      PARAMETER        (NMAX=20,NZMAX=25,LICN=4*NZMAX,LIRN=2*NZMAX)
      DOUBLE PRECISION TENTH, ZERO
      PARAMETER        (TENTH=0.1D+0,ZERO=0.0D+0)
*     .. Local Scalars ..
      DOUBLE PRECISION ANORM, COND, ESTNRM, RESID, SUM, U
      INTEGER          I, ICASE, IFAIL, J, N, NZ
      LOGICAL          GROW, LBLOCK
*     .. Local Arrays ..
      DOUBLE PRECISION A(LICN), W(NMAX), WORK1(NMAX), X(NMAX)
      INTEGER          ICN(LICN), IDISP(10), IKEEP(5*NMAX), IRN(LIRN),
     +                 IW(8*NMAX), IWORK(NMAX)
      LOGICAL          ABORT(4)
*     .. External Subroutines ..
      EXTERNAL         F01BRF, F04AXF, F04YCF
*     .. Intrinsic Functions ..
      INTRINSIC        ABS, MAX
*     .. Executable Statements ..
      WRITE (NOUT,*)
      WRITE (NOUT,*)
      WRITE (NOUT,*) 'Example 2'
*     Skip heading in data file
      READ (NIN,*)
      READ (NIN,*)
*     Input N, the order of matrix A, and NZ, the number of non-zero
*     elements of A.
      READ (NIN,*) N, NZ
      WRITE (NOUT,*)
      IF (N.GT.NMAX .OR. NZ.GT.NZMAX) THEN
         WRITE (NOUT,99999) 'N or NZ is out of range: N =', N,
     +     ',   NZ =', NZ, '.'
      ELSE
*        Input the elements of A, along with row and column information.
         READ (NIN,*) (A(I),IRN(I),ICN(I),I=1,NZ)
*        First compute the norm of A.
         ANORM = 0
         DO 40 I = 1, N
            SUM = ZERO
            DO 20 J = 1, NZ
               IF (ICN(J).EQ.I) SUM = SUM + ABS(A(J))
   20       CONTINUE
            ANORM = MAX(ANORM,SUM)
   40    CONTINUE
         WRITE (NOUT,99998) 'Computed norm of A =', ANORM
*        Next estimate the norm of inverse(A). We do not form the
*        inverse explicitly.
*        Factorise A into L*U using F01BRF.
         U = TENTH
         LBLOCK = .TRUE.
         GROW = .TRUE.
         ABORT(1) = .TRUE.
         ABORT(2) = .TRUE.
         ABORT(3) = .FALSE.
         ABORT(4) = .TRUE.
         IFAIL = 1
*
         CALL F01BRF(N,NZ,A,LICN,IRN,LIRN,ICN,U,IKEEP,IW,W,LBLOCK,GROW,
     +               ABORT,IDISP,IFAIL)
         IF (IFAIL.EQ.0) THEN
            ICASE = 0
*
   60       IFAIL = 1
            CALL F04YCF(ICASE,N,X,ESTNRM,WORK1,IWORK,IFAIL)
*
            IF (ICASE.NE.0) THEN
*              Return X := inv(A)*X or X = inv(A)'*X, depending on the
*              value of ICASE, by solving A*Y = X or A'*Y = X,
*              overwriting Y on X.
               CALL F04AXF(N,A,LICN,ICN,IKEEP,X,W,ICASE,IDISP,RESID)
*              Continue until ICASE is returned as 0.
               GO TO 60
            ELSE IF (IFAIL.EQ.0) THEN
               WRITE (NOUT,99998) 'Estimated norm of inverse(A) =',
     +           ESTNRM
               COND = ANORM*ESTNRM
               WRITE (NOUT,99997) 'Estimated condition number of A =',
     +           COND
            ELSE
               WRITE (NOUT,99996) IFAIL
            END IF
         ELSE
            WRITE (NOUT,99995) IFAIL
         END IF
      END IF
*
99999 FORMAT (1X,A,I5,A,I5,A)
99998 FORMAT (1X,A,F8.4)
99997 FORMAT (1X,A,F5.1)
99996 FORMAT (1X,' ** F04YCF returned with IFAIL = ',I5)
99995 FORMAT (1X,' ** F01BRF returned with IFAIL = ',I5)
      END
