!   E04NQF Example Program Text
!   Mark 23 Release. NAG Copyright 2011.

    MODULE e04nqfe_mod

!      E04NQF Example Program Module:
!             Parameters and User-defined Routines

!      .. Use Statements ..
       USE nag_library, ONLY : nag_wp
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Parameters ..
       INTEGER, PARAMETER                  :: lencw = 600, leniw = 600,        &
                                              lenrw = 600, nin = 5, nout = 6
    CONTAINS
!dec$ attributes offload : mic :: qphx
       SUBROUTINE qphx(ncolh,x,hx,nstate,cuser,iuser,ruser)
!         Routine to compute H*x. (In this version of QPHX, the Hessian
!         matrix H is not referenced explicitly.)

!         .. Implicit None Statement ..
          IMPLICIT NONE
!         .. Scalar Arguments ..
          INTEGER, INTENT (IN)                :: ncolh, nstate
!         .. Array Arguments ..
          REAL (KIND=nag_wp), INTENT (OUT)    :: hx(ncolh)
          REAL (KIND=nag_wp), INTENT (INOUT)  :: ruser(*)
          REAL (KIND=nag_wp), INTENT (IN)     :: x(ncolh)
          INTEGER, INTENT (INOUT)             :: iuser(*)
          CHARACTER (8), INTENT (INOUT)       :: cuser(*)
!         .. Executable Statements ..
          hx(1) = 2.0E0_nag_wp*x(1)
          hx(2) = 2.0E0_nag_wp*x(2)
          hx(3) = 2.0E0_nag_wp*(x(3)+x(4))
          hx(4) = hx(3)
          hx(5) = 2.0E0_nag_wp*x(5)
          hx(6) = 2.0E0_nag_wp*(x(6)+x(7))
          hx(7) = hx(6)

          RETURN

!dec$ attributes offload : mic :: qphx
       END SUBROUTINE qphx
    END MODULE e04nqfe_mod
    PROGRAM e04nqfe

!      E04NQF Example Main Program

!      .. Use Statements ..
       USE nag_library, ONLY : e04npf, e04nqf, e04ntf, nag_wp
       USE e04nqfe_mod, ONLY : lencw, leniw, lenrw, nin, nout, qphx
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Local Scalars ..
       REAL (KIND=nag_wp)                  :: obj, objadd, sinf
       INTEGER                             :: i, icol, ifail, iobj, jcol,      &
                                              lenc, m, n, ncolh, ne, ninf,     &
                                              nname, ns
       CHARACTER (8)                       :: prob
       CHARACTER (1)                       :: start
!      .. Local Arrays ..
       REAL (KIND=nag_wp), ALLOCATABLE     :: acol(:), bl(:), bu(:), c(:),     &
                                              pi(:), rc(:), x(:)
       REAL (KIND=nag_wp)                  :: ruser(1), rw(lenrw)
       INTEGER, ALLOCATABLE                :: helast(:), hs(:), inda(:), loca(:)
       INTEGER                             :: iuser(1), iw(leniw)
       CHARACTER (8)                       :: cuser(1), cw(lencw)
       CHARACTER (8), ALLOCATABLE          :: names(:)
!      .. Intrinsic Functions ..
       INTRINSIC                              max
!      .. Executable Statements ..
       WRITE (nout,*) 'E04NQF Example Program Results'
       FLUSH (nout)

!      Skip heading in data file.
       READ (nin,*)

       READ (nin,*) n, m
       READ (nin,*) ne, iobj, ncolh, start, nname
       ALLOCATE (inda(ne),loca(n+1),helast(n+m),hs(n+m),acol(ne),bl(n+m), &
          bu(n+m),x(n+m),pi(m),rc(n+m),names(nname))

       READ (nin,*) names(1:nname)

!      Read the matrix ACOL from data file. Set up LOCA.

       jcol = 1
       loca(jcol) = 1

       DO i = 1, ne

!         Element ( INDA( I ), ICOL ) is stored in ACOL( I ).

          READ (nin,*) acol(i), inda(i), icol

          IF (icol<jcol) THEN

!            Elements not ordered by increasing column index.

             WRITE (nout,99999) 'Element in column', icol, &
                ' found after element in column', jcol, '. Problem', &
                ' abandoned.'
             GO TO 20
          ELSE IF (icol==jcol+1) THEN

!            Index in ACOL of the start of the ICOL-th column equals I.

             loca(icol) = i
             jcol = icol
          ELSE IF (icol>jcol+1) THEN

!            Index in ACOL 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 LOCA to I.

             loca((jcol+1):icol) = i
             jcol = icol
          END IF

       END DO

       loca(n+1) = ne + 1

!      Columns N,N-1,...,ICOL+1 are empty. Set the corresponding
!      elements of LOCA accordingly.

       DO i = n, icol + 1, -1
          loca(i) = loca(i+1)
       END DO

       READ (nin,*) bl(1:(n+m))
       READ (nin,*) bu(1:(n+m))

       IF (start=='C') THEN
          READ (nin,*) hs(1:n)
       ELSE IF (start=='W') THEN
          READ (nin,*) hs(1:(n+m))
       END IF

       READ (nin,*) x(1:n)

!      Call E04NPF to initialise E04NQF.

       ifail = 0
       CALL e04npf(cw,lencw,iw,leniw,rw,lenrw,ifail)

!      By default E04NQF does not print monitoring
!      information. Set the print file unit or the summary
!      file unit to get information.

       ifail = 0
       CALL e04ntf('Print file',nout,cw,iw,rw,ifail)

!      We have no explicit objective vector so set LENC = 0; the
!      objective vector is stored in row IOBJ of ACOL.

       lenc = 0
       ALLOCATE (c(max(1,lenc)))

       objadd = 0.0E0_nag_wp
       prob = ' '

!      Do not allow any elastic variables (i.e. they cannot be
!      infeasible). If we'd set optional argument "Elastic mode" to 0,
!      we wouldn't need to set the individual elements of array HELAST.

       helast(1:(n+m)) = 0

!      Solve the QP problem.

       ifail = 0
       CALL e04nqf(start,qphx,m,n,ne,nname,lenc,ncolh,iobj,objadd,prob,acol, &
          inda,loca,bl,bu,c,names,helast,hs,x,pi,rc,ns,ninf,sinf,obj,cw,lencw, &
          iw,leniw,rw,lenrw,cuser,iuser,ruser,ifail)

       WRITE (nout,*)
       WRITE (nout,99998) obj
       WRITE (nout,99997) x(1:n)

20     CONTINUE

99999  FORMAT (1X,A,I5,A,I5,A,A)
99998  FORMAT (1X,'Final objective value = ',1P,E11.3)
99997  FORMAT (1X,'Optimal X = ',7F9.2)
    END PROGRAM e04nqfe
