// MEX-file gateway routine. Note that varbvsupdate.m checks the
// inputs, so we do not have to do it here.
void mexFunction (int nlhs, mxArray* plhs[], 
		  int nrhs, const mxArray* prhs[]) {

  // Get inputs.
  const SparseMatrix SiRiS	= getSparseMatrix(prhs[0]);
  const double       sigma_beta	= *mxGetPr(prhs[1]);
  const DoubleVector logodds	= getDoubleVector(prhs[2]);
  const DoubleVector betahat	= getDoubleVector(prhs[3]);
  const DoubleVector se		= getDoubleVector(prhs[4]);
  const DoubleVector alpha0	= getDoubleVector(prhs[5]);
  const DoubleVector mu0	= getDoubleVector(prhs[6]);
  const DoubleVector SiRiSr0	= getDoubleVector(prhs[7]);
  const DoubleVector I		= getDoubleVector(prhs[8]);

  // Get the number of SNPs (p) and coordinate ascent updates (m).
  const Size p = betahat.n;
  const Size m = I.n;
  Index* Ir    = SiRiS.ir;
  Index* Jc    = SiRiS.jc;

  // Initialize outputs.
  DoubleVector alpha  = createMatlabVector(p,&plhs[0]);
  DoubleVector mu     = createMatlabVector(p,&plhs[1]);
  DoubleVector SiRiSr = createMatlabVector(p,&plhs[2]);

  copyDoubleVector(alpha0,alpha);
  copyDoubleVector(mu0,mu);
  copyDoubleVector(SiRiSr0,SiRiSr);

  // Store a single column of matrix inv(S)*R*inv(S).
  double* SiRiS_snp = malloc(sizeof(double)*p);

  // Run coordinate ascent updates.
  // Repeat for each coordinate ascent update.
  for (Index j = 0; j < m; j++) {
    Index k = (Index) I.elems[j];

    // Copy the kth column of matrix inv(S)*R*inv(S).
    copySparseColumn(SiRiS_snp, k, SiRiS.elems, Ir, Jc, p);

    // Copy the kth element of vector inv(S)*R*inv(S)*r.
    double SiRiSr_snp = SiRiSr.elems[k];

    // Perform the mean-field variational update.
    rss_varbvsr_update(betahat.elems[k], se.elems[k], sigma_beta, 
		       SiRiS_snp, SiRiSr.elems, SiRiSr_snp, 
		       logodds.elems[k], alpha.elems+k, mu.elems+k, p);
  }

  // Free the dynamically allocated memory.
  free(SiRiS_snp);
}
// MEX-file gateway routine. Note that varbvsbinupdate.m checks the
// inputs, so we do not have to do it here.
void mexFunction (int nlhs, mxArray* plhs[], 
		  int nrhs, const mxArray* prhs[]) {

  // GET INPUTS.
  const SingleMatrix X       = getSingleMatrix(prhs[0]);
  const double       sa      = *mxGetPr(prhs[1]);
  const DoubleVector logodds = getDoubleVector(prhs[2]);
  const DoubleVector d       = getDoubleVector(mxGetField(prhs[3],0,"d"));
  const DoubleVector xdx     = getDoubleVector(mxGetField(prhs[3],0,"xdx"));
  const DoubleVector xy      = getDoubleVector(mxGetField(prhs[3],0,"xy"));
  const DoubleVector xd      = getDoubleVector(mxGetField(prhs[3],0,"xd"));
  const DoubleVector alpha0  = getDoubleVector(prhs[4]);
  const DoubleVector mu0     = getDoubleVector(prhs[5]);
  const DoubleVector Xr0     = getDoubleVector(prhs[6]);
  const DoubleVector I       = getDoubleVector(prhs[7]);

  // Get the number of samples (n), the number of variables (p), and
  // the number of coordinate ascent updates (numiter).
  const Size n       = X.nr;
  const Size p       = X.nc;
  const Size numiter = I.n;

  // INITIALIZE OUTPUTS.
  DoubleVector alpha = createMatlabVector(p,&plhs[0]);
  DoubleVector mu    = createMatlabVector(p,&plhs[1]);
  DoubleVector Xr    = createMatlabVector(n,&plhs[2]);

  copyDoubleVector(alpha0,alpha);
  copyDoubleVector(mu0,mu);
  copyDoubleVector(Xr0,Xr);

  // This is storage for a column of matrix X.
  double* x = malloc(sizeof(double)*n);

  // RUN COORDINATE ASCENT UPDATES.
  // Repeat for each coordinate ascent update.
  for (Index iter = 0; iter < numiter; iter++) {
    Index k = (Index) I.elems[iter];

    // Copy the kth column of matrix X.
    copyColumn(X.elems,x,k,n);

    // Perform the update.
    varbvsbinupdate(x,xy.elems[k],xd.elems[k],xdx.elems[k],d.elems,sa,
		    logodds.elems[k],alpha.elems+k,mu.elems+k,Xr.elems,n);
  }

  // Free the dynamically allocated memory.
  free(x);
}