/* nag_binary_factor (g11sac) Example Program.
 *
 * Copyright 2014 Numerical Algorithms Group.
 *
 * Mark 7, 2002.
 * Mark 7b revised, 2004.
 */

#include <stdio.h>
#include <nag.h>
#include <nag_stdlib.h>
#include <nagg11.h>

int main(void)
{
  /* Scalars */
  double        cgetol, chi, rlogl, siglev;
  Integer       exit_status, i, pdcm, idf, p, iprint, is;
  Integer       j, maxit, n, niter, nrx, pdx, pdexpp;
  /* Arrays */
  double        *a = 0, *alpha = 0, *c = 0, *cm = 0, *exf = 0, *expp = 0,
    *g = 0, *obs = 0, *pigam = 0, *xl = 0, *y = 0;
  Integer       *iob = 0, *irl = 0;
  char          nag_enum_arg[40];
  /* NAG Types */
  Nag_Boolean   *x = 0;
  Nag_Boolean   chisqr, gprob;
  Nag_OrderType order;
  NagError      fail;

#ifdef NAG_COLUMN_MAJOR
#define X(I, J)    x[(J-1)*pdx + I - 1]
#define CM(I, J)   cm[(J-1)*pdcm + I - 1]
#define EXPP(I, J) expp[(J-1)*pdexpp + I - 1]
  order = Nag_ColMajor;
#else
#define X(I, J)    x[(I-1)*pdx + J - 1]
#define CM(I, J)   cm[(I-1)*pdcm + J - 1]
#define EXPP(I, J) expp[(I-1)*pdexpp + J - 1]
  order = Nag_RowMajor;
#endif

  INIT_FAIL(fail);

  exit_status = 0;
  printf("nag_binary_factor (g11sac) Example Program Results\n");

  /* Skip heading in data file */
  scanf("%*[^\n] ");
  scanf("%ld%ld%ld%*[^\n] ", &p, &n, &is);
  if (p > 0 && is >= 0) {
    /* Allocate arrays */
    pdcm = 2*p;
    pdexpp = p;
    nrx = is;
    if (!(a = NAG_ALLOC(p, double)) ||
        !(alpha = NAG_ALLOC(p, double)) ||
        !(c = NAG_ALLOC(p, double)) ||
        !(cm = NAG_ALLOC(pdcm * 2*p, double)) ||
        !(exf = NAG_ALLOC(is, double)) ||
        !(expp = NAG_ALLOC(pdexpp * p, double)) ||
        !(g = NAG_ALLOC(2*p, double)) ||
        !(obs = NAG_ALLOC(p * p, double)) ||
        !(pigam = NAG_ALLOC(p, double)) ||
        !(xl = NAG_ALLOC(is, double)) ||
        !(y = NAG_ALLOC(is, double)) ||
        !(iob = NAG_ALLOC(is, Integer)) ||
        !(irl = NAG_ALLOC(is, Integer)) ||
        !(x = NAG_ALLOC(nrx * p, Nag_Boolean)))
      {
        printf("Allocation failure\n");
        exit_status = -1;
        goto END;
      }

    if (order == Nag_ColMajor)
      pdx = nrx;
    else
      pdx = p;

    for (i = 1; i <= is; ++i) {
      scanf("%ld", &irl[i-1]);
      for (j = 1; j <= p; ++j) {
        scanf(" %39s", nag_enum_arg);
        /* nag_enum_name_to_value (x04nac).
         * Converts NAG enum member name to value
         */
        X(i, j) = (Nag_Boolean) nag_enum_name_to_value(nag_enum_arg);
      }
      scanf("%*[^\n] ");
    }
    gprob = Nag_FALSE;
    for (i = 1; i <= p; ++i) {
      a[i-1] = 0.5;
      c[i-1] = 0.0;
    }

    /* Set iprint > 0 to obtain intermediate output */
    iprint = -1;
    cgetol = 1e-4;
    maxit = 1000;
    chisqr = Nag_TRUE;

    /* nag_binary_factor (g11sac).
     * Contingency table, latent variable model for binary data
     */
    nag_binary_factor(order, p, n, gprob, is, x, pdx, irl, a, c, iprint,
                      0, cgetol, maxit, chisqr, &niter, alpha, pigam,
                      cm, pdcm, g, expp, pdexpp, obs, exf, y, iob, &rlogl,
                      &chi, &idf, &siglev, &fail);
    if (fail.code != NE_NOERROR) {
      printf("Error from nag_binary_factor (g11sac).\n%s\n", fail.message);
      exit_status = 1;
      goto END;
    }

    printf("\n");
    printf("Item     Alpha      (s.e.)          Pi       (s.e.)\n");
    for (i = 1; i <= p; i++)
      printf("  %ld     %g  (%10g)   %g  (%10g)\n", i,
             alpha[i-1], CM(2*i-1, 2*i-1), pigam[i-1], CM(2*i, 2*i));
    printf("\n");
    printf("Index   Observed   Expected     Theta       Pattern\n");
    printf("        Frequency  Frequency    Score\n");
    for (i = 1; i <= is; i++) {
      printf("%4ld%10ld%13.3f%13.7f ", i, irl[i-1], exf[i-1],
             y[i-1]);
      for (j = 1; j <= p; j++) {
        if (X(i, j) == Nag_TRUE)
          printf("%3s", "T");
        else
          printf("%3s", "F");
      }
      printf("\n");
    }
    printf("\n");
    printf("Chi-squared test statistic = %g\n", chi);
    printf("Degrees of freedom =         %ld\n", idf);
    printf("Significance =               %g\n", siglev);
  }

 END:
  NAG_FREE(a);
  NAG_FREE(alpha);
  NAG_FREE(c);
  NAG_FREE(cm);
  NAG_FREE(exf);
  NAG_FREE(expp);
  NAG_FREE(g);
  NAG_FREE(obs);
  NAG_FREE(pigam);
  NAG_FREE(xl);
  NAG_FREE(y);
  NAG_FREE(iob);
  NAG_FREE(irl);
  NAG_FREE(x);

  return exit_status;
}