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

    MODULE e04ngfe_mod

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

!      .. Use Statements ..
       USE nag_library, ONLY : nag_wp
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Parameters ..
       INTEGER, PARAMETER                  :: iset = 1, nin = 5, ninopt = 7,   &
                                              nout = 6
    CONTAINS
!dec$ attributes offload : mic :: qphess
       SUBROUTINE qphess(n,jthcol,h,ldh,x,hx)
!         In this version of QPHESS, the lower triangle of matrix H is
!         stored in packed form (by columns) in array H.
!         More precisely, the lower triangle of matrix H must be stored with
!         matrix element H(i,j) in array element H(i+(2*N-j)*(j-1)/2,1),
!         for i .ge. j.
!         Note that storing the lower triangle of matrix H in packed form (by
!         columns) is equivalent to storing the upper triangle of matrix H in
!         packed form (by rows).
!         Note also that LDH is used to define the size of array H, and
!         must therefore be at least N*(N+1)/2.

!         .. Implicit None Statement ..
          IMPLICIT NONE
!         .. Scalar Arguments ..
          INTEGER, INTENT (IN)                :: jthcol, ldh, n
!         .. Array Arguments ..
          REAL (KIND=nag_wp), INTENT (IN)     :: h(ldh,*), x(n)
          REAL (KIND=nag_wp), INTENT (OUT)    :: hx(n)
!         .. Local Scalars ..
          REAL (KIND=nag_wp)                  :: s
          INTEGER                             :: i, inc, j, l, lp1
!         .. Executable Statements ..
          IF (jthcol/=0) THEN

!            Special case -- extract one column of  H.

             l = jthcol
             inc = n

             DO i = 1, jthcol
                hx(i) = h(l,1)
                inc = inc - 1
                l = l + inc
             END DO

             l = l - inc + 1

             IF (jthcol<n) THEN
                lp1 = l

                DO i = jthcol + 1, n
                   hx(i) = h(lp1,1)
                   lp1 = lp1 + 1
                END DO

             END IF

          ELSE

!            Normal case.

             l = 0

             DO i = 1, n
                s = 0.0E0_nag_wp

                DO j = i, n
                   l = l + 1
                   s = s + h(l,1)*x(j)
                END DO

                hx(i) = s
             END DO

             l = 0

             DO j = 1, n - 1
                l = l + 1

                DO i = j + 1, n
                   l = l + 1
                   hx(i) = hx(i) + h(l,1)*x(j)
                END DO

             END DO

          END IF

          RETURN

!dec$ attributes offload : mic :: qphess
       END SUBROUTINE qphess
    END MODULE e04ngfe_mod
    PROGRAM e04ngfe

!      E04NGF Example Main Program

!      .. Use Statements ..
       USE nag_library, ONLY : e04nff, e04ngf, e04nhf, nag_wp, x04abf, x04acf, &
                               x04baf
       USE e04ngfe_mod, ONLY : iset, nin, ninopt, nout, qphess
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Parameters ..
       CHARACTER (*), PARAMETER            :: fname = 'e04ngfe.opt'
!      .. Local Scalars ..
       REAL (KIND=nag_wp)                  :: obj
       INTEGER                             :: i, ifail, inform, iter, j, lda,  &
                                              ldh, liwork, lwork, mode, n,     &
                                              nclin, outchn, sda
       CHARACTER (80)                      :: rec
       CHARACTER (1)                       :: uplo
!      .. Local Arrays ..
       REAL (KIND=nag_wp), ALLOCATABLE     :: a(:,:), ax(:), bl(:), bu(:),     &
                                              clamda(:), cvec(:), h(:,:),      &
                                              work(:), x(:)
       INTEGER, ALLOCATABLE                :: istate(:), iwork(:)
!      .. Intrinsic Functions ..
       INTRINSIC                              max
!      .. Executable Statements ..
       WRITE (rec,99998) 'E04NGF Example Program Results'
       CALL x04baf(nout,rec)

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

       READ (nin,*) n, nclin
       liwork = 2*n + 3
       lda = max(1,nclin)

       IF (nclin>0) THEN
          sda = n
       ELSE
          sda = 1
       END IF

!      This particular example problem is of type QP2 with a nondefault QPHESS,
!      so we allocate CVEC(N) and H(LDH,1), and define LDH and LWORK as below

       ldh = n*(n+1)/2

       IF (nclin>0) THEN
          lwork = 2*n**2 + 8*n + 5*nclin
       ELSE
          lwork = n**2 + 8*n
       END IF

       ALLOCATE (istate(n+nclin),ax(max(1,nclin)),iwork(liwork),h(ldh,1),bl(n+ &
          nclin),bu(n+nclin),cvec(n),x(n),a(lda,sda),clamda(n+nclin), &
          work(lwork))

       READ (nin,*) cvec(1:n)
       READ (nin,*) (a(i,1:n),i=1,nclin)
       READ (nin,*) bl(1:(n+nclin))
       READ (nin,*) bu(1:(n+nclin))
       READ (nin,*) x(1:n)
       READ (nin,*) uplo

       IF (uplo=='U') THEN

!         Read the upper triangle of H

          READ (nin,*) ((h(j+(2*n-i)*(i-1)/2,1),j=i,n),i=1,n)
       ELSE IF (uplo=='L') THEN

!         Read the lower triangle of H

          READ (nin,*) ((h(i+(2*n-j)*(j-1)/2,1),j=1,i),i=1,n)
       END IF

       ldh = n*(n+1)/2

!      Set the unit number for advisory messages to OUTCHN

       outchn = nout
       CALL x04abf(iset,outchn)

!      Set four options using E04NHF

       CALL e04nhf(' Print Level = 1 ')

       CALL e04nhf(' Check Frequency = 10 ')

       CALL e04nhf(' Crash Tolerance = 0.05 ')

       CALL e04nhf(' Infinite Bound Size = 1.0D+25 ')

!      Open the options file for reading

       mode = 0

       ifail = 0
       CALL x04acf(ninopt,fname,mode,ifail)

!      Read the options file for the remaining options

       CALL e04ngf(ninopt,inform)

       IF (inform/=0) THEN
          WRITE (rec,99999) 'E04NGF terminated with INFORM =', inform
          CALL x04baf(nout,rec)
          GO TO 20
       END IF

!      Solve the problem

       ifail = 0
       CALL e04nff(n,nclin,a,lda,bl,bu,cvec,h,ldh,qphess,istate,x,iter,obj,ax, &
          clamda,iwork,liwork,work,lwork,ifail)

20     CONTINUE

99999  FORMAT (1X,A,I5)
99998  FORMAT (1X,A)
    END PROGRAM e04ngfe
