NAG Library Manual, Mark 30.3
Interfaces:  FL   CL   CPP   AD 

NAG CL Interface Introduction
Example description
/* nag_sparse_sym_rcm (f11yec) Example Program.
 *
 * Copyright 2024 Numerical Algorithms Group.
 *
 * Mark 30.3, 2024.
 */
#include <nag.h>
#include <stdio.h>

void plot(const Integer n, const Integer nnz, Integer *perm, Integer *icolzp,
          Integer *irowix);
void uncompress(Integer n, Integer *icolzp, Integer *icol);

int main(void) {
  /* Scalars */
  Integer n, nnz, exit_status = 0, doplot = 0, i;
  /* Arrays */
  Integer *icolzp = 0, *irowix = 0, *mask = 0, *perm = 0;
  Integer info[4];
  Nag_Boolean lopts[5];
  /* Nag Types */
  NagError fail;

  INIT_FAIL(fail);
  printf("nag_sparse_sym_rcm (f11yec) Example Program Results\n");
  /* Skip heading in data file and
   * read Size of the matrix and Number of nonzero elements
   */
  scanf("%*[^\n] ");
  scanf("%" NAG_IFMT "%*[^\n] ", &n);
  scanf("%" NAG_IFMT "%*[^\n] ", &nnz);
  if (!(icolzp = NAG_ALLOC((n + 1), Integer)) ||
      !(irowix = NAG_ALLOC((nnz), Integer)) ||
      !(mask = NAG_ALLOC((n), Integer)) || !(perm = NAG_ALLOC((n), Integer))) {
    printf("Allocation failure\n");
    exit_status = -1;
    goto END;
  }
  /* Read in data */
  for (i = 0; i < nnz; i += 1)
    scanf("%" NAG_IFMT "", &irowix[i]);
  scanf("%*[^\n] ");
  for (i = 0; i < (n + 1); i += 1)
    scanf("%" NAG_IFMT "", &icolzp[i]);
  scanf("%*[^\n] ");
  /* Set options */
  lopts[0 /* Use Mask                 */] = Nag_FALSE;
  lopts[1 /* Don't reverse            */] = Nag_FALSE;
  lopts[2 /* Check symmetry           */] = Nag_TRUE;
  lopts[3 /* Compute bandwidth before */] = Nag_TRUE;
  lopts[4 /* Compute bandwidth after  */] = Nag_TRUE;
  /* nag_sparse_sym_rcm (f11yec).
   * Reverse Cuthill-McKee reordering of a real sparse symmetric
   * matrix in CCS format
   */
  nag_sparse_sym_rcm(n, nnz, icolzp, irowix, lopts, mask, perm, info, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_sparse_sym_rcm (f11yec).\n%s\n", fail.message);
    exit_status = 1;
    goto END;
  }
  /* Print results */
  printf("Permutation (perm):\n");
  for (i = 0; i < n; i += 1) {
    printf("    %3" NAG_IFMT "", perm[i]);
    if (i % 6 == 5)
      printf("\n");
  }
  printf("\n\nStatistics:\n");
  printf(" %s%6" NAG_IFMT "\n", " Before:  Bandwidth = ", info[0]);
  printf(" %s%6" NAG_IFMT "\n", " Before:  Profile   = ", info[1]);
  printf(" %s%6" NAG_IFMT "\n", " After :  Bandwidth = ", info[2]);
  printf(" %s%6" NAG_IFMT "\n", " After :  Profile   = ", info[3]);
  /* Print matrix entries and permuted entries in form suitable
   * for plotting
   */
  if (doplot)
    plot(n, nnz, perm, icolzp, irowix);
END:
  NAG_FREE(icolzp);
  NAG_FREE(irowix);
  NAG_FREE(mask);
  NAG_FREE(perm);

  return exit_status;
}

void uncompress(Integer n, Integer *icolzp, Integer *icol) {
  Integer i, j, col_beg, col_end;
  for (i = 0; i < n; i++) {
    col_end = icolzp[i + 1] - 1;
    col_beg = icolzp[i];
    for (j = col_beg; j <= col_end; j++)
      icol[j - 1] = i + 1;
  }
}

void plot(const Integer n, const Integer nnz, Integer *perm, Integer *icolzp,
          Integer *irowix) {
  /* Put data, suitable for plotting matrix structure, in data file */

  /* Scalars */
  Integer i, nnz2;
  /* Arrays */
  double *a = 0;
  Integer *icolix = 0, *ipcolix = 0, *iperm = 0, *iprowix = 0, *istr = 0;
  /* Nag Types */
  NagError fail;

  INIT_FAIL(fail);
  if (!(icolix = NAG_ALLOC(nnz, Integer)) ||
      !(ipcolix = NAG_ALLOC(nnz, Integer)) ||
      !(iprowix = NAG_ALLOC(nnz, Integer)) ||
      !(iperm = NAG_ALLOC(n, Integer)) || !(a = NAG_ALLOC(nnz, double)) ||
      !(istr = NAG_ALLOC(n + 1, Integer))) {
    printf("Allocation failure\n");
    return;
  }
  /* Decompress icolzp to full set of column indices (icolix)
   * and compute inverse permutation
   */
  uncompress(n, icolzp, icolix);
  for (i = 0; i < n; i++) {
    iperm[perm[i] - 1] = i + 1;
  }
  /* Original matrix structure */
  for (i = 0; i < nnz; i++) {
    a[i] = icolix[i] * .01 + 1.0 * irowix[i];
    printf("%8" NAG_IFMT "    ", irowix[i]);
    printf("%8" NAG_IFMT "    ", icolix[i]);
    printf("%8.2f\n", a[i]);
  }
  printf("\n");
  /* Apply Inverse Permutation */
  for (i = 0; i < nnz; i++) {
    ipcolix[i] = iperm[icolix[i] - 1];
    iprowix[i] = iperm[irowix[i] - 1];
  }
  /* Reorder (in exit: istr contains new CCS icolzp) */
  nnz2 = nnz;
  nag_sparse_real_gen_sort(n, &nnz2, a, ipcolix, iprowix,
                           Nag_SparseNsym_FailDups, Nag_SparseNsym_KeepZeros,
                           istr, &fail);
  /* Permuted matrix structure */
  for (i = 0; i < nnz2; i++) {
    printf("%8" NAG_IFMT "    ", iprowix[i]);
    printf("%8" NAG_IFMT "    ", ipcolix[i]);
    printf("%8.2f\n", a[i]);
  }
  NAG_FREE(icolix);
  NAG_FREE(ipcolix);
  NAG_FREE(iprowix);
  NAG_FREE(iperm);
  NAG_FREE(a);
  NAG_FREE(istr);
}