************************************************************************
*
*
*     Maximum of Quadratics Functions
*
*
*     maxq.f includes the following subroutines
*
*     S   READAT          Reading the data from a given data-file.
*     S   MAXQ            Computation of the value and the subgradient 
*                           of the objective function.
*     S   MAXQF           Computation of the value of the objective 
*                           function.
*     S   MAXQG           Computation of the subgradient of the 
*                           objective function.
*
*     RF  VDOT            Dot product of two vectors.
*
*     In addition, a data-file 'maxq.dat' that provides the required 
*     data for matrices and vectors is needed.  The data-file may be 
*     produced by a matlab-code makeproblem.m. Note, however, that these
*     codes are not fully combined. 
*
*
*     The codes need the COMMON blocks
*
*       COMMON /IDAT/ NF
*       COMMON /RDAT/ A,B,C
*
*     to be given in the main program, where 
*
*     I   NF              is the number of elemental functions.
*     R   A(2*10^8)       is used to store columnwise NF pcs. of 
*                           (N x N) matrices, N<=1000, NF<=200. 
*     R   B(2*10^5)       is used to store NF vectors.
*     R   C(200)          is used to store NF scalars.
*
*
*     Napsu Karmitsa (2009)      
*
*
************************************************************************
*      
*     * SUBROUTINE READAT *
*
*      
*     * Purpose *
*
*     Reading the data from a given data-file 'maxq.dat'. Initiation 
*     of X, the matrices A_i, the vectors b_i and the scalars c_i 
*     (with i=1,...,nf).
*
*      
*     * Calling sequence *
*
*     CALL READAT(N,NF,ICON,X,A,B,C,IERR)
*
*
*     * Parameters *
*      
*     II  N          Number of variables, N<=1000.
*     II  NF         Number of elemental functions, NF<=200.
*     II  ICON       Convexity parameter
*                      0  - Nonconvex problem.
*                      1  - Convex problem.
*     RO  X(N)       Vector of variables.
*     RO  A(NF*N*N)  NF pcs. of (N x N) matrices stored columnwise in 
*                      one dimensional array.
*     RO  B(NF*N)    NF pcs. of vectors.
*     RO  C(NF)      NF scalars. 
*     IO  IERR       Error indicador: 
*                      0  - Everything is ok.
*                     -1  - Error: the problem and the data do not match.
*
*     Note: You should specify the size of the matrices and vectors in 
*     the main program.
*
*
*     Napsu Karmitsa (2009)      
*
      
      
      SUBROUTINE READAT(N,NF,ICON,X,A,B,C,IERR)

*     Scalar Arguments
      INTEGER N,NF,ICON,IERR

*     Array Arguments
      DOUBLE PRECISION X(*),A(*),B(*),C(*)

*     Local Arguments
      DOUBLE PRECISION READN,READNF,READCO
      INTEGER NREAD,NFREAD,CONREA


      OPEN(77,FILE='maxq.dat')


      DO 10 I=1,NF
         READ (77,FMT=*) ((A((I-1)*N*N + (K-1)*N + J),J=1,N),K=1,N), 
     &        (B((I-1)*N+J),J=1,N), C(I)
 10   CONTINUE


      READ (77,FMT=*) (X(J),J=1,N)
      READ (77,FMT=*) READN
      READ (77,FMT=*) READNF
      READ (77,FMT=*) READCO

      CLOSE(77)


      NREAD = INT(READN)
      NFREAD = INT(READNF)
      CONREA = INT(READCO)


      IF (NREAD .NE. N .OR. NFREAD .NE. NF .OR. CONREA .NE. ICON) THEN
         PRINT*,'Error: The problem and the data do not match.'
         IERR = -1
      END IF


      RETURN
      END

      
************************************************************************
*      
*     * SUBROUTINE MAXQ *
*
*      
*     * Purpose *
*
*
*     Computation of the value and the subgradient of the function
*
*       f(x) = max{x^T A_i x + b_i x + c_i | i = 1,2,...,nf}.
*
*      
*     * Calling sequence *
*
*     CALL MAXQ(N,X,F,G,IERR)
*
*
*     * Parameters *
*      
*     II  N          Number of variables.
*     RI  X(N)       Vector of variables.
*     RO  F          Value of the objective function.
*     RO  G(N)       Subgradient of the objective function.
*     IO  IERR       Error indicador: 
*                      0  - Everything is ok.
*                     -1  - Error in function calculation.
*
*
*     This code needs the COMMON blocks
*
*        COMMON /IDAT/ NF
*        COMMON /RDAT/ A,B,C
*
*     to be given in the main program with 
*
*     I  NF          Number of elemental functions.
*     R  A(NF*N*N)   NF pcs. of (N x N) matrices stored columnwise in 
*                      one dimensional array,
*     R  B(NF*N)     NF pcs. of vectors,
*     R  C(NF)       NF scalars. 
*
*      
*     * Subprograms used *
*      
*     RF  VDOT            Dot product of two vectors.
*
*
*     Napsu Karmitsa (2009)      
*
     
      
      SUBROUTINE MAXQ(N,X,F,G,IERR)

*     Scalar Arguments
      INTEGER N,IERR
      DOUBLE PRECISION F

*     Array Arguments
      DOUBLE PRECISION X(*),G(*)

*     Local Arguments
      INTEGER I,J,HIT
      DOUBLE PRECISION FTMP

*     Common blocks
      INTEGER NF
      DOUBLE PRECISION A(1000*1000*200),B(1000*200),C(200)
      COMMON /IDAT/NF
      COMMON /RDAT/A,B,C

*     External Functions
      DOUBLE PRECISION VDOT
      EXTERNAL VDOT

*     Parameters
      DOUBLE PRECISION BIG
      PARAMETER (BIG=1.0D+60)


      IERR = 0
      F = - BIG
      HIT = 0


*     Value of the objective

      DO 20 J = 1, NF
         FTMP = 0.0D+00

         DO 10 I = 1,N
            FTMP = FTMP + VDOT(N,X,A((J-1)*N*N + (I-1)*N + 1)) * X(I)
 10      CONTINUE
         FTMP = FTMP/2
         FTMP = FTMP + VDOT(N,X,B((J-1)*N + 1)) + C(J)

         IF (FTMP .GT. F) THEN
            F = FTMP
            HIT = J
         END IF
 20   CONTINUE


*     One arbitrary subgradient

      IF (HIT .EQ. 0) THEN
         PRINT*,'Something wrong in the calculation of the function'
         IERR=-1
         RETURN
      END IF

      DO 30 I = 1,N
         G(I) = VDOT(N,X,A((HIT-1)*N*N + (I-1)*N + 1)) 
     &          + B((HIT-1)*N + I)
 30   CONTINUE


      RETURN
      END
      


************************************************************************
*      
*     * SUBROUTINE MAXQF *
*
*      
*     * Purpose *
*
*
*     Computation of the value of the function
*
*       f(x) = max{x^T A_i x + b_i x + c_i | i = 1,2,...,nf}.
*
*      
*     * Calling sequence *
*
*     CALL MAXQF(N,X,F,IERR)
*
*
*     * Parameters *
*      
*     II  N          Number of variables.
*     RI  X(N)       Vector of variables.
*     RO  F          Value of the objective function.
*     IO  IERR       Error indicador: 
*                      0  - Everything is ok.
*                     -1  - Error in function calculation.
*
*
*     This code needs the COMMON blocks
*
*        COMMON /IDAT/ NF
*        COMMON /RDAT/ A,B,C
*
*     to be given in the main program with 
*
*     I  NF          Number of elemental functions.
*     R  A(NF*N*N)   NF pcs. of (N x N) matrices stored columnwise in 
*                      one dimensional array,
*     R  B(NF*N)     NF pcs. of vectors,
*     R  C(NF)       NF scalars. 
*
*
*     In addition the subroutine uses the COMMON block
*
*        COMMON /ACTIVE/ HIT
*      
*     with
*
*     I  HIT         Index of the first active function.
*
*
*     * Subprograms used *
*      
*     RF  VDOT            Dot product of two vectors.
*
*
*     Napsu Karmitsa (2009)      
*
     
      
      SUBROUTINE MAXQF(N,X,F,IERR)

*     Scalar Arguments
      INTEGER N,IERR
      DOUBLE PRECISION F

*     Array Arguments
      DOUBLE PRECISION X(*)

*     Local Arguments
      INTEGER I,J
      DOUBLE PRECISION FTMP

*     Common blocks
      INTEGER HIT,NF
      DOUBLE PRECISION A(1000*1000*200),B(1000*200),C(200)
      COMMON /IDAT/NF
      COMMON /RDAT/A,B,C
      COMMON /ACTIVE/HIT

*     External Functions
      DOUBLE PRECISION VDOT
      EXTERNAL VDOT

*     Parameters
      DOUBLE PRECISION BIG
      PARAMETER (BIG=1.0D+60)


      IERR = 0
      F = - BIG
      HIT = 0


*     Value of the objective

      DO 20 J = 1, NF
         FTMP = 0.0D+00

         DO 10 I = 1,N
            FTMP = FTMP + VDOT(N,X,A((J-1)*N*N + (I-1)*N + 1)) * X(I)
 10      CONTINUE
         FTMP = FTMP/2
         FTMP = FTMP + VDOT(N,X,B((J-1)*N + 1)) + C(J)

         IF (FTMP .GT. F) THEN
            F = FTMP
            HIT = J
         END IF
 20   CONTINUE


      RETURN
      END
      

************************************************************************
*      
*     * SUBROUTINE MAXQG *
*
*      
*     * Purpose *
*
*
*     Computation of the subgradient of the function
*
*       f(x) = max{x^T A_i x + b_i x + c_i | i = 1,2,...,nf}.
*
*      
*     * Calling sequence *
*
*     CALL MAXQG(N,X,F,G,IERR)
*
*
*     * Parameters *
*      
*     II  N          Number of variables.
*     RI  X(N)       Vector of variables.
*     RO  G(N)       Subgradient of the objective function.
*     IO  IERR       Error indicador: 
*                      0  - Everything is ok.
*                     -1  - Error in subgradient calculation.
*
*
*     This code needs the COMMON blocks
*
*        COMMON /IDAT/ NF
*        COMMON /RDAT/ A,B,C
*
*     to be given in the main program with 
*
*     I  NF          Number of elemental functions.
*     R  A(NF*N*N)   NF pcs. of (N x N) matrices stored columnwise in 
*                      one dimensional array,
*     R  B(NF*N)     NF pcs. of vectors,
*     R  C(NF)       NF scalars. 
*
*
*     In addition the subroutine uses the COMMON block
*
*        COMMON /ACTIVE/ HIT
*      
*     with
*
*     I  HIT         Index of the first active function.
*
*      
*     * Subprograms used *
*      
*     RF  VDOT            Dot product of two vectors.
*
*
*     Napsu Karmitsa (2009)      
*
     
      
      SUBROUTINE MAXQG(N,X,G,IERR)

*     Scalar Arguments
      INTEGER N,IERR

*     Array Arguments
      DOUBLE PRECISION X(*),G(*)

*     Local Arguments
      INTEGER I

*     Common blocks
      INTEGER NF,HIT
      DOUBLE PRECISION A(1000*1000*200),B(1000*200),C(200)
      COMMON /IDAT/NF
      COMMON /RDAT/A,B,C
      COMMON /ACTIVE/ HIT

*     External Functions
      DOUBLE PRECISION VDOT
      EXTERNAL VDOT


      IERR = 0


*     One arbitrary subgradient

      IF (HIT .EQ. 0) THEN
         PRINT*,'Something wrong in the calculation of the function'
         IERR=-1
         RETURN
      END IF

      DO 30 I = 1,N
         G(I) = VDOT(N,X,A((HIT-1)*N*N + (I-1)*N + 1)) 
     &          + B((HIT-1)*N + I)
 30   CONTINUE


      RETURN
      END
      

************************************************************************
*      
*     * DOUBLE PRECISION FUNCTION VDOT *
*
*
*     * Purpose *
*
*     Dot product of two vectors.
*
*     
*     * Calling sequence *
*     
*     XTY = VDOT(N,X,Y)
*     
*     
*     * Parameters *
*
*     II  N               Vectors dimension.
*     RI  X(N)            Input vector.
*     RI  Y(N)            Input vector.
*     RO  VDOT            Value of dot product VDOT=trans(X)*Y.
*
*      
*     Napsu Haarala (2006)
*     
*
      
c      DOUBLE PRECISION FUNCTION VDOT(N,X,Y)

c*     Scalar Arguments
c      INTEGER N

c*     Array Arguments
c      DOUBLE PRECISION X(*),Y(*)

c*     Local Scalars
c      INTEGER I
c      DOUBLE PRECISION TMP

c      TMP = 0.0D0

c      DO 10 I = 1,N
c         TMP = TMP + X(I)*Y(I)
c 10   CONTINUE

c      VDOT = TMP

c      RETURN
c      END

