*     E04NLA Example Program Text
*     Mark 20 Release. NAG Copyright 2001.
*     .. Parameters ..
      INTEGER          NIN, NOUT
      PARAMETER        (NIN=5,NOUT=6)
      INTEGER          IDUMMY
      PARAMETER        (IDUMMY=-11111)
      INTEGER          NMAX, MMAX, NNZMAX, LENIZ, LENZ
      PARAMETER        (NMAX=100,MMAX=100,NNZMAX=100,LENIZ=10000,
     +                 LENZ=10000)
      INTEGER          LCWSAV, LIWSAV, LLWSAV, LRWSAV
      PARAMETER        (LCWSAV=1,LIWSAV=380,LLWSAV=20,LRWSAV=285)
*     .. Local Scalars ..
      DOUBLE PRECISION OBJ, SINF
      INTEGER          I, ICOL, IFAIL, INFORM, IOBJ, J, JCOL, M, MINIZ,
     +                 MINZ, N, NCOLH, NINF, NNAME, NNZ, NS
      CHARACTER        START
*     .. Local Arrays ..
      DOUBLE PRECISION A(NNZMAX), BL(NMAX+MMAX), BU(NMAX+MMAX),
     +                 CLAMDA(NMAX+MMAX), RUSER(1), RWSAV(LRWSAV),
     +                 XS(NMAX+MMAX), Z(LENZ)
      INTEGER          HA(NNZMAX), ISTATE(NMAX+MMAX), IUSER(1),
     +                 IWSAV(LIWSAV), IZ(LENIZ), KA(NMAX+1)
      LOGICAL          LWSAV(LLWSAV)
      CHARACTER*8      CRNAME(NMAX+MMAX), NAMES(5)
      CHARACTER*80     CWSAV(LCWSAV)
*     .. External Subroutines ..
      EXTERNAL         E04NKA, E04NLA, E04NMA, E04WBF, QPHX, X04ABF
*     .. Executable Statements ..
      WRITE (NOUT,*) 'E04NLA Example Program Results'
*     Skip heading in data file.
      READ (NIN,*)
      READ (NIN,*) N, M
      IF (N.LE.NMAX .AND. M.LE.MMAX) THEN
*
*        Read NNZ, IOBJ, NCOLH, START and NNAME from data file.
*
         READ (NIN,*) NNZ, IOBJ, NCOLH, START, NNAME
*
*        Read NAMES and CRNAME from data file.
*
         READ (NIN,*) (NAMES(I),I=1,5)
         READ (NIN,*) (CRNAME(I),I=1,NNAME)
*
*        Read the matrix A from data file. Set up KA.
*
         JCOL = 1
         KA(JCOL) = 1
         DO 40 I = 1, NNZ
*
*           Element ( HA( I ), ICOL ) is stored in A( I ).
*
            READ (NIN,*) A(I), HA(I), ICOL
*
            IF (ICOL.LT.JCOL) THEN
*
*              Elements not ordered by increasing column index.
*
               WRITE (NOUT,99998) 'Element in column', ICOL,
     +           ' found after element in column', JCOL, '. Problem',
     +           ' abandoned.'
               STOP
            ELSE IF (ICOL.EQ.JCOL+1) THEN
*
*              Index in A of the start of the ICOL-th column equals I.
*
               KA(ICOL) = I
               JCOL = ICOL
            ELSE IF (ICOL.GT.JCOL+1) THEN
*
*              Index in A of the start of the ICOL-th column equals I,
*              but columns JCOL+1,JCOL+2,...,ICOL-1 are empty. Set the
*              corresponding elements of KA to I.
*
               DO 20 J = JCOL + 1, ICOL - 1
                  KA(J) = I
   20          CONTINUE
               KA(ICOL) = I
               JCOL = ICOL
            END IF
   40    CONTINUE
*
         KA(N+1) = NNZ + 1
*
         IF (N.GT.ICOL) THEN
*
*           Columns N,N-1,...,ICOL+1 are empty. Set the corresponding
*           elements of KA accordingly.
*
            DO 60 I = N, ICOL + 1, -1
               IF (KA(I).EQ.IDUMMY) KA(I) = KA(I+1)
   60       CONTINUE
         END IF
*
*        Read BL, BU, ISTATE and XS from data file.
*
         READ (NIN,*) (BL(I),I=1,N+M)
         READ (NIN,*) (BU(I),I=1,N+M)
         IF (START.EQ.'C') THEN
            READ (NIN,*) (ISTATE(I),I=1,N)
         ELSE IF (START.EQ.'W') THEN
            READ (NIN,*) (ISTATE(I),I=1,N+M)
         END IF
         READ (NIN,*) (XS(I),I=1,N)
*
*        Set the unit number for advisory messages to NOUT.
*
         CALL X04ABF(1,NOUT)
*
*        Initialise using E04WBF and check for error exits
*
         IFAIL = 1
         CALL E04WBF('E04NKA',CWSAV,LCWSAV,LWSAV,LLWSAV,IWSAV,LIWSAV,
     +               RWSAV,LRWSAV,IFAIL)
         IF (IFAIL.NE.0) THEN
            WRITE (NOUT,99999) 'E04WBF terminated with IFAIL = ', IFAIL
         ELSE
*
*           Set three options using E04NMF.
*
            CALL E04NMA(' Check Frequency = 10 ',LWSAV,IWSAV,RWSAV,
     +                  INFORM)
*
            IF (INFORM.EQ.0) THEN
               CALL E04NMA(' Crash Tolerance = 0.05 ',LWSAV,IWSAV,RWSAV,
     +                     INFORM)
               IF (INFORM.EQ.0) THEN
                  CALL E04NMA(' Infinite Bound Size = 1.0E+25 ',LWSAV,
     +                        IWSAV,RWSAV,INFORM)
               END IF
            END IF
            IF (INFORM.NE.0) THEN
               WRITE (NOUT,99999) 'E04NMA terminated with INFORM = ',
     +           INFORM
            ELSE
*
*              Read the options file for the remaining options.
*
               CALL E04NLA(NIN,LWSAV,IWSAV,RWSAV,INFORM)
*
               IF (INFORM.NE.0) THEN
                  WRITE (NOUT,99999) 'E04NLA terminated with INFORM =',
     +              INFORM
               END IF
            END IF
            IF (INFORM.EQ.0) THEN
*
*              Solve the QP problem.
*
               IFAIL = 1
*
               CALL E04NKA(N,M,NNZ,IOBJ,NCOLH,QPHX,A,HA,KA,BL,BU,START,
     +                     NAMES,NNAME,CRNAME,NS,XS,ISTATE,MINIZ,MINZ,
     +                     NINF,SINF,OBJ,CLAMDA,IZ,LENIZ,Z,LENZ,IUSER,
     +                     RUSER,LWSAV,IWSAV,RWSAV,IFAIL)
*
*              Check for error exits
*
               WRITE (NOUT,*)
               IF (IFAIL.EQ.7) THEN
                  WRITE (NOUT,99997)
               ELSE
                  WRITE (NOUT,99996) IFAIL
                  WRITE (NOUT,*)
                  WRITE (NOUT,99995)
                  WRITE (NOUT,*)
                  DO 80 I = 1, N
                     WRITE (NOUT,99994) CRNAME(I), ISTATE(I), XS(I),
     +                 CLAMDA(I)
   80             CONTINUE
                  IF (M.GT.0) THEN
                     WRITE (NOUT,*)
                     WRITE (NOUT,*)
                     WRITE (NOUT,99993)
                     WRITE (NOUT,*)
                     DO 100 I = N + 1, N + M
                        J = I - N
                        WRITE (NOUT,99992) CRNAME(I), ISTATE(I), XS(I),
     +                    CLAMDA(I)
  100                CONTINUE
                  END IF
                  WRITE (NOUT,*)
                  WRITE (NOUT,*)
                  WRITE (NOUT,99991) OBJ
               END IF
            END IF
         END IF
      END IF
      STOP
*
99999 FORMAT (1X,A,I3)
99998 FORMAT (/1X,A,I5,A,I5,A,A)
99997 FORMAT (1X,'An input parameter is invalid')
99996 FORMAT (1X,'E04NKA returned with IFAIL = ',I4)
99995 FORMAT (1X,'Variable',2X,'Istate',5X,'Value',9X,'Lagr Mult')
99994 FORMAT (1X,1X,A,1X,I3,4X,1P,G14.6,2X,1P,G12.4)
99993 FORMAT (1X,'Constrnt',2X,'Istate',5X,'Value',9X,'Lagr Mult')
99992 FORMAT (1X,1X,A,1X,I3,4X,1P,G14.6,2X,1P,G12.4)
99991 FORMAT (1X,'Final objective value = ',G15.7)
      END
*
      SUBROUTINE QPHX(NSTATE,NCOLH,X,HX,IUSER,RUSER)
*
*     Routine to compute H*x. (In this version of QPHX, the Hessian
*     matrix H is not referenced explicitly.)
*
*     .. Parameters ..
      INTEGER         NOUT
      PARAMETER       (NOUT=6)
      DOUBLE PRECISION TWO
      PARAMETER       (TWO=2.0D+0)
*     .. Scalar Arguments ..
      INTEGER         NCOLH, NSTATE
*     .. Array Arguments ..
      DOUBLE PRECISION HX(NCOLH), RUSER(*), X(NCOLH)
      INTEGER         IUSER(*)
*     .. Executable Statements ..
      IF (NSTATE.EQ.1) THEN
*
*        First entry.
*
         WRITE (NOUT,99999) NCOLH
*
      END IF
*
*     Normal entry.
*
      HX(1) = TWO*X(1)
      HX(2) = TWO*X(2)
      HX(3) = TWO*(X(3)+X(4))
      HX(4) = HX(3)
      HX(5) = TWO*X(5)
      HX(6) = TWO*(X(6)+X(7))
      HX(7) = HX(6)
*
      IF (NSTATE.GE.2) THEN
*
*        Final entry.
*
         WRITE (NOUT,99998)
*
      END IF
*
      RETURN
*
99999 FORMAT (/' This is the E04NLA example.   NCOLH =',I4,'.')
99998 FORMAT (/' Finished the E04NLA example.')
      END
