/* nag_opt_sparse_mps_read (e04mzc) Example Program.
 *
 * Copyright 2014 Numerical Algorithms Group.
 *
 * Mark 5, 1998.
 * Mark 7 revised, 2001.
 * Mark 8 revised, 2004.
 *
 */

#include <nag.h>
#include <stdio.h>
#include <string.h>
#include <nag_stdlib.h>
#include <nag_string.h>
#include <nage04.h>

#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL qphess(Integer ncolh, const double x[], double hx[],
                            Nag_Comm *comm);
#ifdef __cplusplus
}
#endif

int main(void)
{
  static double ruser[1] = {-1.0};
  Integer     exit_status = 0;
  Integer     *ha, iobj, *ka, m, n, ncolh, ninf, nnz;
  Nag_E04_Opt options;
  double      *a, *bl, *bu, obj, sinf, *xs;
  Nag_Comm    comm;
  NagError    fail;

  INIT_FAIL(fail);

  printf("nag_opt_sparse_mps_read (e04mzc) Example Program Results\n");

  /* For communication with user-supplied functions: */
  comm.user = ruser;

  fflush(stdout);
  /* Initialise the options structure and read MPSX data */
  /* nag_opt_init (e04xxc).
   * Initialization function for option setting
   */
  nag_opt_init(&options);
  strcpy(options.prob_name, "..QP 2..");
  strcpy(options.obj_name, "..COST..");
  /* nag_opt_sparse_mps_read (e04mzc), see above. */
  nag_opt_sparse_mps_read((char *) 0, &n, &m, &nnz, &iobj, &a, &ha, &ka, &bl,
                          &bu,
                          &xs, &options,
                          &fail);
  if (fail.code != NE_NOERROR)
    {
      printf("Error from nag_opt_sparse_mps_read (e04mzc).\n%s\n",
             fail.message);
      exit_status = 1;
      goto END;
    }

  /* Column and row names are now available via options */
  ncolh = 5;
  /* nag_opt_sparse_convex_qp (e04nkc), see above. */
  nag_opt_sparse_convex_qp(n, m, nnz, iobj, ncolh, qphess, a, ha, ka, bl, bu,
                           xs, &ninf, &sinf, &obj, &options, &comm,
                           &fail);
  if (fail.code != NE_NOERROR)
    {
      printf("Error from nag_opt_sparse_convex_qp (e04nkc).\n%s\n",
             fail.message);
      exit_status = 1;
    }

  /* Free memory returned by nag_opt_sparse_mps_read (e04mzc) */
  /* nag_opt_sparse_mps_free (e04myc), see above. */
  nag_opt_sparse_mps_free(&a, &ha, &ka, &bl, &bu, &xs);

  /* Free memory in options (including column & row names) */
  /* nag_opt_free (e04xzc).
   * Memory freeing function for use with option setting
   */
  nag_opt_free(&options, "all", &fail);
  if (fail.code != NE_NOERROR)
    {
      printf("Error from nag_opt_free (e04xzc).\n%s\n", fail.message);
      exit_status = 1;
      goto END;
    }
 END:

  return exit_status;
}

static void NAG_CALL qphess(Integer ncolh, const double x[], double hx[],
                            Nag_Comm *comm)
{
  /* Function to compute H*x. */
  if (comm->user[0] == -1.0)
    {
      printf("(User-supplied callback qphess, first invocation.)\n");
      fflush(stdout);
      comm->user[0] = 0.0;
    }
  hx[0] = 2.0*x[0] + x[1] + x[2] + x[3] + x[4];
  hx[1] = x[0] + 2.0*x[1] + x[2] + x[3] + x[4];
  hx[2] = x[0] + x[1] + 2.0*x[2] + x[3] + x[4];
  hx[3] = x[0] + x[1] + x[2] + 2.0*x[3] + x[4];
  hx[4] = x[0] + x[1] + x[2] + x[3] + 2.0*x[4];
}  /* qphess */