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

NAG CL Interface Introduction
Example description
/* nag_eigen_real_gen_partialsvd (f02wgc) Example Program.
 *
 * Copyright 2024 Numerical Algorithms Group.
 *
 * Mark 30.1, 2024.
 */
/* Pre-processor includes */
#include <math.h>
#include <nag.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL av(Integer *iflag, Integer m, Integer n, const double x[],
                        double ax[], Nag_Comm *comm);
#ifdef __cplusplus
}
#endif
int main(void) {
  /*Integer scalar and array declarations */
  Integer exit_status = 0;
  Integer i, m, n, nconv, ncv, nev;
  Integer pdu, pdv;
  Nag_Comm comm;
  NagError fail;
  /*Double scalar and array declarations */
  static double ruser[1] = {-1.0};
  double *resid = 0, *sigma = 0, *u = 0, *v = 0;
  Nag_OrderType order;

  INIT_FAIL(fail);

  printf("nag_eigen_real_gen_partialsvd (f02wgc) Example Program Results\n\n");

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

  /*     Skip heading in data file */
  scanf("%*[^\n] ");
  scanf("%" NAG_IFMT "%" NAG_IFMT "%" NAG_IFMT "%" NAG_IFMT "%*[^\n]", &m, &n,
        &nev, &ncv);

#ifdef NAG_COLUMN_MAJOR
  order = Nag_ColMajor;
  pdu = m;
  pdv = n;
#else
  order = Nag_RowMajor;
  pdu = ncv;
  pdv = ncv;
#endif

  if (!(resid = NAG_ALLOC(m, double)) || !(sigma = NAG_ALLOC(ncv, double)) ||
      !(u = NAG_ALLOC(m * ncv, double)) || !(v = NAG_ALLOC(n * ncv, double))) {
    printf("Allocation failure\n");
    exit_status = -1;
    goto END;
  }
  /*
   * nag_eigen_real_gen_partialsvd (f02wgc)
   * Computes leading terms in the singular value decomposition of
   * a real general matrix; also computes corresponding left and right
   * singular vectors.
   */
  nag_eigen_real_gen_partialsvd(order, m, n, nev, ncv, av, &nconv, sigma, u,
                                pdu, v, pdv, resid, &comm, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_eigen_real_gen_partialsvd (f02wgc).\n%s\n",
           fail.message);
    exit_status = 1;
    goto END;
  }
  /* Print computed residuals */
  printf("%s\n", "  Singular Value    Residual");
  for (i = 0; i < nconv; i++)
    printf("%10.5f %16.2g\n", sigma[i], resid[i]);
  printf("\n");

END:
  NAG_FREE(resid);
  NAG_FREE(sigma);
  NAG_FREE(u);
  NAG_FREE(v);

  return exit_status;
}

static void NAG_CALL av(Integer *iflag, Integer m, Integer n, const double x[],
                        double ax[], Nag_Comm *comm) {
  Integer i, j;
  double one = 1.0, zero = 0.0;
  double h, k, s, t;

  /* Matrix vector multiply: w <- A*x or w <- Trans(A)*x. */
  if (comm->user[0] == -1.0) {
    printf("(User-supplied callback av, first invocation.)\n");
    comm->user[0] = 0.0;
  }
  h = one / (double)(m + 1);
  k = one / (double)(n + 1);
  if (*iflag == 1) {
    for (i = 0; i < m; i++)
      ax[i] = zero;
    t = zero;
    for (j = 0; j < n; j++) {
      t = t + k;
      s = zero;
      for (i = 0; i < MIN(j + 1, m); i++) {
        s = s + h;
        ax[i] = ax[i] + k * s * (t - one) * x[j];
      }
      for (i = j + 1; i < m; i++) {
        s = s + h;
        ax[i] = ax[i] + k * t * (s - one) * x[j];
      }
    }
  } else {
    for (i = 0; i < n; i++)
      ax[i] = zero;
    t = zero;
    for (j = 0; j < n; j++) {
      t = t + k;
      s = zero;
      for (i = 0; i < MIN(j + 1, m); i++) {
        s = s + h;
        ax[j] = ax[j] + k * s * (t - one) * x[i];
      }
      for (i = j + 1; i < m; i++) {
        s = s + h;
        ax[j] = ax[j] + k * t * (s - one) * x[i];
      }
    }
  }
  return;
}