示例#1
0
// gridA[sum(ngrid)] ............ grids to compute predictive quantities for each observation
// loggridA[sum(ngrid)] ......... logarithm of the grid
// ngrid[nobs] .................. lengths of grids for each observation
// onlyAver ..................... 0/1: compute only predictive quantities or return values as well?
// predictP[4] .................. 0/1 indicating which predictive quantities are to be computed
//   predictP[0] ... densities?
//   predictP[1] ... survivor functions?
//   predictP[2] ... hazards?
//   predictP[3] ... cumulative hazards?
// M ............................ McMC sample size (total, 'skip' and 'by' iterations included)
//                                * M should be <= number of rows in *.sim files
//                                * here: it is an index of the last iteration used to compute the average
// skip ......................... how many rows are to be skipped at the beginning of the sample
// by ........................... only every 'by' G-spline will be taken into account
// nwrite ....................... frequency of informing the user about the progress
// version ...................... arbitrary or 32
//                                if = 32, then model for doubly-interval censored data is assumed with G-spline errors
//                                and bivariate normal random intercepts in the onset and time-to-event parts of the model
// Onset ........................ only used by version = 32
//                                equal to 1 if we are predicting the onset 
//                                equak to 0 if we are predicting the event
// errP ......................... error flag (0 on output if everything OK)
//
void
predictive_GS(double *averDens,         double *averS,           double *averHaz,      double *averCumHaz,
              double *valDens,          double *valS,            double *valHaz,       double *valCumHaz,
              double *quantDens,        double *quantS,          double *quantHaz,     double *quantCumHaz,
              const int *dimsP,         const double *X,         const int *obsdims,
              int *M_now,               char **dirP,             char **extensP,       char **extens_adjP,
              const int *GsplI,
              const int *objBetaI,      const double *objBetaD,
              const int *objbI,         const double *objbD,
              const int *b_GsplI,
              const double *gridA,      const double *loggridA,  const int *ngrid,
              double *probsA,           const int *nquant,       int *onlyAver,        const int *predictP,
              const int *M,             const int *skip,         const int *by,        const int *nwrite,
              const int *version,       const int *Onset,        int *errP)
{
  try{
    GetRNGstate();
    double dtemp;
    int itemp;

    int i, j, ix;
    double tmpd;

    *errP = 0;
    string dir = *dirP;
    string extens = *extensP;
    string extens_adj = *extens_adjP;

    /*** Dimensionality parameters ***/
    const int *nobs     = dimsP;
    const int *ncluster = dimsP + 1;
    const int *nwithin  = dimsP + 2;
    const int M_now_max = *M_now;

    /*** What to predict? ***/
    const int *predDens   = predictP + 0;
    const int *predS      = predictP + 1;
    const int *predHaz    = predictP + 2;
    const int *predCumHaz = predictP + 3;

    /*** Quantiles ***/
    if (*nquant <= 0) *onlyAver = 1;

    /*** Needed G-spline parameters      ***/
    const int *dim          = GsplI + 0;
    const int *total_length = GsplI + 1;
    const int *GsplK        = GsplI + 2;          /* K1 (and K2) */
    int *Glength            = (int*) calloc(*dim, sizeof(int));
    if (!Glength) throw returnR("Not enough memory available in predictive_GS (Glength)", 1);
    for (j = 0; j < *dim; j++) Glength[j] = 2*GsplK[j] + 1;

    /*** Check obsdims ***/
    for (i = 0; i < *nobs; i++){
      if (obsdims[i] < 0 || obsdims[i] >= *dim) throw returnR("Error: Inconsistent 'obsdims' parameter supplied to predictive_GS", 1);
    }

    /*** Check grid  and log-grid ***/
    int sum_ngrid = 0;
    for (i = 0; i < *nobs; i++) sum_ngrid += ngrid[i];

    /*** Object for regression parameters ***/
    BetaGamma* beta = new BetaGamma;
    if (!beta) throw returnR("Not enough memory available in predictive_GS (beta)", 1);
    *beta = BetaGamma(objBetaI, objBetaD);

    /*** Object for random effects      ***/
    RandomEff *bb        = new RandomEff;
    RandomEff32::RE *db  = new RandomEff32::RE;
    bool reff_NORMAL = true;                      /** BUT NOT version = 32 !**/

    /*** Objects for bivariate normal random effects in version = 32 ***/
    double *dval, *bval, *dbval;
    double D32[7] = {1, 0, 1,  2,  1, 0, 1};                /** parD argument for RandomEff32::RE initializer  (filled arbitrary) **/
    if (*version == 32){
      reff_NORMAL = false;
      dval = (double*) calloc(objbI[2], sizeof(double));        // objbI[2] = nCluster
      bval = (double*) calloc(objbI[2], sizeof(double));        // objbI[2] = nCluster
      RandomEff32::init(db, dval, bval, D32, objbI, objbI);
      if (*Onset) dbval = dval;
      else        dbval = bval;
    }
    else{
      dval = NULL;
      bval = NULL;
      dbval = NULL;
      if (beta->nRandom()){
        *bb = RandomEff(objbI, objbD);
        if (bb->type_prior() == Gspline_) reff_NORMAL = false;
      }
    }

    
    /*** Object for covariance matrix of random effects                              ***/
    /*** or arrays for G-spline parameters definig distribution of random effects    ***/
    CovMatrix *DD = new CovMatrix;
    const int nD = (beta->nRandom() * (beta->nRandom() + 1)) / 2;

    const int *dim_b          = b_GsplI + 0;
    const int *total_length_b = b_GsplI + 1;
    int k_effect_b;
    int *rM_b = &itemp;
    double *cum_w_b = &dtemp;
    double *sig_scale_b = &dtemp;
    double *prop_mu_b = &dtemp;

    if (*version != 32){
      if (beta->nRandom()){
        if (reff_NORMAL){
          int DDparmI[2];
          DDparmI[0] = beta->nRandom();
          DDparmI[1] = InvWishart;                                       /** it does not matter what is filled here **/
          double *DDparmD = (double*) calloc(2*nD + 1, sizeof(double));
          if (!DDparmD) throw returnR("Not enough memory available in predictive_GS (DDparmD)", 1);
          for (j = 0; j < beta->nRandom(); j++){                         /** initial cov matrix and scale matrix equal to identity  **/
            ix = (j * (2*beta->nRandom() - j + 1))/2;                    /** again, it does not matter what is filled here          **/
            DDparmD[ix] = DDparmD[nD + 1 + ix] = 1.0;                    /** initial matrix must only be positive definite          **/
            for (i = j+1; i < beta->nRandom(); i++){                     /** to pass the CovMatrix constructor                      **/
              DDparmD[ix + i - j] = DDparmD[nD + 1 + ix + i - j] = 0.0;
            }
          }
          DDparmD[nD] = beta->nRandom() + 2;                              /** 'prior degrees of freedom', it does not matter what   **/
          *DD = CovMatrix(DDparmI, DDparmD);
          free(DDparmD);
        }
        else{                          /** G-spline random effects **/
          cum_w_b     = (double*) calloc(*total_length_b, sizeof(double));
          prop_mu_b   = (double*) calloc(*total_length_b, sizeof(double));
          sig_scale_b = (double*)  calloc(*dim_b, sizeof(double));
          rM_b        = (int*) calloc(*ncluster, sizeof(int));
          if (!cum_w_b || !prop_mu_b || !sig_scale_b) throw returnR("Not enough memory available in predictive_GS (cum_w_b/sig_scale_b)", 1);
          if (!rM_b) throw returnR("Not enough memory available in predictive_GS (rM_b)", 1);
        }
      }
    }  /** end of if (*version != 32) **/

    /*** Space for linear predictors    ***/
    double *linPred = (double*) calloc(*nobs, sizeof(double));
    if (!linPred) throw returnR("Not enough memory available in predictive_GS (linPred)", 1);
    for (i = 0; i < *nobs; i++) linPred[i] = 0.0;

    /*** Allocate memory for needed quantities from simulated G-splines ***/
    int k_effect;
    double *sigma         = (double*)  calloc(*dim, sizeof(double));
    double *gamma         = (double*)  calloc(*dim, sizeof(double));
    double *delta         = (double*)  calloc(*dim, sizeof(double));
    double *intcpt        = (double*)  calloc(*dim, sizeof(double));
    double *scale         = (double*)  calloc(*dim, sizeof(double));
    double *delta_sig     = (double*)  calloc(*dim, sizeof(double));
    double *inv_sig_scale = (double*)  calloc(*dim, sizeof(double));
    if (!sigma || !gamma || !delta || !inv_sig_scale || !intcpt || !scale || !delta_sig) 
      throw returnR("Not enough memory available in predictive_GS (sigma/gamma/delta/intcpt/scale/delta_sig/inv_sig_scale)", 1);

    double **w_marg           = (double**) calloc(*dim, sizeof(double*));
    double **mu_sig_marg      = (double**) calloc(*dim, sizeof(double*));
    if (!w_marg || !mu_sig_marg)
      throw returnR("Not enough memory available in predictive_GS (w_marg/sc_mu_marg)", 1);
    for (j = 0; j < *dim; j++){
      w_marg[j]      = (double*) calloc(Glength[j], sizeof(double));
      mu_sig_marg[j] = (double*) calloc(Glength[j], sizeof(double));
      if (!w_marg[j] || !mu_sig_marg[j]) throw returnR("Not enough memory available in predictive_GS (w_marg[j]/mu_sig_marg[j])", 1);
    }

    /*** Open files with simulated G-splines ***/
    std::string kpath     = dir + "/mixmoment" + extens + ".sim";    
    std::string wpath     = dir + "/mweight" + extens + ".sim";
    std::string mupath    = dir + "/mmean" + extens + ".sim";       
    std::string sigmapath = dir + "/gspline" + extens + ".sim";
    std::ifstream kfile, wfile, mufile, sigmafile;
    openGsplineFiles(kfile, wfile, mufile, sigmafile, kpath, wpath, mupath, sigmapath, *skip + 1);   /* skip also header */

    /*** Open files with simulated remaining quantities ***/
    std::string betapath = dir + "/beta" + extens + ".sim";
    std::ifstream betafile;

    std::string Dpath    = dir + "/D" + extens + ".sim";
    std::ifstream Dfile;

    std::string D32path  = dir + "/D" + ".sim";
    std::ifstream D32file;

    std::string kpath_b     = dir + "/mixmoment" + extens_adj + ".sim";    
    std::string wpath_b     = dir + "/mweight" + extens_adj + ".sim";
    std::string mupath_b    = dir + "/mmean" + extens_adj + ".sim";       
    std::string sigmapath_b = dir + "/gspline" + extens_adj + ".sim";
    std::ifstream kfile_b, wfile_b, mufile_b, sigmafile_b;

    openRegresFiles(betafile, Dfile, betapath, Dpath, *skip + 1, beta->nbeta(), beta->nRandom(), reff_NORMAL);    /* skip also header */
    if (*version == 32){     
      openD32File(D32file, D32path, *skip + 1);     /* skip also header */
    }
    else{    
      if (beta->nRandom() && !reff_NORMAL){
        openGsplineFiles(kfile_b, wfile_b, mufile_b, sigmafile_b, kpath_b, wpath_b, mupath_b, sigmapath_b, *skip + 1);
      }
    }

    /*** Reset averages ***/
    resetAverage(averDens, nobs, ngrid, predDens);
    resetAverage(averS, nobs, ngrid, predS);
    resetAverage(averHaz, nobs, ngrid, predHaz);
    resetAverage(averCumHaz, nobs, ngrid, predCumHaz);

    /*** Loop over McMC iterations ***/
    double *vvDens   = valDens;
    double *vvS      = valS;
    double *vvHaz    = valHaz;
    double *vvCumHaz = valCumHaz;
    const int *shift_pointer_inEval = (*onlyAver ? &ONE_INT : &M_now_max);
    
    if (*skip >= *M) throw returnR("More McMC iterations should be skipped than available", 1);    
    readGsplineFromFiles2(&k_effect, w_marg, mu_sig_marg, gamma, sigma, delta, intcpt, scale, delta_sig, 0, *skip, 
                          *dim, *total_length, GsplK,
                          kfile, wfile, mufile, sigmafile, kpath, wpath, mupath, sigmapath);
    readRegresFromFiles(beta, DD, 0, *skip, betafile, Dfile, betapath, Dpath, reff_NORMAL);
    if (*version == 32){
      readDfromFile(db, 0, *skip, D32file, D32path);
      predict_db(db);
      linPred_GS(linPred, beta, dbval, X, nwithin, nobs, ncluster);
    }
    else{
      if (beta->nRandom()){
        if (reff_NORMAL){
          bb->predictNormalRE(beta, DD);
        }
        else{
          readGsplineFromFiles3(&k_effect_b, cum_w_b, prop_mu_b, sig_scale_b, 0, *skip, *dim_b, *total_length_b,
                                kfile_b, wfile_b, mufile_b, sigmafile_b, kpath_b, wpath_b, mupath_b, sigmapath_b);
          bb->predictGspl_intcpt(&k_effect_b, cum_w_b, prop_mu_b, sig_scale_b, rM_b);
        }
      }
      linPred_GS(linPred, beta, bb->bMP(), X, nwithin, nobs, ncluster);
    }
    evalPredFuns(averDens, averS, averHaz, averCumHaz, vvDens, vvS, vvHaz, vvCumHaz, obsdims, nobs, ngrid, gridA, loggridA,
                 linPred, dim, Glength, w_marg, mu_sig_marg, intcpt, sigma, scale, inv_sig_scale, predictP, &_zero_weight,
                 shift_pointer_inEval);

    *M_now = 1;

    int by_1 = *by - 1;
    int jump_value = (*onlyAver ? 0 : 1);
    int backs = 0;
    Rprintf("Iteration ");
    for (int iter = *skip + 1 + (*by); iter <= *M; iter += (*by)){
      if (*M_now >= M_now_max) throw returnR("Error: Higher sample size would be used than indicated", 1);
      if (*predDens)   vvDens += jump_value;
      if (*predS)      vvS += jump_value;
      if (*predHaz)    vvHaz += jump_value;
      if (*predCumHaz) vvCumHaz += jump_value;
      readGsplineFromFiles2(&k_effect, w_marg, mu_sig_marg, gamma, sigma, delta, intcpt, scale, delta_sig, by_1, iter, 
                            *dim, *total_length, GsplK,
                            kfile, wfile, mufile, sigmafile, kpath, wpath, mupath, sigmapath);
      readRegresFromFiles(beta, DD, by_1, iter, betafile, Dfile, betapath, Dpath, reff_NORMAL);
      if (*version == 32){
        readDfromFile(db, by_1, iter, D32file, D32path);
        predict_db(db);
        linPred_GS(linPred, beta, dbval, X, nwithin, nobs, ncluster);
      }
      else{
        if (beta->nRandom()){
          if (reff_NORMAL){
            bb->predictNormalRE(beta, DD);
          }
          else{
            readGsplineFromFiles3(&k_effect_b, cum_w_b, prop_mu_b, sig_scale_b, by_1, iter, *dim_b, *total_length_b,
                                  kfile_b, wfile_b, mufile_b, sigmafile_b, kpath_b, wpath_b, mupath_b, sigmapath_b);
            bb->predictGspl_intcpt(&k_effect_b, cum_w_b, prop_mu_b, sig_scale_b, rM_b);
          }
        }
        linPred_GS(linPred, beta, bb->bMP(), X, nwithin, nobs, ncluster);
      }
      evalPredFuns(averDens, averS, averHaz, averCumHaz, 
                   vvDens, vvS, vvHaz, vvCumHaz, 
                   obsdims, nobs, ngrid, gridA, loggridA,
                   linPred, dim, Glength, w_marg, mu_sig_marg, intcpt, sigma, scale, inv_sig_scale, predictP, &_zero_weight,
                   shift_pointer_inEval);
      (*M_now)++;

      if (!(iter % (*nwrite)) || iter == *M){
        for (i = 0; i < backs; i++) Rprintf("\b");
        Rprintf("%d", iter);
        backs = int(log10(double(iter))) + 1;
      }
    }    /** end of the while over iterations **/
    Rprintf("\n");
         
    /*** Close files with simulated G-splines and regression quantities ***/
    closeGsplineFiles(kfile, wfile, mufile, sigmafile);
    closeRegresFiles(betafile, Dfile, beta->nbeta(), beta->nRandom(), reff_NORMAL);
    if (*version == 32){
      D32file.close();
    }
    else{
      if (beta->nRandom() && !reff_NORMAL) closeGsplineFiles(kfile_b, wfile_b, mufile_b, sigmafile_b);
    }

    /*** McMC averages ***/
    cumsum2average(averDens, M_now, nobs, ngrid, predDens);
    cumsum2average(averS, M_now, nobs, ngrid, predS);
    cumsum2average(averHaz, M_now, nobs, ngrid, predHaz);
    cumsum2average(averCumHaz, M_now, nobs, ngrid, predCumHaz);

    /*** Indeces of quantile values in sampled chain (indexing starting from 0)   ***/
    // indquant1, indquant2 ..... quantile = q*sample[indquant1] + (1-q)sample[indquant2]
    //
    int *indquant1 = &itemp;
    int *indquant2 = &itemp;
    if (!(*onlyAver)){
      indquant1  = (int*) calloc(*nquant, sizeof(int));
      indquant2  = (int*) calloc(*nquant, sizeof(int));
      if (!indquant1 || !indquant2) throw returnR("Error Not enough memory available in predictive_GS (indquant1/indquant2)", 1);
      for (i = 0; i < *nquant; i++){
        if (probsA[i] < 0 || probsA[i] > 1) throw returnR("Error: Incorrect probs values supplied.", 1);
        if (probsA[i] <= 0) indquant1[i] = indquant2[i] = 0;
        else{
          if (probsA[i] >= 1) indquant1[i] = indquant2[i] = *M_now - 1;
          else{
            tmpd = probsA[i] * double(*M_now);
            if (fabs(tmpd - floor(tmpd + 1e-8)) < 1e-8){
              indquant1[i] = int(floor(tmpd)) - 1;
              indquant2[i] = int(floor(tmpd));
            }
            else{
              indquant1[i] = indquant2[i] = int(floor(tmpd));
            }
          }
	}
      }
      Rprintf("\nComputing quantiles.");
      value2quantile(valDens, quantDens, probsA, indquant1, indquant2, nquant, M_now, nobs, ngrid, predDens, shift_pointer_inEval);
      value2quantile(valS, quantS, probsA, indquant1, indquant2, nquant, M_now, nobs, ngrid, predS, shift_pointer_inEval);
      value2quantile(valHaz, quantHaz, probsA, indquant1, indquant2, nquant, M_now, nobs, ngrid, predHaz, shift_pointer_inEval);
      value2quantile(valCumHaz, quantCumHaz, probsA, indquant1, indquant2, nquant, M_now, nobs, ngrid, predCumHaz, shift_pointer_inEval);
    }

    PutRNGstate();

    /*** Cleaning ***/
    if (!(*onlyAver)){
      free(indquant1);
      free(indquant2);
    }

    for (j = 0; j < *dim; j++){
      free(w_marg[j]);   
      free(mu_sig_marg[j]);
    }    
    free(w_marg);    
    free(mu_sig_marg);
    free(sigma);     
    free(gamma);   
    free(delta);     
    free(inv_sig_scale);
    free(intcpt);    
    free(scale);   
    free(delta_sig);
    free(Glength);

    free(linPred);

    delete DD;
   
    if (*version == 32){
      free(bval);
      free(dval);
    }
    else{
      if (beta->nRandom()){
        if (reff_NORMAL){
	  //        delete DD;
        }
        else{
          free(sig_scale_b);
          free(prop_mu_b);
          free(cum_w_b);
          free(rM_b);
        }
      }
    }
    delete db;
    delete bb;
    delete beta;

    return; 
  }
  catch(returnR rr){
    *errP = rr.errflag();
    PutRNGstate();
    return;
  }
}
/******************************************************************************
** entry point for the mex call
** nlhs - number of outputs
** plhs - pointer to array of outputs
** nrhs - number of inputs
** prhs - pointer to array of inputs
******************************************************************************/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  /*************************************************************
  ** this function takes 4-6 arguments:
  ** flag = which algorithm to use,
  ** k = number of features to select,
  ** featureMatrix[][] = matrix of features,
  ** classColumn[] = targets,
  ** optionalParam1 = (path angle or beta value),
  ** optionalParam2 = (gamma value),
  ** the arguments should all be discrete integers.
  ** and has one output:
  ** selectedFeatures[] of size k
  *************************************************************/
  
  int flag, k; 
  double optionalParam1, optionalParam2;
  int numberOfFeatures, numberOfSamples, numberOfTargets;
  double *featureMatrix, *targets, *output, *outputFeatures;

  double entropyTest;
  int i,j;

  /************************************************************
  ** number to function map
  ** 1 = MIFS
  ** 2 = mRMR
  ** 3 = CMIM
  ** 4 = JMI
  ** 5 = DISR
  ** 6 = CIFE
  ** 7 = ICAP
  ** 8 = CondRed
  ** 9 = BetaGamma
  ** 10 = CMI
  *************************************************************/
  if (nlhs > 1)
  {
    printf("Incorrect number of output arguments");
  }/*if not 1 output*/
  if ((nrhs < 4) || (nrhs > 6))
  {
    printf("Incorrect number of input arguments");
    return;
  }/*if not 4-6 inputs*/
 
  /*get the flag for which algorithm*/
  flag = (int) mxGetScalar(prhs[0]);

  /*get the number of features to select, cast out as it is a double*/
  k = (int) mxGetScalar(prhs[1]);

  numberOfFeatures = mxGetN(prhs[2]);
  numberOfSamples = mxGetM(prhs[2]);
  
  numberOfTargets = mxGetM(prhs[3]);

  if (nrhs == 6)
  {
    optionalParam1 = (double) mxGetScalar(prhs[4]);
    optionalParam2 = (double) mxGetScalar(prhs[5]);
  }
  else if (nrhs == 5)
  {
    optionalParam1 = (double) mxGetScalar(prhs[4]);
    optionalParam2 = 0.0;
  }
  
  if (numberOfTargets != numberOfSamples)
  {
    printf("Number of targets must match number of samples\n");
    printf("Number of targets = %d, Number of Samples = %d, Number of Features = %d\n",numberOfTargets,numberOfSamples,numberOfFeatures);
    
    plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL);
    return;
  }/*if size mismatch*/
  else if ((k < 1) || (k > numberOfFeatures))
  {
      printf("You have requested k = %d features, which is not possible\n",k);
      plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL);
      return;
  }
  else
  {
    featureMatrix = mxGetPr(prhs[2]);
    targets = mxGetPr(prhs[3]);
        
    /*double calculateEntropy(double *dataVector, int vectorLength)*/
    entropyTest = calculateEntropy(targets,numberOfSamples);
    if (entropyTest < 0.0000001)
    {
      printf("The class label Y has entropy of 0, therefore all mutual informations containing Y will be 0. No feature selection is performed\n");
      plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL);
      return;
    }
    else
    { 
        /*printf("Flag = %d, k = %d, numFeatures = %d, numSamples = %d\n",flag,k,numberOfFeatures,numberOfSamples);*/
        switch (flag)
        {
            case 1: /* MIFS */
            {
                plhs[0] = mxCreateDoubleMatrix(k,1,mxREAL);
                output = (double *)mxGetPr(plhs[0]);
                if (nrhs == 4)
                { 
                    /* MIFS is Beta = 1, Gamma = 0 */
                    optionalParam1 = 1.0;
                    optionalParam2 = 0.0;
                }

                /*void BetaGamma(int k, long noOfSamples, long noOfFeatures,double *featureMatrix, double *classColumn, double *outputFeatures, double beta, double gamma)*/
                BetaGamma(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output,optionalParam1,optionalParam2);

                incrementVector(output,k);
                break;
            }
            case 2: /* mRMR */
            {
                plhs[0] = mxCreateDoubleMatrix(k,1,mxREAL);
                output = (double *)mxGetPr(plhs[0]);
                
                /*void mRMR_D(int k, int noOfSamples, int noOfFeatures,double *featureMatrix, double *classColumn, double *outputFeatures)*/
                mRMR_D(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output);

                incrementVector(output,k);
                break;
            }
            case 3: /* CMIM */
            {
                plhs[0] = mxCreateDoubleMatrix(k,1,mxREAL);
                output = (double *)mxGetPr(plhs[0]);
                
                /*void CMIM(int k, int noOfSamples, int noOfFeatures,double *featureMatrix, double *classColumn, double *outputFeatures)*/
                CMIM(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output);

                incrementVector(output,k);
                break;
            }
            case 4: /* JMI */
            {
                plhs[0] = mxCreateDoubleMatrix(k,1,mxREAL);
                output = (double *)mxGetPr(plhs[0]);
               
                /*void JMI(int k, int noOfSamples, int noOfFeatures,double *featureMatrix, double *classColumn, double *outputFeatures)*/
                JMI(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output);

                incrementVector(output,k);
                break;
            }
            case 5: /* DISR */
            {
                plhs[0] = mxCreateDoubleMatrix(k,1,mxREAL);
                output = (double *)mxGetPr(plhs[0]);
                
                /*void DISR(int k, int noOfSamples, int noOfFeatures,double *featureMatrix, double *classColumn, double *outputFeatures)*/
                DISR(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output);

                incrementVector(output,k);
                break;
            }
            case 6: /* CIFE */
            {
                plhs[0] = mxCreateDoubleMatrix(k,1,mxREAL);
                output = (double *)mxGetPr(plhs[0]);
               
                /* CIFE is Beta = 1, Gamma = 1 */
                optionalParam1 = 1.0;
                optionalParam2 = 1.0;

                /*void BetaGamma(int k, long noOfSamples, long noOfFeatures,double *featureMatrix, double *classColumn, double *outputFeatures, double beta, double gamma)*/
                BetaGamma(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output,optionalParam1,optionalParam2);

                incrementVector(output,k);
                break;
            }
            case 7: /* ICAP */
            {
                plhs[0] = mxCreateDoubleMatrix(k,1,mxREAL);
                output = (double *)mxGetPr(plhs[0]);
                
                /*void ICAP(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output);*/
                ICAP(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output);

                incrementVector(output,k);
                break;
            }
            case 8: /* CondRed */
            {
                plhs[0] = mxCreateDoubleMatrix(k,1,mxREAL);
                output = (double *)mxGetPr(plhs[0]);
               
                /* CondRed is Beta = 0, Gamma = 1 */
                optionalParam1 = 0.0;
                optionalParam2 = 1.0;

                /*void BetaGamma(int k, long noOfSamples, long noOfFeatures,double *featureMatrix, double *classColumn, double *outputFeatures, double beta, double gamma)*/
                BetaGamma(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output,optionalParam1,optionalParam2);

                incrementVector(output,k);
                break;
            }
            case 9: /* BetaGamma */
            {
                if (nrhs != 6)
                {
                    printf("Insufficient arguments specified for Beta Gamma FS\n");
                    plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL);
                    return;
                }
                else
                {
                    plhs[0] = mxCreateDoubleMatrix(k,1,mxREAL);
                    output = (double *)mxGetPr(plhs[0]);
                
                    /*void BetaGamma(int k, long noOfSamples, long noOfFeatures,double *featureMatrix, double *classColumn, double *outputFeatures, double beta, double gamma)*/
                    BetaGamma(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output,optionalParam1,optionalParam2);
                    
                    incrementVector(output,k);
                }
                break;
            }
            case 10: /* CMI */
            {
                output = (double *)mxCalloc(k,sizeof(double));

                /*void CondMI(int k, int noOfSamples, int noOfFeatures,double *featureMatrix, double *classColumn, double *outputFeatures)*/
                CondMI(k,numberOfSamples,numberOfFeatures,featureMatrix,targets,output);

                i = 0;

                while((output[i] != -1) && (i < k))
                {
                    i++;
                }

                plhs[0] = mxCreateDoubleMatrix(i,1,mxREAL);
                outputFeatures = (double *)mxGetPr(plhs[0]);

                for (j = 0; j < i; j++)
                {
                    outputFeatures[j] = output[j] + 1; /*C indexes from 0 not 1*/
                }/*for number of selected features*/

                mxFree(output);
                output = NULL;
                break;
            }
        }/*switch on flag*/
        return;
    }
  }
}/*mex function entry*/