/* nag_real_cholesky_skyline_solve (f04mcc) Example Program.
 *
 * Copyright 2014 Numerical Algorithms Group.
 *
 * Mark 4, 1996.
 * Mark 8 revised, 2004.
 */

#include <nag.h>
#include <math.h>
#include <stdio.h>
#include <nag_stdlib.h>
#include <nagf01.h>
#include <nagf04.h>

#define B(I, J) b[(I) *tdb + J]
#define X(I, J) x[(I) *tdx + J]

int main(void)
{
  Integer         exit_status = 0, i, k, k1, k2, lal, n, nrhs, *row = 0, tdb,
                  tdx;
  Nag_SolveSystem select;
  double          *a = 0, *al = 0, *b = 0, *d = 0, *x = 0;
  NagError        fail;

  INIT_FAIL(fail);

  printf(
          "nag_real_cholesky_skyline_solve (f04mcc) Example Program Results\n");
  /* Skip heading in data file */
  scanf("%*[^\n]");
  scanf("%ld", &n);
  if (n >= 1)
    {
      if (!(row = NAG_ALLOC(n, Integer)))
        {
          printf("Allocation failure\n");
          exit_status = -1;
          goto END;
        }
    }
  else
    {
      printf("Invalid n.\n");
      exit_status = 1;
      return exit_status;
    }

  lal = 0;
  for (i = 0; i < n; ++i)
    {
      scanf("%ld", &row[i]);
      lal += row[i];
    }
  if (!(a = NAG_ALLOC(lal, double)) ||
      !(al = NAG_ALLOC(lal, double)))
    {
      printf("Allocation failure\n");
      exit_status = -1;
      goto END;
    }
  k2 = 0;
  for (i = 0; i < n; ++i)
    {
      k1 = k2;
      k2 = k2 + row[i];
      for (k = k1; k < k2; ++k)
        scanf("%lf", &a[k]);
    }
  scanf("%ld", &nrhs);
  if (nrhs >= 1)
    {
      if (!(b = NAG_ALLOC(n*nrhs, double)) ||
          !(d = NAG_ALLOC(n, double)) ||
          !(x = NAG_ALLOC(n*nrhs, double)))
        {
          printf("Allocation failure\n");
          exit_status = -1;
          goto END;
        }
      tdb = nrhs;
      tdx = nrhs;
    }
  else
    {
      printf("Invalid nrhs.\n");
      exit_status = 1;
      return exit_status;
    }
  for (i = 0; i < n; ++i)
    for (k = 0; k < nrhs; ++k)
      scanf("%lf", &B(i, k));
  /* nag_real_cholesky_skyline (f01mcc).
   * LDL^T factorization of real symmetric positive-definite
   * variable-bandwidth (skyline) matrix
   */
  nag_real_cholesky_skyline(n, a, lal, row, al, d, &fail);
  if (fail.code != NE_NOERROR)
    {
      printf("Error from nag_real_cholesky_skyline (f01mcc).\n%s\n",
              fail.message);
      exit_status = 1;
      goto END;
    }
  select = Nag_LDLTX;
  /* nag_real_cholesky_skyline_solve (f04mcc).
   * Approximate solution of real symmetric positive-definite
   * variable-bandwidth simultaneous linear equations
   * (coefficient matrix already factorized by
   * nag_real_cholesky_skyline (f01mcc))
   */
  nag_real_cholesky_skyline_solve(select, n, nrhs, al, lal, d, row, b, tdb,
                                  x, tdx, &fail);
  if (fail.code != NE_NOERROR)
    {
      printf(
              "Error from nag_real_cholesky_skyline_solve (f04mcc).\n%s\n",
              fail.message);
      exit_status = 1;
      goto END;
    }
  printf("\n Solution\n");
  for (i = 0; i < n; ++i)
    {
      for (k = 0; k < nrhs; ++k)
        printf("%9.3f", X(i, k));
      printf("\n");
    }
 END:
  NAG_FREE(row);
  NAG_FREE(b);
  NAG_FREE(d);
  NAG_FREE(x);
  NAG_FREE(a);
  NAG_FREE(al);
  return exit_status;
}