*     E04DJA Example Program Text
*     Mark 20 Release. NAG Copyright 2001.
*     .. Parameters ..
      INTEGER          NMAX
      PARAMETER        (NMAX=10)
      INTEGER          NIN, NOUT
      PARAMETER        (NIN=5,NOUT=6)
      INTEGER          LCWSAV, LIWSAV, LLWSAV, LRWSAV
      PARAMETER        (LCWSAV=1,LIWSAV=610,LLWSAV=120,LRWSAV=475)
*     .. Local Scalars ..
      DOUBLE PRECISION OBJF
      INTEGER          I, IFAIL, INFORM, ITER, N
*     .. Local Arrays ..
      DOUBLE PRECISION OBJGRD(NMAX), RUSER(5*NMAX), RWSAV(LRWSAV),
     +                 WORK(13*NMAX), X(NMAX)
      INTEGER          IWORK(NMAX+1), IWSAV(LIWSAV+NMAX)
      LOGICAL          LWSAV(LLWSAV)
      CHARACTER*80     CWSAV(LCWSAV)
*     .. External Subroutines ..
      EXTERNAL         E04DGA, E04DJA, E04DKA, E04WBF, OBJFN1, X04ABF
*     .. Executable Statements ..
      WRITE (NOUT,*) 'E04DJA Example Program Results'
*     Skip heading in data file
      READ (NIN,*)
      READ (NIN,*) N
      IF (N.LE.NMAX) THEN
*
*        Set the unit number for advisory messages to NOUT
*
         CALL X04ABF(1,NOUT)
*
*        Read X from data file
*
         READ (NIN,*) (X(I),I=1,N)
*
*        Initialise using E04WBF and check for error exits
*
         IFAIL = 1
         CALL E04WBF('E04DGA',CWSAV,LCWSAV,LWSAV,LLWSAV,IWSAV,LIWSAV,
     +               RWSAV,LRWSAV,IFAIL)
         IF (IFAIL.NE.0) THEN
            WRITE (NOUT,99999) 'E04WBF terminated with IFAIL = ', IFAIL
         ELSE
*
*           Set two options using E04DKA
*
            CALL E04DKA(' Verify Level = -1 ',LWSAV,IWSAV,RWSAV,INFORM)
            IF (INFORM.EQ.0) THEN
               CALL E04DKA(' Maximum Step Length = 100.0 ',LWSAV,IWSAV,
     +                     RWSAV,INFORM)
            END IF
*
            IF (INFORM.NE.0) THEN
               WRITE (NOUT,99999) 'E04DKA terminated with INFORM = ',
     +           INFORM
            ELSE
*
*              Read the options file for the remaining options
*
               CALL E04DJA(NIN,LWSAV,IWSAV,RWSAV,INFORM)

               IF (INFORM.NE.0) THEN
                  WRITE (NOUT,99999) 'E04DJA terminated with INFORM = ',
     +              INFORM
               END IF
            END IF
            IF (INFORM.EQ.0) THEN
*
*              Solve the problem
*
               IFAIL = 1
*
*              OBJFN1, as defined below, needs to pass IWSAV to E04XAA.
*              This can be done by passing IWSAV as the actual argument
*              for the dummy argument IUSER. OBJFN1 also needs
*              additional IUSER space (for E04XAA dummy array argument
*              INFO), so the dimension of IWSAV has been increased
*              accordingly.
*
               CALL E04DGA(N,OBJFN1,ITER,OBJF,OBJGRD,X,IWORK,WORK,IWSAV,
     +                     RUSER,LWSAV,IWSAV,RWSAV,IFAIL)
*
*              Check for error exits
*
               WRITE (NOUT,*)
               IF (IFAIL.GE.9) THEN
                  WRITE (NOUT,99998)
               ELSE IF (IFAIL.LT.0) THEN
                  WRITE (NOUT,99997)
               ELSE
                  WRITE (NOUT,99996) IFAIL
                  WRITE (NOUT,*)
                  WRITE (NOUT,99995)
                  WRITE (NOUT,*)
                  DO 20 I = 1, N
                     WRITE (NOUT,99994) I, X(I), OBJGRD(I)
   20             CONTINUE
                  WRITE (NOUT,*)
                  WRITE (NOUT,*)
                  WRITE (NOUT,99993) OBJF
               END IF
            END IF
         END IF
*
      END IF
      STOP
*
99999 FORMAT (1X,A,I3)
99998 FORMAT (1X,'An input parameter is invalid in a call to E04DGA')
99997 FORMAT (1X,'MODE < 0 on exit from OBJFUN. Problem abandoned.')
99996 FORMAT (1X,'E04DGA returned with IFAIL = ',I4)
99995 FORMAT (1X,'Variable',10X,'Value',8X,'Gradient value')
99994 FORMAT (1X,'Varbl',1X,I3,4X,1P,G15.7,4X,1P,G9.1)
99993 FORMAT (1X,'Final objective value = ',G15.7)
      END
*
      SUBROUTINE OBJFN1(MODE,N,X,OBJF,OBJGRD,NSTATE,IUSER,RUSER)
*     Routine to evaluate F(x) and approximate its 1st derivatives
*     .. Scalar Arguments ..
      DOUBLE PRECISION  OBJF
      INTEGER           MODE, N, NSTATE
*     .. Array Arguments ..
      DOUBLE PRECISION  OBJGRD(N), RUSER(*), X(N)
      INTEGER           IUSER(*)
*     .. Local Scalars ..
      DOUBLE PRECISION  EPSRF
      INTEGER           I, IFAIL, IMODE, IWARN, LHES, MSGLVL
*     .. Local Arrays ..
      DOUBLE PRECISION  RWLOC(475), USE(1)
      INTEGER           IUSE(1)
      LOGICAL           LWLOC(120)
*     .. External Subroutines ..
*
*     We can use local arrays LWLOC and RWLOC for E04XAA because
*     it only uses information in the integer array passed through
*     as IUSER(1:610) here.
*
      EXTERNAL          E04XAA, OBJFN2
*     .. Executable Statements ..
      IF (MODE.EQ.0) THEN
*        Evaluate F(x) only
         CALL OBJFN2(MODE,N,X,OBJF,OBJGRD,NSTATE,IUSE,USE)
*
      ELSE IF (MODE.EQ.2) THEN
*        Evaluate F(x) and approximate its 1st derivatives
         MSGLVL = 0
         EPSRF = 0.0D0
         IMODE = 0
         LHES = N
         DO 20 I = 1, N
            RUSER(I) = 0.0D0
            RUSER(4*N+I) = X(I)
   20    CONTINUE
         IFAIL = 1
*
*        IUSER(611:610+N) is used for dummy argument INFO in E04XAA.
*        IUSER(1:610) is used for dummy argument IWSAV in E04XAA
*
         CALL E04XAA(MSGLVL,N,EPSRF,RUSER(4*N+1),IMODE,OBJFN2,LHES,
     +               RUSER(1),OBJF,OBJGRD,RUSER(N+1),RUSER(2*N+1),IWARN,
     +               RUSER(3*N+1),IUSE,USE,IUSER(611),LWLOC,IUSER,RWLOC,
     +               IFAIL)
*
      END IF
*
      RETURN
      END
      SUBROUTINE OBJFN2(MODE,N,X,OBJF,OBJGRD,NSTATE,IUSE,USE)
*     Routine to evaluate F(x)
*     .. Scalar Arguments ..
      DOUBLE PRECISION  OBJF
      INTEGER           MODE, N, NSTATE
*     .. Array Arguments ..
      DOUBLE PRECISION  OBJGRD(N), USE(*), X(N)
      INTEGER           IUSE(*)
*     .. Local Scalars ..
      DOUBLE PRECISION  X1, X2
*     .. Intrinsic Functions ..
      INTRINSIC         EXP
*     .. Executable Statements ..
      X1 = X(1)
      X2 = X(2)
*
      OBJF = EXP(X1)*(4.0D0*X1**2+2.0D0*X2**2+4.0D0*X1*X2+2.0D0*X2+
     +       1.0D0)
*
      RETURN
      END
