Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

  • 99b3d68
  • /
  • src
  • /
  • test-nmmin.cpp
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
content badge
swh:1:cnt:a953a17ef643c785a103f99bb9c82a1b81c4c169
directory badge
swh:1:dir:bba5b58e2bad46df47c42d4594f042f68c7d4aab

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
test-nmmin.cpp
#include <RcppArmadillo.h>
#include <vector>
#include <map>
#include "c_optim.h"

namespace rstpm2 {

  using namespace Rcpp;
  using namespace arma;

  // typedefs

  typedef bool constraintfn(int, double *, void *);

  // Hadamard element-wise multiplication for the _columns_ of a matrix with a vector

  mat rmult(mat m, vec v) {
    mat out(m);
    out.each_col() %= v;
    return out;
  }
  mat lmult(vec v, mat m) {
    return rmult(m,v);
  }

  // element-wise multiplication and division for NumericVector and arma::vec

  NumericVector ew_mult(NumericVector nv, vec v) {
    return as<NumericVector>(wrap(as<vec>(wrap(nv)) % v));
  }

  NumericVector ew_div(NumericVector nv, vec v) {
    return as<NumericVector>(wrap(as<vec>(wrap(nv)) / v));
  }

  void Rprint(NumericMatrix m) {
    for (int i=0; i<m.nrow(); ++i) {
      for (int j=0; j<m.ncol(); ++j) 
	Rprintf("%f ", m(i,j));
      Rprintf("\n");
    }
  }

  void Rprint(NumericVector v) {
    for (int i=0; i<v.size(); ++i) 
      Rprintf("%f ", v(i));
    Rprintf("\n");
  }

  void Rprint(vec v) {
    for (size_t i=0; i<v.size(); ++i) 
      Rprintf("%f ", v(i));
    Rprintf("\n");
  }
  void Rprint(rowvec v) {
    for (size_t i=0; i<v.size(); ++i) 
      Rprintf("%f ", v(i));
    Rprintf("\n");
  }

  void Rprint(mat m) {
    for (size_t i=0; i<m.n_rows; ++i) {
      for (size_t j=0; j<m.n_cols; ++j) 
	Rprintf("%f ", m(i,j));
      Rprintf("\n");
    }
  }

  vec pnorm01(vec x) {
    vec out(x.size());
    for (size_t i=0; i<x.size(); ++i)
      out(i) = R::pnorm(x(i),0.0,1.0,1,0);
    return out;
    //return as<vec>(wrap(pnorm(as<NumericVector>(wrap<vec>(x)),0.0,1.0)));
  }

  vec qnorm01(vec x) {
    vec out(x.size());
    for (size_t i=0; i<x.size(); ++i)
      out(i) = R::qnorm(x(i),0.0,1.0,1,0);
    return out;
  }

  vec dnorm01(vec x) {
    vec out(x.size());
    for (size_t i=0; i<x.size(); ++i)
      out(i) = R::dnorm(x(i),0.0,1.0,0);
    return out;
  }

  vec logit(vec p) {
    return log(p/(1-p));
  }

  vec expit(vec x) {
    return 1/(1+exp(-x));
  }

  RcppExport SEXP tapplySum(SEXP s_y, SEXP s_group) {
    NumericVector y(s_y);
    NumericVector group(s_group);
    NumericVector::iterator iy, igroup;
    std::map<double,double> out;
    for (iy = y.begin(), igroup = group.begin(); iy != y.end(); ++iy, ++igroup) { 
	out[*igroup] += *iy;
    }
    return wrap(out);
  }

  // Q: do we need parscale, trace, reltol and criterion in these structs?

  class stpm2 {
  public:
    stpm2(SEXP sexp) {
      List list = as<List>(sexp);
      init = as<NumericVector>(list["init"]);
      X = as<mat>(list["X"]); 
      XD = as<mat>(list["XD"]); 
      bhazard = as<vec>(list["bhazard"]);
      wt = as<vec>(list["wt"]);
      event = as<vec>(list["event"]);
      time = as<vec>(list["time"]);
      delayed = as<int>(list["delayed"]);
      X0.set_size(1,1); X0.fill(0.0);
      wt0.set_size(1); wt0.fill(0.0);
      if (delayed == 1) {
	X0 = as<mat>(list["X0"]); // optional
	XD0 = as<mat>(list["XD0"]); // optional
	wt0 = as<vec>(list["wt0"]); // optional
      }
      parscale = as<vec>(list["parscale"]);
      reltol = as<double>(list["reltol"]);
      kappa = as<double>(list["kappa"]);
      trace = as<int>(list["trace"]);
    }
    // defaults are for the PH model
    virtual vec link(vec S) { return log(-log(S)); }
    virtual vec ilink(vec x) { return exp(-exp(x)); }
    virtual vec h(vec eta, vec etaD) { return etaD % exp(eta); }
    virtual vec H(vec eta, vec etaD) { return exp(eta); }
    virtual mat gradH(vec eta, vec etaD, mat X, mat XD) { return rmult(X,exp(eta)); }
    virtual mat gradh(vec eta, vec etaD, mat X, mat XD) { 
      return rmult(XD, exp(eta)) + rmult(X, etaD % exp(eta));
    }
    virtual double negll(NumericVector beta);
    virtual void grad_negll(NumericVector beta);
    NumericVector init;
    mat X, XD, X0, XD0; 
    vec bhazard,wt,wt0,event,time,parscale;
    double reltol, kappa;
    int delayed, trace;
  };

  double stpm2::negll(NumericVector beta) {
    int n = init.size();
    vec vbeta(&beta[0],n);
    vbeta = vbeta % parscale;
    vec eta = X * vbeta;
    vec etaD = XD * vbeta;
    vec h = this->h(eta,etaD) + bhazard;
    vec H = this->H(eta,etaD) + bhazard;
    double constraint = kappa/2.0 * sum(h % h % (h<0)); // sum(h^2 | h<0)
    vec eps = h*0.0 + 1.0e-16; 
    h = max(h,eps);
    double ll = sum(wt % event % log(h)) - sum(wt % H) - constraint;
    if (delayed == 1) {
      vec eta0 = X0 * vbeta;
      vec etaD0 = XD0 * vbeta;
      mat H0 = this->H(eta0,etaD0);
      ll += sum(wt0 % H0);
    }
    return -ll;  
  }

  void stpm2::grad_negll(NumericVector beta) {
    int n = beta.size();
    vec vbeta = as<vec>(wrap(beta));
    vbeta = vbeta % parscale;
    vec eta = X * vbeta;
    vec etaD = XD * vbeta;
    vec h = this->h(eta,etaD) + bhazard;
    // vec H = exp(eta);
    mat gradH = this->gradH(eta,etaD,X,XD);
    mat gradh = this->gradh(eta,etaD,X,XD);
    mat Xgrad = -gradH + rmult(gradh, event / h);
    mat Xconstraint = - kappa*rmult(gradh,h);
    vec eps = h*0.0 + 1.0e-16; // hack
    //Xgrad.rows(h<=eps) = Xconstraint.rows(h<=eps);
    Xgrad = rmult(Xgrad,wt);
    rowvec vgr = sum(Xgrad,0);
    if (delayed == 1) {
      vec eta0 = X0 * vbeta;
      vec etaD0 = XD0 * vbeta;
      mat gradH0 = this->gradH(eta0, etaD0, X0, XD0); 
      vgr += sum(rmult(gradH0, wt0),0);
    }
    for (int i = 0; i<n; ++i) {
      // gr[i] = -vgr[i]*parscale[i];
    }
  }


  class stpm2PO : public stpm2 {
  public:
    stpm2PO(SEXP sexp) : stpm2(sexp) { }
    vec link(vec S) { return -logit(S); }
    vec ilink(vec x) { return expit(-x); }
    vec h(vec eta, vec etaD) { return etaD % exp(eta) % expit(-eta); }
    vec H(vec eta, vec etaD) { return log(1+exp(eta)); }
    mat gradH(vec eta, vec etaD, mat X, mat XD) { 
      return rmult(X,exp(eta) % expit(-eta));
    }
    mat gradh(vec eta, vec etaD, mat X, mat XD) { 
      return rmult(X, etaD % exp(eta) % expit(-eta)) - 
	rmult(X, exp(2*eta) % etaD % expit(-eta) % expit(-eta)) +
	rmult(XD, exp(eta) % expit(-eta));
    }
  };

  class stpm2Probit : public stpm2 {
  public:
    stpm2Probit(SEXP sexp) : stpm2(sexp) { }
    vec link(vec S) { return -qnorm01(S); }
    vec ilink(vec eta) { return pnorm01(-eta); }
    vec H(vec eta, vec etaD) { return -log(pnorm01(-eta)); }
    vec h(vec eta, vec etaD) { return etaD % dnorm01(eta) / pnorm01(-eta); }
    mat gradH(vec eta, vec etaD, mat X, mat XD) { 
      return rmult(X, dnorm01(eta) / pnorm01(-eta));
    }
    mat gradh(vec eta, vec etaD, mat X, mat XD) { 
      return rmult(X, -eta % dnorm01(eta) % etaD / pnorm01(-eta)) +
	rmult(X, dnorm01(eta) % dnorm01(eta) / pnorm01(-eta) / pnorm01(-eta) % etaD) +
	rmult(XD,dnorm01(eta) / pnorm01(-eta));
    }
  };
  
  class stpm2AH : public stpm2 {
  public:
    stpm2AH(SEXP sexp) : stpm2(sexp) { }
    vec link(vec S) { return -log(S); }
    vec ilink(vec x) { return exp(-x); }
    vec h(vec eta, vec etaD) { return etaD; }
    vec H(vec eta, vec etaD) { return eta; }
    mat gradh(vec eta, vec etaD, mat X, mat XD) { return XD; }
    mat gradH(vec eta, vec etaD, mat X, mat XD) { return X;  }
  };

  struct SmoothLogH {
    int first_para, last_para;
    mat S;
  };

  struct SmoothHaz {
    mat X0, X1, X2, X3;
    vec w;
    double lambda;
  };

  template<class Smooth>
  std::vector<Smooth> read_smoothers(List lsmooth) {}

  template<>
  std::vector<SmoothLogH> read_smoothers(List lsmooth) {
    std::vector<SmoothLogH> smooth;
    for(int i=0; i<lsmooth.size(); ++i) {
      List lsmoothi = as<List>(lsmooth[i]);
      List lsmoothiS = as<List>(lsmoothi["S"]);
      SmoothLogH smoothi =  {
	as<int>(lsmoothi["first.para"]) - 1, 
	as<int>(lsmoothi["last.para"]) - 1, 
	as<mat>(lsmoothiS[0])
      };
      smooth.push_back(smoothi);
    }
    return smooth;
  }

  template<>
  std::vector<SmoothHaz> read_smoothers(List lsmooth) {
    std::vector<SmoothHaz> smooth;
    for(int i=0; i<lsmooth.size(); ++i) {
      List lsmoothi = as<List>(lsmooth[i]);
      SmoothHaz smoothi =  {
	as<mat>(lsmoothi["X0"]), 
	as<mat>(lsmoothi["X1"]), 
	as<mat>(lsmoothi["X2"]), 
	as<mat>(lsmoothi["X3"]), 
	as<vec>(lsmoothi["w"]), 
	as<double>(lsmoothi["lambda"])
      };
      smooth.push_back(smoothi);
    }
    return smooth;
  }

  template<class Smooth, class Stpm2 = stpm2>
  class pstpm2 : public Stpm2 {
  public:
    pstpm2(SEXP sexp) : Stpm2(sexp) {
      List list = as<List>(sexp);
      List lsmooth = as<List>(list["smooth"]);
      sp = as<NumericVector>(list["sp"]);
      reltol_search = as<double>(list["reltol_search"]);
      // reltol = as<double>(list["reltol"]);
      alpha = as<double>(list["alpha"]);
      criterion = as<int>(list["criterion"]);
      smooth = read_smoothers<Smooth>(lsmooth);
    }
    NumericVector sp;
    double alpha, reltol_search; 
    int criterion;
    std::vector<Smooth> smooth;
  };

  /** 
      Extension of stpm2 and pstpm2 to include shared frailties with a cluster variable
  **/
  template<class Stpm2>
  class stpm2Shared : public Stpm2 {
  public:
    stpm2Shared(SEXP sexp) : Stpm2(sexp) {
      List list = as<List>(sexp);
      IntegerVector cluster = as<IntegerVector>(list["cluster"]);
      // wragged array indexed by a map of vectors
      for (int i=0; i<cluster.size(); ++i) {
	clusters[cluster[i]].push_back(i);
      }
    }
    std::map<int,std::vector<int> > clusters;
  };


  /**
     Extension to the BFGS class

     optim() and calc_hessian() assume that data->parscale is an array/vector/NumericVector
     optimWithConstraint() further assumes that data->kappa is a double with an initial value
   */
  template<class Data>
  class BFGS2 : public BFGS {
  public:
    void optim(optimfn fn, optimgr gr, NumericVector init, void * ex,
	       bool apply_parscale = true) {
      Data * data = (Data *) ex;
      n = init.size();
      if (apply_parscale) for (int i = 0; i<n; ++i) init[i] /= data->parscale[i];
      BFGS::optim(fn,gr,init,ex);
      if (apply_parscale) for (int i = 0; i<n; ++i) coef[i] *= data->parscale[i];
      hessian = calc_hessian(gr, ex);
    }
    void optimWithConstraint(optimfn fn, optimgr gr, NumericVector init, void * ex, constraintfn constraint,
			     bool apply_parscale = true) {
      Data * data = (Data *) ex;
      n = init.size();
      if (apply_parscale) for (int i = 0; i<n; ++i) init[i] /= data->parscale[i];
      bool satisfied;
      do {
	BFGS::optim(fn,gr,init,ex);
	satisfied = constraint(n,&coef[0],ex);
	if (!satisfied) data->kappa *= 2.0;   
      } while ((!satisfied)&& data->kappa < 1.0e3);      
      if (apply_parscale) for (int i = 0; i<n; ++i) coef[i] *= data->parscale[i];
      hessian = calc_hessian(gr, ex);
   // Rprintf("kappa=%f\n",data->kappa);
    }
    NumericMatrix calc_hessian(optimgr gr, void * ex) {
      Data * data = (Data *) ex;
      vec parscale(n);
      for (int i=0; i<n; ++i) {
	parscale[i] = data->parscale[i];
	data->parscale[i] = 1.0;
      }
      NumericMatrix hessian = BFGS::calc_hessian(gr,ex);
      for (int i=0; i<n; ++i) data->parscale[i] = parscale[i];
      return hessian;
    }
  };

  template<class Data>
  double fminfn(int n, double * beta, void *ex) {
    Data * data = (Data *) ex;
    vec vbeta(beta,n);
    vbeta = vbeta % data->parscale;
    vec eta = data->X * vbeta;
    vec etaD = data->XD * vbeta;
    vec h = data->h(eta,etaD) + data->bhazard;
    vec H = data->H(eta,etaD);
    double constraint = data->kappa/2.0 * sum(h % h % (h<0)) + 
      data->kappa/2.0 * sum((H/data->time) % (H/data->time) % (H<0));
    vec eps = h*0.0 + 1.0e-16; 
    h = max(h,eps);
    H = max(H,eps);
    double ll = sum(data->wt % data->event % log(h)) - sum(data->wt % H) - constraint;
    if (data->delayed == 1) {
      vec eta0 = data->X0 * vbeta;
      vec etaD0 = data->XD0 * vbeta;
      mat H0 = data->H(eta0,etaD0);
      ll += sum(data->wt0 % H0);
    }
    return -ll;  
  }

  /** 
      Objective function for a Gamma shared frailty
      Assumes that weights == 1.
      The implementation is incomplete, requiring either the use of optimisation without
      gradients or the calculation of the gradients.
  **/
  template<class Data>
  double fminfnShared(int n, double * beta, void *ex) {
    typedef std::vector<int> Index;
    typedef std::map<int,Index> IndexMap;
    Data * data = (Data *) ex;
    vec vbeta(beta,n-1); // theta is the last parameter in beta
    double theta = beta[n-1];
    vbeta = vbeta % data->parscale;
    vec eta = data->X * vbeta;
    vec etaD = data->XD * vbeta;
    vec h = data->h(eta,etaD) + data->bhazard;
    vec H = data->H(eta,etaD) + data->bhazard;
    double constraint = data->kappa/2.0 * sum(h % h % (h<0)); // sum(h^2 | h<0)
    vec eps = h*0.0 + 1.0e-16; 
    h = max(h,eps);
    mat H0;
    //double ll = sum(data->wt % data->event % log(h)) - sum(data->wt % H) - constraint;
    if (data->delayed == 1) {
      vec eta0 = data->X0 * vbeta;
      vec etaD0 = data->XD0 * vbeta;
      H0 = data->H(eta0,etaD0);
      //ll += sum(data->wt0 % H0);
    }
    double ll;
    for (IndexMap::iterator it=data->clusters.begin(); it!=data->clusters.end(); ++it) {
      int mi=0;
      double sumH = 0.0, sumHenter = 0.0;
      for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) {
	if (data->event(*j)==1) {
	  mi++;
	  ll += log(h(*j));
	}
	sumH += H(*j);
	if (data->delayed == 1)
	  sumHenter += H0(*j);
      }
      ll -= (1.0/theta+mi)*log(1.0+theta*sumH);
      if (data->delayed == 1)
	ll += 1.0/theta*log(1.0+theta*sumHenter);
      if (mi>0) {
	int k=1;
	for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) {
	  if (data->event(*j)==1) {
	    ll += log(1.0+theta*(mi-k));
	    k++;
	  }
	}
      }
    }
    ll -= constraint;
    return -ll;  
  }

  /** 
      Utility function for calculating a gamma frailty log-likelihood within R code 
   **/
  RcppExport SEXP llgammafrailty(SEXP _theta, SEXP _h, SEXP _H, SEXP _d,
				    SEXP _cluster) {
    double theta = as<double>(_theta);
    NumericVector h = as<NumericVector>(_h);
    NumericVector H = as<NumericVector>(_H);
    IntegerVector d = as<IntegerVector>(_d);
    IntegerVector cluster = as<IntegerVector>(_cluster);
    double ll = 0.0;
    // wragged array indexed by a map of vectors
    typedef std::vector<int> Index;
    typedef std::map<int,Index> IndexMap;
    IndexMap clusters;
    for (int i=0; i<cluster.size(); ++i) {
      clusters[cluster[i]].push_back(i);
    }
    for (IndexMap::iterator it=clusters.begin(); it!=clusters.end(); ++it) {
      int mi=0;
      double sumH = 0.0;
      for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) {
	if (d[*j]==1) {
	  mi++;
	  ll += log(h[*j]);
	}
	sumH += H[*j];
	// sumHenter += Henter[*j];
      }
      ll -= (1.0/theta+mi)*log(1.0+theta*sumH);
      // ll += 1.0/theta*log(1.0+theta*sumHenter);
      if (mi>0) {
	int k=1;
	for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) {
	  if (d[*j]==1) {
	    ll += log(1.0+theta*(mi-k));
	    k++;
	  }
	}
      }
    }
    return wrap(ll);
  }

  /** 
      Utility function for calculating a gamma frailty log-likelihood within R code 
   **/
  RcppExport SEXP llgammafrailtydelayed(SEXP _theta, SEXP _h, SEXP _H, SEXP _H0, SEXP _d,
				    SEXP _cluster) {
    double theta = as<double>(_theta);
    NumericVector h = as<NumericVector>(_h);
    NumericVector H = as<NumericVector>(_H);
    NumericVector H0 = as<NumericVector>(_H0); // assumes that _H0 is zero for data not left truncated
    IntegerVector d = as<IntegerVector>(_d);
    IntegerVector cluster = as<IntegerVector>(_cluster);
    double ll = 0.0;
    // wragged array indexed by a map of vectors
    typedef std::vector<int> Index;
    typedef std::map<int,Index> IndexMap;
    IndexMap clusters;
    for (int i=0; i<cluster.size(); ++i) {
      clusters[cluster[i]].push_back(i);
    }
    for (IndexMap::iterator it=clusters.begin(); it!=clusters.end(); ++it) {
      int mi=0;
      double sumH = 0.0, sumHenter = 0.0;
      for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) {
	if (d[*j]==1) {
	  mi++;
	  ll += log(h[*j]);
	}
	sumH += H[*j];
	sumHenter += H0[*j];
      }
      ll -= (1.0/theta+mi)*log(1.0+theta*sumH);
      ll += 1.0/theta*log(1.0+theta*sumHenter);
      if (mi>0) {
	int k=1;
	for (Index::iterator j=it->second.begin(); j!=it->second.end(); ++j) {
	  if (d[*j]==1) {
	    ll += log(1.0+theta*(mi-k));
	    k++;
	  }
	}
      }
    }
    return wrap(ll);
  }


  struct CureModel {
    int n0, n1, n2;
    mat Xshape, Xscale, Xcure;
    vec time, status;
  };

  double fminfn_cureModel(int n, double * beta, void *ex) {
    double ll = 0.0;
    CureModel * data = (CureModel *) ex;
    vec vbeta(beta,n);
    vec shape = exp(data->Xshape * vbeta(span(0,data->n0-1)));
    vec scale = exp(data->Xscale * vbeta(span(data->n0,data->n1-1)));
    vec cure = 1.0/(1.0+exp(-data->Xcure * vbeta(span(data->n1,data->n2-1))));
    for (size_t i=0; i < data->time.size(); ++i) {
      ll += data->status(i)==1.0 ?
	log(1.0-cure(i)) + R::dweibull(data->time(i),shape(i),scale(i),1) :
	log(cure(i)+(1.0-cure(i)) * R::pweibull(data->time(i),shape(i),scale(i),0,0));
    }
    R_CheckUserInterrupt();  /* be polite -- did the user hit ctrl-C? */
    return -ll;
  }

RcppExport SEXP fitCureModel(SEXP stime, SEXP sstatus, SEXP sXshape,
			  SEXP sXscale, SEXP sXcure, SEXP sbeta) {
    mat Xshape = as<mat>(sXshape);
    mat Xscale = as<mat>(sXscale);
    mat Xcure = as<mat>(sXcure);
    vec time = as<vec>(stime);
    vec status = as<vec>(sstatus);
    NumericVector init = as<NumericVector>(sbeta);
    int n0=Xshape.n_cols;
    int n1=n0+Xscale.n_cols;
    int n2=n1+Xcure.n_cols;
    CureModel data = {n0,n1,n2,Xshape,Xscale,Xcure,time,status};
    
    NelderMead nm;
    nm.reltol = 1.0e-8;
    nm.maxit = 1000;
    nm.optim(& fminfn_cureModel, init, (void *) &data);

    for (int i = 0; i<nm.coef.size(); ++i)
      init[i] = nm.coef[i]; // clone
    
    return List::create(_("Fmin")=nm.Fmin, 
			_("coef")=wrap(init),
			_("fail")=nm.fail,
			_("hessian")=wrap(nm.hessian));
  }


  template<class Data>
  bool fminfn_constraint(int n, double * beta, void *ex) {
    Data * data = (Data *) ex;
    vec vbeta(beta,n);
    vbeta = vbeta % data->parscale;
    vec eta = data->X * vbeta;
    vec etaD = data->XD * vbeta;
    vec h = data->h(eta, etaD) + data->bhazard;
    vec H = data->H(eta, etaD);
    return all((h>0) % (H>0));
  }

  template<class Data>
  void fminfn_nlm(int n, double * beta, double * f, void *ex) {
    *f = fminfn<Data>(n, beta, ex);
  };


  // log H penalty - using penalty matrices from mgcv
  template<class Stpm2>
  double pfminfn_SmoothLogH(int n, double * beta, void *ex) {
    typedef SmoothLogH Smooth;
    typedef pstpm2<Smooth,Stpm2> Data;
    double ll = -fminfn<Data>(n,beta,ex);
    Data * data = (Data *) ex;
    vec vbeta(beta,n);
    vbeta = vbeta % data->parscale;
    for (size_t i=0; i < data->smooth.size(); ++i) {
      Smooth smoothi = data->smooth[i];
      ll -= (data->sp)[i]/2 * 
	dot(vbeta.subvec(smoothi.first_para,smoothi.last_para),
	    smoothi.S * vbeta.subvec(smoothi.first_para,smoothi.last_para));
    }
    return -ll;  
  }

  // hazard penalty
  template<class Stpm2>
  double pfminfn_SmoothHaz(int n, double * beta, void *ex) {
    typedef SmoothHaz Smooth;
    typedef pstpm2<Smooth,Stpm2> Data;
    double ll = -fminfn<Data>(n,beta,ex);
    Data * data = (Data *) ex;
    vec vbeta(beta,n);
    vbeta = vbeta % data->parscale;
    for (size_t i=0; i < data->smooth.size(); ++i) {
      Smooth obj = data->smooth[i];
      vec s0 = obj.X0 * vbeta;
      vec s1 = obj.X1 * vbeta;
      vec s2 = obj.X2 * vbeta;
      vec s3 = obj.X3 * vbeta;
      vec h2 = exp(s0) % (s3 + 3*s1%s2 + s1%s1%s1);
      ll -= (data->sp)[i]/2 * obj.lambda * sum(obj.w % h2 % h2);
    }
    return -ll;  
  };

  template<class Data>
  void grfn(int n, double * beta, double * gr, void *ex) {
    Data * data = (Data *) ex;
    vec vbeta(beta,n);
    // if (data->trace) Rprint(vbeta);
    vbeta = vbeta % data->parscale;
    vec eta = data->X * vbeta;
    vec etaD = data->XD * vbeta;
    vec h = data->h(eta,etaD) + data->bhazard;
    vec H = data->H(eta,etaD);
    vec one = ones(h.size());
    vec eps = h*0.0 + 1.0e-16; 
    mat gradH = data->gradH(eta,etaD,data->X,data->XD); 
    mat gradh = data->gradh(eta,etaD,data->X,data->XD); 
    mat Xgrad = -rmult(gradH, one % (H>eps)) + rmult(gradh, data->event / h % (h>eps));
    mat Xconstraint = data->kappa * rmult(gradh,h%(h<eps)) + 
      data->kappa * rmult(gradH,H / data->time / data->time % (H<eps));
    rowvec dconstraint = sum(Xconstraint,0);
    // if (data->trace) Rprint(dconstraint);
    Xgrad = rmult(Xgrad,data->wt);
    rowvec vgr = sum(Xgrad,0);
    if (data->delayed == 1) {
      vec eta0 = data->X0 * vbeta;
      vec etaD0 = data->XD0 * vbeta;
      mat gradH0 = data->gradH(eta0, etaD0, data->X0, data->XD0); 
      vgr += sum(rmult(gradH0, data->wt0),0);
    }
    for (int i = 0; i<n; ++i) {
      gr[i] = -vgr[i]*data->parscale[i] + dconstraint[i];
    }
  }

  template<class Stpm2>
  void pgrfn_SmoothLogH(int n, double * beta, double * gr, void *ex) {
    typedef SmoothLogH Smooth;
    typedef pstpm2<Smooth,Stpm2> Data;
    grfn<Data>(n, beta, gr, ex);
    Data * data = (Data *) ex;
    vec vbeta(beta,n);
    vbeta = vbeta % data->parscale;
    vec eta = data->X * vbeta;
    vec etaD = data->XD * vbeta;
    vec h = data->h(eta,etaD) + data->bhazard;
    vec H = data->H(eta,etaD);
    mat gradh = data->gradh(eta,etaD,data->X,data->XD);
    mat gradH = data->gradH(eta,etaD,data->X,data->XD);
    rowvec vgr(n, fill::zeros);
    for (size_t i=0; i < data->smooth.size(); ++i) {
      SmoothLogH smoothi = data->smooth[i];
      vgr.subvec(smoothi.first_para,smoothi.last_para) += 
	(data->sp)[i] * (smoothi.S * vbeta.subvec(smoothi.first_para,smoothi.last_para)).t();
    }
    for (int i = 0; i<n; ++i) gr[i] += vgr[i]*data->parscale[i];
  }

  template<class Stpm2>
  void pgrfn_SmoothHaz(int n, double * beta, double * gr, void *ex) {
    typedef SmoothHaz Smooth;
    typedef pstpm2<Smooth,Stpm2> Data;
    grfn<Data>(n, beta, gr, ex);
    Data * data = (Data *) ex;
    vec vbeta(beta,n);
    vbeta = vbeta % data->parscale;
    rowvec vgr(n, fill::zeros);
    for (size_t i=0; i < data->smooth.size(); ++i) {
      Smooth obj = data->smooth[i];
      vec s0 = obj.X0 * vbeta;
      vec s1 = obj.X1 * vbeta;
      vec s2 = obj.X2 * vbeta;
      vec s3 = obj.X3 * vbeta;
      vec h2 = exp(s0) % (s3 + 3*s1%s2 + s1%s1%s1);
      mat dh2sq_dbeta = 
	2*lmult(h2 % exp(s0),
		obj.X3+3*(rmult(obj.X1,s2)+rmult(obj.X2,s1))+3*lmult(s1%s1,obj.X1))+
	2*lmult(h2 % h2,obj.X0);
      vgr += (data->sp)[i]*obj.lambda*sum(lmult(obj.w, dh2sq_dbeta),0);
    }
    for (int i = 0; i<n; ++i) gr[i] += vgr[i] * data->parscale[i];
  }

  // oh, for partial template specialisation for functions...

  template<class Smooth,class Stpm2>
  double pfminfn(int n, double * beta, void *ex) { return 0.0; }

  template<>
  double pfminfn<SmoothLogH,stpm2>(int n, double * beta, void *ex) {
    return pfminfn_SmoothLogH<stpm2>(n, beta, ex); }
  template<>
  double pfminfn<SmoothLogH,stpm2PO>(int n, double * beta, void *ex) {
    return pfminfn_SmoothLogH<stpm2PO>(n, beta, ex); }
  template<>
  double pfminfn<SmoothLogH,stpm2Probit>(int n, double * beta, void *ex) {
    return pfminfn_SmoothLogH<stpm2Probit>(n, beta, ex); }
    template<>
  double pfminfn<SmoothLogH,stpm2AH>(int n, double * beta, void *ex) {
    return pfminfn_SmoothLogH<stpm2AH>(n, beta, ex); }

  template<>
  double pfminfn<SmoothHaz,stpm2>(int n, double * beta, void *ex) {
    return pfminfn_SmoothHaz<stpm2>(n, beta, ex); }
  template<>
  double pfminfn<SmoothHaz,stpm2PO>(int n, double * beta, void *ex) {
    return pfminfn_SmoothHaz<stpm2PO>(n, beta, ex); }
  template<>
  double pfminfn<SmoothHaz,stpm2Probit>(int n, double * beta, void *ex) {
    return pfminfn_SmoothHaz<stpm2Probit>(n, beta, ex); }

  template<class Smooth, class Stpm2>
  void pgrfn(int n, double * beta, double * gr, void *ex) { }

  template<>
  void pgrfn<SmoothLogH,stpm2>(int n, double * beta, double * gr, void *ex) {
    pgrfn_SmoothLogH<stpm2>(n, beta, gr, ex); }
  template<>
  void pgrfn<SmoothLogH,stpm2PO>(int n, double * beta, double * gr, void *ex) {
    pgrfn_SmoothLogH<stpm2PO>(n, beta, gr, ex); }
  template<>
  void pgrfn<SmoothLogH,stpm2Probit>(int n, double * beta, double * gr, void *ex) {
    pgrfn_SmoothLogH<stpm2Probit>(n, beta, gr, ex);}
    template<>
  void pgrfn<SmoothLogH,stpm2AH>(int n, double * beta, double * gr, void *ex) {
    pgrfn_SmoothLogH<stpm2AH>(n, beta, gr, ex); }

  template<>
  void pgrfn<SmoothHaz,stpm2>(int n, double * beta, double * gr, void *ex) {
    pgrfn_SmoothHaz<stpm2>(n, beta, gr, ex); }
  template<>
  void pgrfn<SmoothHaz,stpm2PO>(int n, double * beta, double * gr, void *ex) {
    pgrfn_SmoothHaz<stpm2PO>(n, beta, gr, ex); }
  template<>
  void pgrfn<SmoothHaz,stpm2Probit>(int n, double * beta, double * gr, void *ex) {
    pgrfn_SmoothHaz<stpm2Probit>(n, beta, gr, ex); }


  template<class Stpm2>
  SEXP optim_stpm2(SEXP args) {

    Stpm2 data(args);

    BFGS2<Stpm2> bfgs;
    bfgs.reltol = data.reltol;
    bfgs.optimWithConstraint(fminfn<Stpm2>, grfn<Stpm2>, data.init, (void *) &data, fminfn_constraint<Stpm2>);

    return List::create(_("fail")=bfgs.fail,
			_("coef")=wrap(bfgs.coef),
			_("hessian")=wrap(bfgs.hessian));
  }

  RcppExport SEXP optim_stpm2_ph(SEXP args) {
    return optim_stpm2<stpm2>(args); }
  RcppExport SEXP optim_stpm2_po(SEXP args) {
    return optim_stpm2<stpm2PO>(args); }
  RcppExport SEXP optim_stpm2_probit(SEXP args) {
    return optim_stpm2<stpm2Probit>(args); }
  RcppExport SEXP optim_stpm2_ah(SEXP args) {
    return optim_stpm2<stpm2AH>(args); }


  RcppExport SEXP optim_stpm2_nlm(SEXP args) {

    stpm2 data(args);

    data.init = ew_div(data.init,data.parscale);
    int n = data.init.size();
    
    Nlm nlm;
    nlm.gradtl = nlm.steptl = data.reltol;
    //nlm.method=2; nlm.stepmx=0.0;
    bool satisfied;
    do {
      nlm.optim(& fminfn_nlm<stpm2>, & grfn<stpm2>, data.init, (void *) &data);
      satisfied = fminfn_constraint<stpm2>(n,&nlm.coef[0],(void *) &data);
      if (!satisfied) data.kappa *= 2.0;
    } while (!satisfied && data.kappa<1.0e5);

    nlm.coef = ew_mult(nlm.coef, data.parscale);

    return List::create(_("itrmcd")=wrap(nlm.itrmcd),
			_("niter")=wrap(nlm.itncnt),
			_("coef")=wrap(nlm.coef),
			_("hessian")=wrap(nlm.hessian));
  }



  template<class Smooth, class Stpm2>
  double pstpm2_step_first(double logsp, void * ex) {
    typedef pstpm2<Smooth,Stpm2> Data;
    Data * data = (Data *) ex;

    data->sp[0] = exp(logsp);

    BFGS2<Data> bfgs;
    bfgs.reltol = data->reltol;

    bfgs.optimWithConstraint(pfminfn<Smooth,Stpm2>, pgrfn<Smooth,Stpm2>, data->init, ex, fminfn_constraint<Data>, false); // do not apply parscale b4/after

    NumericMatrix hessian0 = bfgs.calc_hessian(grfn<Data>, ex);

    if (data->trace > 0)  {
      Rprintf("Debug on trace calculation. Coef:\n");
      Rprint(bfgs.coef);
      Rprintf("Hessian0:\n");
      Rprint(hessian0);
      Rprintf("Hessian:\n");
      Rprint(bfgs.hessian);
    }

    double edf = trace(solve(as<mat>(bfgs.hessian),as<mat>(hessian0)));
    double negll = bfgs.calc_objective(fminfn<Data>,ex);
    double gcv =  negll + data->alpha*edf;
    double bic =  negll + data->alpha*edf*log(sum(data->event));
    data->init = bfgs.coef;
    if (data->trace > 0)
      Rprintf("sp=%f\tedf=%f\tnegll=%f\tgcv=%f\tbic=%f\talpha=%f\n",data->sp[0],edf,negll,gcv,bic,data->alpha);

    return data->criterion==1 ? gcv : bic;
  }    

  template<class Smooth, class Stpm2>
  double pstpm2_step_multivariate(int n, double * logsp, void * ex) {
    typedef pstpm2<Smooth,Stpm2> Data;
    Data * data = (Data *) ex;

    double lsp = -9.0, usp = 9.0;

    for (int i=0; i < data->sp.size(); ++i)
      //data->sp[i] = exp(logsp[i]);
      data->sp[i] = exp(bound(logsp[i],lsp,usp));

    if (data->trace > 0) {
      for (int i = 0; i < data->sp.size(); ++i)
	Rprintf("sp[%i]=%f\t",i,data->sp[i]);
    }

    BFGS2<Data> bfgs; 
    bfgs.reltol = data->reltol_search;
    bfgs.optimWithConstraint(pfminfn<Smooth,Stpm2>, pgrfn<Smooth,Stpm2>, data->init, ex, fminfn_constraint<Data>, false); // do not apply parscale b4/after

    NumericMatrix hessian0 = bfgs.calc_hessian(grfn<Data>, ex);

    double edf = trace(solve(as<mat>(bfgs.hessian),as<mat>(hessian0)));
    double negll = bfgs.calc_objective(fminfn<Data>, ex);
    double gcv =  negll + data->alpha*edf;
    double bic =  2.0*negll + data->alpha*edf*log(sum(data->event));
    data->init = bfgs.coef;

    // simple boundary constraints
    double constraint = 0.0;
    // double kappa = 1.0;
    for (int i=0; i < data->sp.size(); ++i) {
      if (logsp[i] < lsp)
	constraint +=  pow(logsp[i]-lsp,2.0);
      if (logsp[i] > usp)
	constraint +=  pow(logsp[i]-usp,2.0);
    }
    double objective =  data->criterion==1 ? 
      gcv + data->kappa/2.0*constraint : 
      bic + data->kappa/2.0*constraint;

    if (data->trace > 0) {
      Rprintf("edf=%f\tnegll=%f\tgcv=%f\tbic=%f\tobjective=%f\n",edf,negll,gcv,bic,objective);
    }
    return objective;
  }    


  template<class Smooth, class Stpm2>
  void pstpm2_step_multivariate_nlm(int n, double * logsp, double * f, void *ex) {
    *f = pstpm2_step_multivariate<Smooth,Stpm2>(n, logsp, ex);
  };


  template<class Smooth, class Stpm2>
  SEXP optim_pstpm2_first(SEXP args) { 

    typedef pstpm2<Smooth,Stpm2> Data;
    Data data(args);
    int n = data.init.size();

    for (int i=0; i<n; ++i) data.init[i] /= data.parscale[i];
    double opt_sp = exp(Brent_fmin(log(0.001),log(1000.0),&pstpm2_step_first<Smooth,Stpm2>,&data,1.0e-2));
    data.sp[0] = opt_sp;
    for (int i=0; i<n; ++i) data.init[i] *= data.parscale[i];

    BFGS2<Data> bfgs;
    bfgs.coef = data.init;
    bfgs.reltol = data.reltol;
    bfgs.optimWithConstraint(pfminfn<Smooth,Stpm2>, pgrfn<Smooth,Stpm2>, data.init, (void *) &data, fminfn_constraint<Data>);

    NumericMatrix hessian0 = bfgs.calc_hessian(grfn<Data>, (void *) &data);
    double edf = trace(solve(as<mat>(bfgs.hessian),as<mat>(hessian0)));

    return List::create(_("sp")=wrap(opt_sp),
			_("coef")=wrap(bfgs.coef),
			_("hessian")=wrap(bfgs.hessian),
          _("edf")=wrap(edf));

  }

  RcppExport SEXP optim_pstpm2LogH_first_ph(SEXP args) {
    return optim_pstpm2_first<SmoothLogH,stpm2>(args); }
  RcppExport SEXP optim_pstpm2Haz_first_ph(SEXP args) {
    return optim_pstpm2_first<SmoothHaz,stpm2>(args); }
  RcppExport SEXP optim_pstpm2LogH_first_po(SEXP args) {
    return optim_pstpm2_first<SmoothLogH,stpm2PO>(args); }
  RcppExport SEXP optim_pstpm2Haz_first_po(SEXP args) {
    return optim_pstpm2_first<SmoothHaz,stpm2PO>(args); }
  RcppExport SEXP optim_pstpm2LogH_first_probit(SEXP args) {
    return optim_pstpm2_first<SmoothLogH,stpm2Probit>(args); }
  RcppExport SEXP optim_pstpm2Haz_first_probit(SEXP args) {
    return optim_pstpm2_first<SmoothHaz,stpm2Probit>(args); }
  RcppExport SEXP optim_pstpm2LogH_first_ah(SEXP args) {
    return optim_pstpm2_first<SmoothLogH,stpm2AH>(args); }
  
  
  template<class Smooth, class Stpm2>
  SEXP optim_pstpm2_multivariate(SEXP args) {

    typedef pstpm2<Smooth,Stpm2> Data;
    Data data(args);
    int n = data.init.size();
    data.kappa = 10.0;

    NelderMead nm;
    nm.reltol = 1.0e-5;
    nm.maxit = 500;
    nm.hessianp = false;
    for (int i=0; i<n; ++i) data.init[i] /= data.parscale[i];

    NumericVector logsp(data.sp.size());
    for (int i=0; i < data.sp.size(); ++i)
      logsp[i] = log(data.sp[i]);

    bool satisfied;
    do {
      nm.optim(pstpm2_step_multivariate<Smooth,Stpm2>, logsp, (void *) &data);
      satisfied = true;
      for (int i=0; i < data.sp.size(); ++i)
	if (logsp[i]< -7.0 || logsp[i] > 7.0) satisfied = false;
      if (!satisfied) data.kappa *= 2.0;
    } while (!satisfied && data.kappa<1.0e5);

    for (int i=0; i<n; ++i) data.init[i] *= data.parscale[i];
    // for (int i=0; i < data.sp.size(); ++i)
    //   data.sp[i] = exp(logsp[i]);
    for (int i=0; i < nm.coef.size(); ++i)
      data.sp[i] = exp(nm.coef[i]);

    BFGS2<Data> bfgs;
    bfgs.coef = data.init;
    bfgs.reltol = data.reltol;
    data.kappa = 1.0;
    bfgs.optimWithConstraint(pfminfn<Smooth,Stpm2>, pgrfn<Smooth,Stpm2>, data.init, (void *) &data, fminfn_constraint<Data>);

    NumericMatrix hessian0 = bfgs.calc_hessian(grfn<Data>, (void *) &data);
    double edf = trace(solve(as<mat>(bfgs.hessian),as<mat>(hessian0)));

    return List::create(_("sp")=wrap(data.sp),
  			_("coef")=wrap(bfgs.coef),
  			_("hessian")=wrap(bfgs.hessian),
        _("edf")=wrap(edf));

  }

  RcppExport SEXP optim_pstpm2LogH_multivariate_ph(SEXP args) { 
    return optim_pstpm2_multivariate<SmoothLogH,stpm2>(args); }
  RcppExport SEXP optim_pstpm2Haz_multivariate_ph(SEXP args) {
    return optim_pstpm2_multivariate<SmoothHaz,stpm2>(args); }
  RcppExport SEXP optim_pstpm2LogH_multivariate_po(SEXP args) {
    return optim_pstpm2_multivariate<SmoothLogH,stpm2PO>(args); }
  RcppExport SEXP optim_pstpm2Haz_multivariate_po(SEXP args) {
    return optim_pstpm2_multivariate<SmoothHaz,stpm2PO>(args); }
  RcppExport SEXP optim_pstpm2LogH_multivariate_probit(SEXP args) {
    return optim_pstpm2_multivariate<SmoothLogH,stpm2Probit>(args); }
  RcppExport SEXP optim_pstpm2Haz_multivariate_probit(SEXP args) {
    return optim_pstpm2_multivariate<SmoothHaz,stpm2Probit>(args); }
  RcppExport SEXP optim_pstpm2LogH_multivariate_ah(SEXP args) { 
    return optim_pstpm2_multivariate<SmoothLogH,stpm2AH>(args); }

  template<class Smooth, class Stpm2>
  SEXP optim_pstpm2_multivariate_nlm(SEXP args) {

    typedef pstpm2<Smooth,Stpm2> Data;
    Data data(args);
    int n = data.init.size();
    data.kappa = 10.0;

    Nlm nlm;
    nlm.iagflg = 0;
    nlm.gradtl = 1.0e-4;
    nlm.steptl = 1.0e-4;
    nlm.msg = 9 + 4;
    nlm.hessianp = false;
    for (int i=0; i<n; ++i) data.init[i] /= data.parscale[i];

    NumericVector logsp(data.sp.size());
    for (int i=0; i < data.sp.size(); ++i)
      logsp[i] = log(data.sp[i]);

    bool satisfied;
    do {
      nlm.optim(pstpm2_step_multivariate_nlm<Smooth,Stpm2>, (fcn_p) 0, logsp, (void *) &data);
      satisfied = true;
      for (int i=0; i < data.sp.size(); ++i)
	if (logsp[i]< -7.0 || logsp[i] > 7.0) satisfied = false;
      if (!satisfied) data.kappa *= 2.0;
    } while (!satisfied && data.kappa<1.0e5);

    for (int i=0; i<n; ++i) data.init[i] *= data.parscale[i];
    for (int i=0; i < nlm.coef.size(); ++i)
      data.sp[i] = exp(nlm.coef[i]);

    BFGS2<Data> bfgs;
    bfgs.coef = data.init;
    bfgs.reltol = data.reltol;
    data.kappa = 1.0;
    bfgs.optimWithConstraint(pfminfn<Smooth,Stpm2>, pgrfn<Smooth,Stpm2>, data.init, (void *) &data, fminfn_constraint<Data>);

    NumericMatrix hessian0 = bfgs.calc_hessian(grfn<Data>, (void *) &data);
    double edf = trace(solve(as<mat>(bfgs.hessian),as<mat>(hessian0)));

    return List::create(_("sp")=wrap(data.sp),
  			_("coef")=wrap(bfgs.coef),
  			_("hessian")=wrap(bfgs.hessian),
			_("edf")=wrap(edf));
  }

  RcppExport SEXP optim_pstpm2LogH_multivariate_ph_nlm(SEXP args) { 
    return optim_pstpm2_multivariate_nlm<SmoothLogH,stpm2>(args); }
  RcppExport SEXP optim_pstpm2Haz_multivariate_ph_nlm(SEXP args) {
    return optim_pstpm2_multivariate_nlm<SmoothHaz,stpm2>(args); }
  RcppExport SEXP optim_pstpm2LogH_multivariate_po_nlm(SEXP args) {
    return optim_pstpm2_multivariate_nlm<SmoothLogH,stpm2PO>(args); }
  RcppExport SEXP optim_pstpm2Haz_multivariate_po_nlm(SEXP args) {
    return optim_pstpm2_multivariate_nlm<SmoothHaz,stpm2PO>(args); }
  RcppExport SEXP optim_pstpm2LogH_multivariate_probit_nlm(SEXP args) {
    return optim_pstpm2_multivariate_nlm<SmoothLogH,stpm2Probit>(args); }
  RcppExport SEXP optim_pstpm2Haz_multivariate_probit_nlm(SEXP args) {
    return optim_pstpm2_multivariate_nlm<SmoothHaz,stpm2Probit>(args); }


  template<class Smooth, class Stpm2>
  SEXP optim_pstpm2_fixedsp(SEXP args) { 

    typedef pstpm2<Smooth,Stpm2> Data;
    Data data(args);
    BFGS2<Data> bfgs;
    bfgs.coef = data.init;
    bfgs.reltol = data.reltol;

    bfgs.optimWithConstraint(pfminfn<Smooth,Stpm2>, pgrfn<Smooth,Stpm2>, data.init, (void *) &data, fminfn_constraint<Data>);

    NumericMatrix hessian0 = bfgs.calc_hessian(grfn<Data>, (void *) &data);
    double edf = trace(solve(as<mat>(bfgs.hessian),as<mat>(hessian0)));

    return List::create(_("sp")=wrap(data.sp),
			_("coef")=wrap(bfgs.coef),
			_("hessian")=wrap(bfgs.hessian),
			_("edf")=wrap(edf));
  }

  RcppExport SEXP optim_pstpm2LogH_fixedsp_ph(SEXP args) {
    return optim_pstpm2_fixedsp<SmoothLogH,stpm2>(args); }
  RcppExport SEXP optim_pstpm2Haz_fixedsp_ph(SEXP args) {
    return optim_pstpm2_fixedsp<SmoothHaz,stpm2>(args); }
  RcppExport SEXP optim_pstpm2LogH_fixedsp_po(SEXP args) {
    return optim_pstpm2_fixedsp<SmoothLogH,stpm2PO>(args); }
  RcppExport SEXP optim_pstpm2Haz_fixedsp_po(SEXP args) {
    return optim_pstpm2_fixedsp<SmoothHaz,stpm2PO>(args); }
  RcppExport SEXP optim_pstpm2LogH_fixedsp_probit(SEXP args) { 
    return optim_pstpm2_fixedsp<SmoothLogH,stpm2Probit>(args); }
  RcppExport SEXP optim_pstpm2Haz_fixedsp_probit(SEXP args) {
    return optim_pstpm2_fixedsp<SmoothHaz,stpm2Probit>(args); }
  RcppExport SEXP optim_pstpm2LogH_fixedsp_ah(SEXP args) {
    return optim_pstpm2_fixedsp<SmoothLogH,stpm2AH>(args); }

  template<class Smooth, class Stpm2>
  SEXP test_pstpm2(SEXP args) { 

    pstpm2<Smooth,Stpm2> data(args);
    int n = data.init.size();

    NumericVector init = ew_div(data.init,data.parscale);

    double pfmin = pfminfn<Smooth,Stpm2>(n,&init[0],(void *) &data);
    NumericVector gr(n);
    pgrfn<Smooth,Stpm2>(n,&init[0], &gr[0], (void *) &data);

    init = ew_mult(init,data.parscale);

    return List::create(_("sp")=wrap(data.sp),
			_("pfmin")=wrap(pfmin),
			_("gr")=wrap(gr)
			);

  }

  RcppExport SEXP test_pstpm2LogH(SEXP args) {
    return test_pstpm2<SmoothLogH,stpm2>(args);
  }

  RcppExport SEXP test_pstpm2Haz(SEXP args) {
    return test_pstpm2<SmoothHaz,stpm2>(args);
  }

  // R CMD INSTALL ~/src/R/microsimulation
  // R -q -e "require(microsimulation); .Call('test_nmmin',1:2,PACKAGE='microsimulation')"

  // .Call("optim_stpm2",init,X,XD,rep(bhazard,nrow(X)),wt,ifelse(event,1,0),package="rstpm2")

} // anonymous namespace

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API