Пример #1
0
Файл: dtnorm.c Проект: cran/pscl
double dtnorm_std(const double lower_bound)
{
  double y;
  if (lower_bound < 0.0)
    {
      do {
	y = norm_rand();
      } while (y <= lower_bound);
      return y;
    }
  else if (lower_bound < 0.75)
    {
      do {
	y = fabs(norm_rand());
      } while (y <= lower_bound);
      return y;
    }
  else
    {
      do {
	y = exp_rand();
      } while (exp_rand() * lower_bound * lower_bound <= 0.5 * y * y);
      return y / lower_bound + lower_bound;
    }
}
Пример #2
0
void Prekazitor::ostruvek() {
    BLOK bloky[9] = {K[3], K[4], K[5], K[6], K[7], K[8], K[9], K[10], K[11]};
    int x2 = *X + 1 + exp_rand(4,6);
    int y2 = *Y + 1 + exp_rand(4,4);
    s->intact2->ram_obdelnik(bloky, *X, x2, *Y, y2);
    s->intact2->poloz_blok(K[0], *X, (*Y)-1);
    s->intact2->obdelnik(K[1], (*X)+1, x2-1, (*Y)-1, (*Y)-1);
    s->intact2->poloz_blok(K[2], x2, (*Y)-1);
    //std::cout << "před:" << *X;
    *X = x2;
    //std::cout << " po:" << *X << std::endl;
}
Пример #3
0
  double rexp_mt(ENG & eng, double scale)
  {
    if (!R_FINITE(scale) || scale <= 0.0)
      ML_ERR_return_NAN;

    return scale * exp_rand(eng);
  }
Пример #4
0
task *newtask(void) {
	task *tsk = (task *) malloc (sizeof(task));
	tsk->nkern = unif_rand(kmax);
	tsk->nmem = unif_rand(vmax);
	tsk->comptime = exp_rand(D, mu);
	return tsk;
}
Пример #5
0
bool Prekazitor::pneumatic() {
    int rezerva1 = (*Y) - min_y;
    int rezerva2 = s->intact2->vyska - (*Y) - 1;
    int rezerva = std::min(rezerva1, rezerva2);
    if (rezerva < 5) {
        return false;
    }
    int max_d = std::min(rezerva, 12) - 5;
    int dy = 5 + exp_rand(10, max_d);
    int y_pn = *Y;
    int nove_y = y_pn + dy;

    Objekt *o = new Objekt("rock", (*X)*32, ((*Y)-1)*32);
    s->objekty.push_back(o);

    while (*Y < nove_y) {
        dolovak( std::min(nove_y - (*Y), 4) );
    }
    o = new Objekt("pneumatic-platform", (*X)*32, y_pn*32);
    o->blbosti = "(sprite \"images/objects/platforms/small.sprite\")";
    s->objekty.push_back(o);
    stredovak(4);
    nahorovak(2*dy);
    return true;
}
Пример #6
0
double rexp(double scale)
{
    if (!R_FINITE(scale) || scale <= 0.0) {
        if(scale == 0.) return 0.;
        /* else */
        ML_ERR_return_NAN;
    }
    return scale * exp_rand(); // --> in ./sexp.c
}
Пример #7
0
double rztgeom(double prob)
{
    if (!R_FINITE(prob) || prob <= 0 || prob > 1) return R_NaN;

    /* limiting case as p approaches one is point mass at one */
    if (prob == 1) return 1.0;

    return 1 + rpois(exp_rand() * ((1 - prob) / prob));
}
Пример #8
0
/*
 * For arrival events, use exponential distribution.
 * For departure events, function assumes <src,pkt> have sufficient deficits.
 */
void stateDRR::schedule_event(int type, int pkt, int src)
{
    events *evt = new events(type, src, pkt, 0, 0);

    switch(type) {
        case PKT_ARRIVE:
            switch(src) {
                case TELNET1:
                case TELNET2:
                case TELNET3:
                case TELNET4:
            #ifdef DEBUG
                    cout<<"Arr "<<this->lastArrival[src]<<", "<<exp_rand(L_TELNET/r)<<endl;
            #endif
                    evt->eventTime = this->lastArrival[src] + exp_rand(L_TELNET/r);
                    this->lastArrival[src] = evt->eventTime;
                    evt->packetSize = exp_rand(L_TELNET);
                    break;
                case FTP1:
                case FTP2:
                case FTP3:
                case FTP4:
                case FTP5:
                case FTP6:
                    evt->eventTime = this->lastArrival[src] + exp_rand(L_FTP/r);
                    this->lastArrival[src] = evt->eventTime;
                    evt->packetSize = exp_rand(L_FTP);
                    break;
                case ROGUE:
                    evt->eventTime = this->lastArrival[src] + exp_rand(L_ROGUE*2/ROGUE_SRC);
                    this->lastArrival[src] = evt->eventTime;
                    evt->packetSize = exp_rand(L_ROGUE);
                    break;
            }
            evt->arrivalTime = evt->eventTime;
            evt->departureTime = INVAL;
            
            this->eventQueue.push(evt);
#ifdef DEBUG
            cout<<"sched\t"<<evt->eventTime<<"\tA\tpkt "<<evt->packetId<<"\tsrc "<<evt->sourceId<<"\ttime "<<evt->eventTime;
            cout<<"\tQsize "<<this->eventQueue.size()<<endl;
#endif
            break;
        case PKT_DEPART:
            evt->eventTime = this->lastDeparture + 
                                this->flows[src].front()->packetSize/R;
            evt->packetSize = this->flows[src].front()->packetSize;
            evt->sourceId = src;
            evt->packetId = this->flows[src].front()->packetId;
            evt->departureTime = evt->eventTime;
            evt->arrivalTime = this->flows[src].front()->arrivalTime;
            this->eventQueue.push(evt);
#ifdef DEBUG
            cout<<"sched\t"<<evt->eventTime<<"\tD\tpkt "<<evt->packetId<<"\tsrc "<<evt->sourceId;
            cout<<"\ttime "<<evt->eventTime<<"\tQsize "<<this->eventQueue.size()<<endl;
#endif
            break;
    }
}
Пример #9
0
bool Prekazitor::tajna_chodba() {
    bool sm = !(nahodne(2));
    if (!uprav_smer(sm, 4)) {
        return false;
    }
    int delka = exp_rand(6, max_x-(*X)-4) + 3;
    if (delka < 3) {
        return false;
    }

    Tilemap* tm = new Tilemap(delka, 4, false);
    tm->pojmenuj("secretTM",s->tajnych_chodeb);
    tm->z_pos = 101 + s->tajnych_chodeb;
    tm->cesta = new Cesta();
    float x, y;
    if (sm) {
        dolovak(4);
        stredovak(delka);
        s->intact2->obdelnik(K[1] , (*X)-delka-1, (*X)-3, (*Y)-5, (*Y)-5);
        s->intact2->obdelnik(K[4] , (*X)-delka-1, (*X)-3, (*Y)-4, (*Y)-4);
        s->intact2->obdelnik(K[10], (*X)-delka-1, (*X)-3, (*Y)-3, (*Y)-3);
        s->intact2->poloz_blok(K[2] , (*X)-2, (*Y)-5);
        s->intact2->poloz_blok(K[5] , (*X)-2, (*Y)-4);
        s->intact2->poloz_blok(K[11], (*X)-2, (*Y)-3);
        s->intact2->poloz_blok(V[0], (*X)-delka-1, (*Y)-3);

        tm->obdelnik(S, 0, tm->sirka-2, 0, tm->vyska-1);
        tm->obdelnik(K[8], tm->sirka-1, tm->sirka-1, 0, tm->vyska-3);
        tm->poloz_blok(V[2], tm->sirka-1, tm->vyska-2);
        tm->poloz_blok(V[4], tm->sirka-1, tm->vyska-1);
        x = (*X)-delka-1;
        y = (*Y)-3;
    } else {
        stredovak(delka);
        nahorovak(4);
        s->intact2->poloz_blok(K[0], (*X)-delka, (*Y)-1);
        s->intact2->poloz_blok(K[3], (*X)-delka, *Y);
        s->intact2->poloz_blok(K[9], (*X)-delka, (*Y)+1);
        s->intact2->obdelnik(K[1] , (*X)-delka+1, *X, (*Y)-1, (*Y)-1);
        s->intact2->obdelnik(K[4] , (*X)-delka+1, *X, *Y, *Y);
        s->intact2->obdelnik(K[10], (*X)-delka+1, *X, (*Y)+1, (*Y)+1);
        s->intact2->poloz_blok(V[1], (*X)-1, (*Y)+1);

        tm->obdelnik(S, 1, tm->sirka-1, 0, tm->vyska-1);
        tm->obdelnik(K[6], 0, 0, 0, tm->vyska-3);
        tm->poloz_blok(V[3], 0, tm->vyska-2);
        tm->poloz_blok(V[5], 0, tm->vyska-1);
        x = (*X)-delka;
        y = (*Y)+1;
    }
    secretarea(x, y, tm);
    stredovak(1);
    s->tilemapy.push_back(tm);
    s->tajnych_chodeb++;
    return true;
}
Пример #10
0
static int geodev (double p)
     /* Return geometric distributed random deviate with p(i) = p*(1-p)^i,
	where 0<p<1 and i=0,1,..
	See Fishman, G. S., 1996, Monte Carlo (Springer, NY, Berlin, Heidelberg), 221. */
{
  double b, y, z;
  
  b = (-1.0)/log(1.0-p);
  y = exp_rand();
  z = b*y;
  return (int)z;
}
Пример #11
0
void rsmith2d(double *coord, double *center, double *edge, int *nObs,
	      int *nSites, int *grid, double *cov11, double *cov12,
	      double *cov22, double *ans){
  /* This function generates random fields for the 2d smith model

     coord: the coordinates of the locations
    center: the center of the compact set - here I use a square
      edge: the length of the edge of the square
      nObs: the number of observations to be generated
      grid: Does coord specifies a grid?
    nSites: the number of locations
     covXX: the parameters of the bivariate normal density
       ans: the generated random field */

  const double det = *cov11 * *cov22 - *cov12 * *cov12,
    uBound = 1 / (M_2PI * sqrt(det)), itwiceDet = 1 / (2 * det);

  if ((det <= 0) || (*cov11 <= 0))
    error("The covariance matrix isn't semi-definite positive!\n");

  /* We first center the coordinates to avoid repetition of
    unnecessary operations in the while loop */
  for (int i=0;i<*nSites;i++){
    coord[i] -= center[0];
    coord[*nSites + i] -= center[1];
  }

  /* Simulation according to the Schlather methodology. The compact
     set need to be inflated first */
  *edge += 6.92 * sqrt(fmax2(*cov11, *cov22));
  double lebesgue = *edge * *edge;

  GetRNGstate();
  
  if (*grid){
    //Simulation part if a grid is used
    for (int i=0;i<*nObs;i++){
      double poisson = 0;
      int nKO = *nSites * *nSites;
    
      while (nKO) {
	/* The stopping rule is reached when nKO = 0 i.e. when each site
	   satisfies the condition in Eq. (8) of Schlather (2002) */

	poisson += exp_rand();
	double ipoisson = 1 / poisson, thresh = uBound * ipoisson;

	//We simulate points uniformly in [-r/2, r/2]^2
	double u1 = *edge * runif(-0.5, 0.5),
	  u2 = *edge * runif(-0.5, 0.5);
      
	nKO = *nSites * *nSites;
	for (int j=0;j<*nSites;j++){
	  for (int k=0;k<*nSites;k++){
	    /* This is the bivariate normal density with 0 mean and
	       cov. matrix [cov11, cov12; cov12, cov22] */
	    double y = exp((-*cov22 * (coord[j] - u1) * (coord[j] - u1) + 2 * *cov12 *
			    (coord[j] - u1) * (coord[*nSites + k] - u2) - *cov11 *
			    (coord[*nSites + k] - u2) * (coord[*nSites + k] - u2)) *
			   itwiceDet) * thresh;
	      
	    ans[j + k * *nSites + i * *nSites * *nSites] = 
	      fmax2(y, ans[j + k * *nSites + i * *nSites * *nSites]);
	    
	    nKO -= (thresh <= ans[j + k * *nSites + i * *nSites * *nSites]);
	  }
	}
      }
    }
  }

  else{
    //Simulation part if a grid isn't used
    for (int i=0;i<*nObs;i++){
      double poisson = 0;
      int nKO = *nSites;
    
      while (nKO) {
	/* The stopping rule is reached when nKO = 0 i.e. when each site
	   satisfies the condition in Eq. (8) of Schlather (2002) */

	poisson += exp_rand();
	double ipoisson = 1 / poisson, thresh = uBound * ipoisson;

	//We simulate points uniformly in [-r/2, r/2]^2
	double u1 = *edge * runif(-0.5, 0.5),
	  u2 = *edge * runif(-0.5, 0.5);
      
	nKO = *nSites;
	for (int j=0;j<*nSites;j++){
	  /* This is the bivariate normal density with 0 mean and
	     cov. matrix [cov11, cov12; cov12, cov22] */
	  double y = exp((-*cov22 * (coord[j] - u1) * (coord[j] - u1) + 2 * *cov12 *
			  (coord[j] - u1) * (coord[*nSites + j] - u2) - *cov11 *
			  (coord[*nSites + j] - u2) * (coord[*nSites + j] - u2)) *
			 itwiceDet) * thresh;
	  
	  ans[i + j * *nObs] = fmax2(y, ans[i + j * *nObs]);
	  
	  nKO -= (thresh <= ans[i + j * *nObs]);
	}
      }
    }
  }
 
  PutRNGstate();

  /* Lastly, we multiply by the Lebesgue measure of the dilated
    compact set */
  if (*grid){
    for (int i=0;i<(*nSites * *nSites * *nObs);i++)
      ans[i] *= lebesgue;
  }
  
  else{
    for (int i=0;i<(*nSites * *nObs);i++)
      ans[i] *= lebesgue;
  }

  return;
}
Пример #12
0
void rsmith1d(double *coord, double *center, double *edge, int *nObs,
	      int *nSites, double *var, double *ans){
  /* This function generates random fields for the 1d smith model

     coord: the coordinates of the locations
    center: the center of the compact set - here I use an interval
      edge: the length of the interval
      nObs: the number of observations to be generated
    nSites: the number of locations
       var: the variance of the univariate normal density
       ans: the generated random field */

  const double uBound = M_1_SQRT_2PI / sqrt(*var);

  if (*var <= 0)
    error("The variance should be strictly positive!\n");

  /* We first center the coordinates to avoid repetition of
    unnecessary operations in the while loop */
  for (int i=0;i<*nSites;i++)
    coord[i] -= center[0];

  /* Simulation according to the Schlather methodology. The compact
     set need to be inflated first */
  *edge += 6.92 * sqrt(*var);
  const double lebesgue = *edge;

  GetRNGstate();
  
  for (int i=0;i<*nObs;i++){
    double poisson = 0;
    int nKO = *nSites;
    
    while (nKO) {
      /* The stopping rule is reached when nKO = 0 i.e. when each site
	 satisfies the condition in Eq. (8) of Schlather (2002) */
      
      poisson += exp_rand();
      double ipoisson = 1 / poisson, thresh = uBound * ipoisson;
      
      //We simulate points uniformly in [-r/2, r/2]
      double u = *edge * runif(-0.5, 0.5);
            
      nKO = *nSites;
      for (int j=0;j<*nSites;j++){
	//This is the normal density with 0 mean and variance var
	double y = exp(-(coord[j] - u) * (coord[j] - u) / (2 * *var)) * thresh;	  
	ans[i + j * *nObs] = fmax2(y, ans[i + j * *nObs]);
	nKO -= (thresh <= ans[i + j * *nObs]);
      }
    }
  }
 
  PutRNGstate();

  /* Lastly, we multiply by the Lebesgue measure of the dilated
    compact set */
  for (int i=0;i<(*nSites * *nObs);i++)
    ans[i] *= lebesgue;

  return;
}
Пример #13
0
SEXP thinjumpequal(SEXP n,
		   SEXP p,
		   SEXP guess) 
{
  int N;
  double P;

  int *w;  /* temporary storage for selected integers */
  int nw, nwmax;

  int i, j, k;
  double log1u, log1p;

  /* R object return value */
  SEXP Out;
  /* external storage pointer */
  int *OutP;

  /* protect R objects from garbage collector */
  PROTECT(p = AS_NUMERIC(p));
  PROTECT(n = AS_INTEGER(n));
  PROTECT(guess = AS_INTEGER(guess));

  /* Translate arguments from R to C */
  N = *(INTEGER_POINTER(n));
  P = *(NUMERIC_POINTER(p));
  nwmax = *(INTEGER_POINTER(guess));

  /* Allocate space for result */
  w = (int *) R_alloc(nwmax, sizeof(int));

  /* set up */
  GetRNGstate();
  log1p = -log(1.0 - P);
  
  /* main loop */
  i = 0;  /* last selected element of 1...N */
  nw = 0;  /* number of selected elements */
  while(i <= N) {
    log1u = exp_rand();  /* an exponential rv is equivalent to -log(1-U) */
    j = (int) ceil(log1u/log1p); /* j is geometric(p) */
    i += j;
    if(nw >= nwmax) {
      /* overflow; allocate more space */
      w  = (int *) S_realloc((char *) w,  2 * nwmax, nwmax, sizeof(int));
      nwmax    = 2 * nwmax;
    }
    /* add 'i' to output vector */
    w[nw] = i;
    ++nw;
  }
  /* The last saved 'i' could have exceeded 'N' */
  /* For efficiency we don't check this in the loop */
  if(nw > 0 && w[nw-1] > N) 
    --nw;

  PutRNGstate();

  /* create result vector */
  PROTECT(Out = NEW_INTEGER(nw));

  /* copy results into output */
  OutP  = INTEGER_POINTER(Out);
  for(k = 0; k < nw; k++)
    OutP[k] = w[k];

  UNPROTECT(4);
  return(Out);
}
Пример #14
0
void rgeomtbm(double *coord, int *nObs, int *nSite, int *dim,
	      int *covmod, int *grid, double *sigma2, double *nugget,
	      double *range, double *smooth, double *uBound,
	      int *nlines, double *ans){
  /* This function generates random fields from the geometric model

     coord: the coordinates of the locations
      nObs: the number of observations to be generated
    nSite: the number of locations
       dim: the random field is generated in R^dim
    covmod: the covariance model
      grid: Does coord specifies a grid?
    sigma2: the variance of the geometric gaussian process
      nugget: the nugget parameter
     range: the range parameter
    smooth: the smooth parameter
    uBound: the uniform upper bound for the stoch. proc.
    nlines: the number of lines used in the TBM algo
       ans: the generated random field */

  int i, neffSite, lagi = 1, lagj = 1;
  const double loguBound = log(*uBound), halfSigma2 = 0.5 * *sigma2;
  double sigma = sqrt(*sigma2), sill = 1 - *nugget;

  if (*grid){
    neffSite = R_pow_di(*nSite, *dim);
    lagi = neffSite;
  }

  else{
    neffSite = *nSite;
    lagj = *nObs;
  }

  double *gp = malloc(neffSite * sizeof(double)),
    *lines = malloc(3 * *nlines * sizeof(double));

  //rescale the coordinates
  for (i=(*nSite * *dim);i--;){
    const double irange = 1 / *range;
    coord[i] = coord[i] * irange;
  }
  
  if ((*covmod == 3) && (*smooth == 2))
    //This is the gaussian case
    *covmod = 5;

  //Generate lines
  vandercorput(nlines, lines);
  

  GetRNGstate();
 
  for (i=*nObs;i--;){
    int nKO = neffSite;
    double poisson = 0;
    
    while (nKO) {
      /* The stopping rule is reached when nKO = 0 i.e. when each site
	 satisfies the condition in Eq. (8) of Schlather (2002) */
      int j;
            
      /* ------- Random rotation of the lines ----------*/
      double u = unif_rand() - 0.5,
	v = unif_rand() - 0.5,
	w = unif_rand() - 0.5,
	angle = runif(0, M_2PI),	
	inorm = 1 / sqrt(u * u + v * v + w * w);
      
      u *= inorm;
      v *= inorm;
      w *= inorm;
      
      rotation(lines, nlines, &u, &v, &w, &angle);
      /* -------------- end of rotation ---------------*/
      
      poisson += exp_rand();
      double ipoisson = -log(poisson),
	thresh = loguBound + ipoisson;
      
      /* We simulate one realisation of a gaussian random field with
	 the required covariance function */
      for (j=neffSite;j--;)
	gp[j] = 0;

      tbmcore(nSite, &neffSite, dim, covmod, grid, coord, nugget,
	      &sill, range, smooth, nlines, lines, gp);
      
      nKO = neffSite;
      double ipoissonMinusHalfSigma2 = ipoisson - halfSigma2;
      for (j=neffSite;j--;){
	ans[j * lagj + i * lagi] = fmax2(sigma * gp[j] + ipoissonMinusHalfSigma2,
					 ans[j * lagj + i * lagi]);
	
	nKO -= (thresh <= ans[j * lagj + i * lagi]);
	
      }
    }
  }

  PutRNGstate();

  /* So far we generate a max-stable process with standard Gumbel
     margins. Switch to unit Frechet ones */
  for (i=*nObs * neffSite;i--;)
    ans[i] = exp(ans[i]);

  free(lines); free(gp);
  return;
}
Пример #15
0
void rextremaltdirect(double *coord, int *nObs, int *nSite, int *dim,
		      int *covmod, int *grid, double *nugget, double *range,
		      double *smooth, double *DoF, double *uBound, double *ans){
  /* This function generates random fields for the Extremal-t model

     coord: the coordinates of the locations
      nObs: the number of observations to be generated
    nSite: the number of locations
       dim: the random field is generated in R^dim
    covmod: the covariance model
      grid: Does coord specifies a grid?
      nugget: the nugget parameter
     range: the range parameter
    smooth: the smooth parameter
       DoF: the degree of freedom
 blockSize: see rextremalttbm.
       ans: the generated random field */

  int neffSite, lagi = 1, lagj = 1, oneInt = 1;
  double sill = 1 - *nugget;

  if (*grid){
    neffSite = R_pow_di(*nSite, *dim);
    lagi = neffSite;
  }

  else{
    neffSite = *nSite;
    lagj = *nObs;
  }

  double *covmat = malloc(neffSite * neffSite * sizeof(double)),
    *gp = malloc(neffSite * sizeof(double));

  buildcovmat(nSite, grid, covmod, coord, dim, nugget, &sill, range,
	      smooth, covmat);
  
  /* Compute the Cholesky decomposition of the covariance matrix */
  int info = 0;
  F77_CALL(dpotrf)("U", &neffSite, covmat, &neffSite, &info);

  if (info != 0)
    error("error code %d from Lapack routine '%s'", info, "dpotrf");
  
  GetRNGstate();
 
  for (int i=*nObs;i--;){
    double poisson = 0;
    int nKO = neffSite;
      
    while (nKO){
      poisson += exp_rand();

      double ipoisson = 1 / poisson,
	thresh = *uBound * ipoisson;

      
      /* We simulate one realisation of a gaussian random field with
	 the required covariance function */
      for (int j=neffSite;j--;)
	gp[j] = norm_rand();
      
      F77_CALL(dtrmv)("U", "T", "N", &neffSite, covmat, &neffSite, gp, &oneInt);
      
      nKO = neffSite;
      for (int j=neffSite;j--;){
	double dummy = R_pow(fmax2(0, gp[j]), *DoF) * ipoisson;
	ans[j * lagj + i * lagi] = fmax2(dummy, ans[j * lagj + i * lagi]);
	nKO -= (thresh <= ans[j * lagj + i * lagi]);
      }
    }
  }

  PutRNGstate();
  //Lastly we multiply by the normalizing constant
  const double imean = M_SQRT_PI * R_pow(2, -0.5 * (*DoF - 2)) /
    gammafn(0.5 * (*DoF + 1));
  for (int i=(neffSite * *nObs);i--;)
    ans[i] *= imean;
  
  free(covmat); free(gp);
  return;
}
Пример #16
0
/***** ***************************************************************************************** *****/
void
RJMCMCcombine(int* accept,           double* log_AR,
              int* K,                double* w,             double* logw,           double* mu,    
              double* Q,             double* Li,            double* Sigma,          double* log_dets,  
              int* order,            int* rank,             int* r,                 int* mixN,         int** rInv,
              double* u,             double* P,             double* log_dens_u,                  
              double* dwork,         int* iwork,            int* err,
              const double* y,          const int* p,                     const int* n,
              const int* Kmax,          const double* logK,               const double* log_lambda,  const int* priorK,
              const double* logPsplit,  const double* logPcombine,        const double* delta,  
              const double* c,          const double* log_c,              const double* xi,          const double* D_Li,               const double* log_dets_D,
              const double* zeta,       const double* log_Wishart_const,  const double* gammaInv,    const double* log_sqrt_detXiInv,  
              const int* priormuQ,      const double* pars_dens_u,
              void (*ld_u)(double* log_dens_u,  const double* u,  const double* pars_dens_u,  const int* p))
{
  const char *fname = "NMix::RJMCMCcombine";

  *err = 0;
  *accept = 0;
  *log_AR = R_NegInf;

  /*** Array of two zeros to be passed to ldMVN as log_dets to compute only -1/2(x-mu)'Sigma^{-1}(x-mu) ***/
  static const double ZERO_ZERO[2] = {0.0, 0.0};

  /***  Some variables ***/
  static int i0, i1, k, LTp, p_p, ldwork_logJacLambdaVSigma;
  static int jstar, jremove, j1, j2;
  static int rInvPrev;
  static int rankstar;

  static double sqrt_u1_ratio, one_u1, log_u1, log_one_u1, log_u1_one_minus_u1_min32, one_minus_u2sq, erand;
  static double log_Jacob, log_Palloc, log_LikelihoodRatio, log_PriorRatio, log_ProposalRatio;
  static double log_phi1, log_phi2, log_phistar, Prob_r1, Prob_r2, log_Prob_r1, log_Prob_r2, max_log_Prob_r12, sum_Prob_r12;
  static double mu1_vstar, mu2_vstar, mustar_vstar;

  /*** Some pointers ***/
  static double *w1, *w2, *logw1, *logw2, *mu1, *mu2, *Sigma1, *Sigma2, *Li1, *Li2, *Q1, *Q2, *log_dets1, *log_dets2;
  static int *mixN1, *mixN2, *rInv1, *rInv2;
  static int **rrInv1, **rrInv2;

  static double *wOldP, *logwOldP, *muOldP, *SigmaOldP, *LiOldP, *QOldP, *log_detsOldP;
  static double *Listar;
  static int *mixNOldP;  
  static int **rrInvOldP;
  static const double *muNewP, *SigmaNewP, *QNewP;

  static const double *mu1P, *mu2P;
  static const double *yP;
  static int *rInv1P, *rInv2P, *rInvP;
  static int *rP;

  /*** Declaration for dwork ***/
  static double *mustar, *Sigmastar, *Lambdastar, *Vstar, *Lstar, *Qstar;
  static double *SigmaTemp, *Lambda1, *Lambda2, *V1, *V2, *Lambda_dspev, *V_dspev, *dwork_misc;
  static double *dlambdaV_dSigma, *P_im, *VPinv_re, *VPinv_im, *sqrt_Plambda_re, *sqrt_Plambda_im, *VP_re, *VP_im;

  static double *mustarP, *LambdastarP, *LstarP, *Lambda1P, *Lambda2P, *VstarP, *VP_reP;

  /*** Declaration for iwork ***/
  static int *iwork_misc;

  static int complexP[1];

  /*** Declaration for auxiliary variables ***/
  static double *u1, *u2, *u3;
  static double *u2P, *u3P;

  /*** Declaration for other mixture related variables ***/
  static double wstar[1];                       /** weight of the new combined component                                                         **/
  static double logwstar[1];                    /** log(weight) of the new combined component                                                    **/
  static double log_detsstar[2];                /** Like log_dets, related to the new combined component                                         **/ 
  static double logJ_part3[1];                  /** the third part of the log-Jacobian                                                           **/
  //static double log_dlambdaV_dSigma[1];         /** logarithm of |d(Lambdastar,Vstar)/d(Sigmastar)|                                              **/
  static double logL12[2];                      /** logL12[0] = sum_{i=0}^{mixN1} log(phi(y_i | mu_{r_i}, Sigma_{r_i})) + sum_{i=0}^{mixN2}...   **/
                                                /** logL12[1] = sum_{i=0}^{mixN1} log(P(r = r_i | w, K)) + sum_{i=0}^{mixN2} ...                 **/
                                                /** for observations allocated to the combined components, state before reallocation             **/
  static double logLstar[2];                    /** the same as above, state after reallocation                                                  **/
  static double log_prior_mu1[1];               /** logarithm of the prior of mu1 (first splitted component)                                     **/
  static double log_prior_mu2[1];               /** logarithm of the prior of mu2 (second splitted component)                                    **/
  static double log_prior_mustar[1];            /** logarithm of the prior of mu(star) (splitted component)                                      **/
  static double log_prior_Q1[1];                /** logarithm of the prior of Q1 = Sigma1^{-1} (first splitted component)                        **/
  static double log_prior_Q2[1];                /** logarithm of the prior of Q2 = Sigma2^{-1} (first splitted component)                        **/
  static double log_prior_Qstar[1];             /** logarithm of the prior of Q(star) = Sigma(star)^{-1} (splitted component)                    **/
  static int mixNstar[1];                       /** numbers of allocated observations in the new combined component                              **/

  if (*K == 1) return;

  LTp = (*p * (*p + 1))/2;
  p_p = *p * *p;
  ldwork_logJacLambdaVSigma = *p * LTp + (4 + 2 * *p) * *p;

  /*** Components of dwork ***/
  mustar          = dwork;                       /** mean vector of the new combined component                                                  **/
  Sigmastar       = mustar + *p;                 /** covariance matrix of the new combined component                                            **/
  Lambdastar      = Sigmastar + LTp;             /** eigenvalues of the new combined component                                                  **/
  Vstar           = Lambdastar + *p;             /** eigenvectors of the new combined component                                                 **/
  Lstar           = Vstar + p_p;                 /** Cholesky decomposition of Sigmastar                                                        **/
  Qstar           = Lstar + LTp;                 /** inversion of Sigmastar                                                                     **/
  SigmaTemp       = Qstar + LTp;                 /** Sigma1 and Sigma2 passed to dspev which overwrites it during the decomposition             **/
  Lambda1         = Sigmastar + LTp;             /** eigenvalues of the first component to be combined                                          **/
  Lambda2         = Lambda1 + *p;                /** eigenvalues of the second component to be combined                                         **/  
  V1              = Lambda2 + *p;                /** eigenvectors of the first component to be combined                                         **/
  V2              = V1 + p_p;                    /** eigenvectors of the second component to be combined                                        **/
  Lambda_dspev    = V2 + p_p;                    /** space to store lambda's computed by dspev (in ascending order)                             **/
  V_dspev         = Lambda_dspev + *p;           /** space to store V computed by dspev                                                         **/
  dwork_misc      = V_dspev + p_p;               /** working array for LAPACK dspev (needs 3*p)                                                 **/
         				         /**                   Dist::ldMVN1, Dist::ldMVN2 (needs p)                                     **/
                                                 /**                   NMix::RJMCMC_logJacLambdaVSigma (needs: see above)                       **/
                                                 /**                   AK_LAPACK::sqrtGE (needs p*p)                                            **/
                                                 /**                   AK_LAPACK::correctMatGE (needs p*p)                                      **/
                                                 /**                   NMix::orderComp (needs at most Kmax)                                     **/
  dlambdaV_dSigma = dwork_misc + ldwork_logJacLambdaVSigma + *Kmax;  
  P_im            = dlambdaV_dSigma + LTp * LTp; /** needed by AK_LAPACK::sqrt_GE                                                               **/
  VPinv_re        = P_im + p_p;                  /** needed by AK_LAPACK::sqrt_GE                                                               **/
  VPinv_im        = VPinv_re + p_p;              /** needed by AK_LAPACK::sqrt_GE                                                               **/
  sqrt_Plambda_re = VPinv_im + p_p;              /** needed by AK_LAPACK::sqrt_GE                                                               **/
  sqrt_Plambda_im = sqrt_Plambda_re + *p;        /** needed by AK_LAPACK::sqrt_GE                                                               **/
  VP_re           = sqrt_Plambda_im + *p;        /** needed by AK_LAPACK::sqrt_GE                                                               **/
  VP_im           = VP_re + p_p;                 /** needed by AK_LAPACK::sqrt_GE                                                               **/
  // next       = VP_im + p_p;

  /*** Components of iwork ***/
  iwork_misc = iwork;                   /** working array for NMix::RJMCMC_logJacLambdaVSigma (needs p)                   **/
                                        /**                   Rand::RotationMatrix (needs p)                              **/
                                        /**                   AK_LAPACK::sqrtGE (needs p)                                 **/
                                        /**                   AK_LAPACK::correctMatGE (needs p)                           **/
  // next   = iwork_misc + *p;

  /***** Pointers for auxiliary vector u *****/
  /***** =============================== *****/
  u1 = u;
  u2 = u1 + 1;
  u3 = u2 + *p;
  

  /***** Choose the components to be splitted *****/
  /***** ==================================== *****/

  // TEMPORAR? For p > 1, a pair is sampled from all pairs,
  //           for p = 1, a pair of "adjacent components" is sampled
  if (*p > 1){

    // ===== Code for the situation when a pair is sampled from all pairs ===== //
    Rand::SamplePair(&j1, &j2, K);       // generates a pair (j1, j2) where j1 < j2
  }

  else{
    // ===== Code for the situation when j1 is sampled from K-1 components with the "smallest" mean  ===== //
    // ===== and j2 is the adjacent component with just a "higher" mean                              ===== //
    // ===== For a definition of ordering see NMix::orderComp function                               ===== //
    rankstar = (int)(floor(unif_rand() * (*K - 1)));  
    if (rankstar == *K - 1) jstar = *K - 2;                     // this row is needed with pobability 0 (unif_rand() would have to return 1)
    j1 = order[rankstar];
    j2 = order[rankstar + 1];
  }

  // ===== Code for the situation similar to the Matlab code of I. Papageorgiou ===== //
  //j1 = (int)(floor(unif_rand() * (*K - 1)));      // This way is used in the Matlab code of I. Papageorgiou,
  //if (j1 == *K - 1) j1 = *K - 2;                  // i.e., j1 is sampled from Unif(0,...,K-2)
  //j2      = *K - 1;                               // I have no idea why in this way...  

  /*** Pointers to chosen components ***/
  w1        = w  + j1;
  w2        = w1 + (j2 - j1);
  logw1     = logw  + j1;
  logw2     = logw1 + (j2 - j1);
  mu1       = mu + j1 * *p;
  mu2       = mu1 + (j2 - j1) * *p;
  Sigma1    = Sigma  + j1 * LTp;
  Sigma2    = Sigma1 + (j2 - j1) * LTp;
  Li1       = Li  + j1 * LTp;
  Li2       = Li1 + (j2 - j1) * LTp;
  Q1        = Q  + j1 * LTp;
  Q2        = Q1 + (j2 - j1) * LTp;
  log_dets1 = log_dets  + j1 * 2;
  log_dets2 = log_dets1 + (j2 - j1) * 2;
  rrInv1    = rInv + j1;
  rrInv2    = rrInv1 + (j2 - j1);
  rInv1     = *rrInv1;
  rInv2     = *rrInv2;
  mixN1     = mixN  + j1;
  mixN2     = mixN1 + (j2 - j1);

  /*** Pointers to the old places where a new component will be written (if accepted)                                         ***/
  /*** jstar   = index of the place where a new component will be written on the place of one of old components (if accepted) ***/
  /*** jremove = index of the place where an old component will be removed (and the rest will be shifted forward)             ***/
  /*** I will ensure jstar < jremove                                                                                          ***/
  if (j1 < j2){                   
    jstar   = j1;              // combined component will be placed on place with a lower index if combine move accepted
    jremove = j2;              // component with a higher index will be removed if combine move accepted

    wOldP        = w1;         // places where a new component will be written
    logwOldP     = logw1;
    muOldP       = mu1;
    SigmaOldP    = Sigma1;
    LiOldP       = Li1;
    QOldP        = Q1;
    log_detsOldP = log_dets1;
    rrInvOldP    = rrInv1;
    mixNOldP     = mixN1;  
  }
  else{
    jstar   = j2;
    jremove = j1;

    wOldP        = w2;         // places where a new component will be written
    logwOldP     = logw2;
    muOldP       = mu2;
    SigmaOldP    = Sigma2;
    LiOldP       = Li2;
    QOldP        = Q2;
    log_detsOldP = log_dets2;
    rrInvOldP    = rrInv2;
    mixNOldP     = mixN2;  
  }


  /***** Compute proposed weight, mean, variance and log-Jacobian of the RJ (split) move *****/
  /***** =============================================================================== *****/

  /***** Proposed weight *****/
  *wstar = *w1 + *w2;
  *logwstar = AK_Basic::log_AK(wstar[0]);
  *u1 = *w1 / *wstar;
  one_u1 = 1 - *u1;

  /***** Log-Jacobian, part 1                                                          *****/
  /***** Jacobian = dtheta/dtheta^*, that is corresponds to the reversal split move    *****/
  log_Jacob = *logwstar;

  /***** Code for UNIVARIATE mixtures *****/
  if (*p == 1){          /*** UNIVARIATE mixture             ***/               

    /***** Check inequality condition which is satisfied by the reversal split move *****/
    /***** This will ensure that u2 is positive                                     *****/
    // ===== The following code is needed only when (j1, j2) is sampled from a set of all pairs and hence there is no guarantee ===== //
    // ===== that mu1 <= mu2                                                                                                    ===== //
    //if (*mu1 > *mu2){             // switch labels j1, j2 such that mu1 < mu2 to get correctly u1, u2 and u3
    //  AK_Basic::switchValues(&j1, &j2);
    //  *u1    = one_u1;
    //  one_u1 = 1 - *u1;
    //  AK_Basic::switchPointers(&w1,        &w2);
    //  AK_Basic::switchPointers(&logw1,     &logw2);
    //  AK_Basic::switchPointers(&mu1,       &mu2);
    //  AK_Basic::switchPointers(&Sigma1,    &Sigma2);
    //  AK_Basic::switchPointers(&Li1,       &Li2);
    //  AK_Basic::switchPointers(&Q1,        &Q2);
    //  AK_Basic::switchPointers(&log_dets1, &log_dets2);
    //  AK_Basic::switchPointers(&rInv1,     &rInv2);
    //  AK_Basic::switchPointers(&mixN1,     &mixN2);
    //}

    /***** Values derived from the auxiliary number u1 corresponding to the reversal split move *****/
    sqrt_u1_ratio             = sqrt(*u1 / (1 - *u1));
    log_u1                    = AK_Basic::log_AK(*u1);
    log_one_u1                = AK_Basic::log_AK(1 - *u1);
    log_u1_one_minus_u1_min32 = -1.5 * (log_u1+ log_one_u1);

    /***** Proposed mean:   mustar = u1 * mu1 + (1 - u1) * mu2 *****/
    *mustar = *u1 * *mu1 + one_u1 * *mu2;

    /***** Proposed variance *****/
    *Sigmastar = *u1 * (*mu1 * *mu1 + *Sigma1) + one_u1 * (*mu2 * *mu2 + *Sigma2) - *mustar * *mustar;
    if (*Sigmastar <= 0) return;
    
    /***** Cholesky decomposition of the proposed variance (standard deviation) *****/
    *Lstar = sqrt(*Sigmastar);

    /***** Inverted proposed variance *****/
    *Qstar = 1 / *Sigmastar;

    /***** Auxiliary numbers u2 and u3 correspoding to the reversal split move *****/
    *u2 = ((*mustar - *mu1) / *Lstar) * sqrt_u1_ratio;
    one_minus_u2sq = 1 - *u2 * *u2;

    *u3 = (*u1 * *Sigma1) / (one_minus_u2sq * *Sigmastar);

    /***** Log-Jacobian, part 2 *****/
    log_Jacob += AK_Basic::log_AK(one_minus_u2sq * *Sigmastar * *Lstar) + log_u1_one_minus_u1_min32;

    /***** log|d(Lambdastar,Vstar)/d(Sigmastar)|*****/             // NOT NEEDED AS IT IS ZERO,  moreover, 25/01/2008:  included in logJ_part3
    //*log_dlambdaV_dSigma = 0.0;

    /***** Log-Jacobian, part 3 *****/                             // NOT NEEDED AS IT IS ZERO
    //*logJ_part3 = 0.0;    
    //log_Jacob += *logJ_part3;

    /***** log-dets for the proposed variance *****/
    log_detsstar[0] = -AK_Basic::log_AK(*Lstar);        /** log_detsstar[0] = -log(Lstar) = log|Sigmastar|^{-1/2}  **/
    log_detsstar[1] = log_dets1[1];                        /** log_detsstar[1] = -p * log(sqrt(2*pi))                 **/
  }

  else{                  /*** MULTIVARIATE mixture                                      ***/

    /***** Values derived from the auxiliary number u1 corresponding to the reversal split move *****/
    sqrt_u1_ratio             = sqrt(*u1 / (1 - *u1));
    log_u1                    = AK_Basic::log_AK(*u1);
    log_one_u1                = AK_Basic::log_AK(1 - *u1);
    log_u1_one_minus_u1_min32 = -1.5 * (log_u1+ log_one_u1);

    /***** Spectral decomposition of Sigma1 *****/
    AK_Basic::copyArray(SigmaTemp, Sigma1, LTp);
    F77_CALL(dspev)("V", "L", p, SigmaTemp, Lambda_dspev, V_dspev, p, dwork_misc, err);    /** eigen values in ascending order  **/
    if (*err){
      warning("%s: Spectral decomposition of Sigma[%d] failed.\n", fname, j1);    
      return;
    }
    //AK_LAPACK::spevAsc2spevDesc(Lambda1, V1, Lambda_dspev, V_dspev, p);                  /** eigen values in descending order **/
    // 05/02/2008:  CHANGE - eigenvalues are assumed to be in ASCENDING order
    AK_LAPACK::correctMatGE(V1, dwork_misc, iwork_misc, err, p);                           /** be sure that det(V1) = 1 and not -1 **/
    if (*err){
      warning("%s: Correction of V[%d] failed.\n", fname, j1);    
      return;
    }

    /***** Spectral decomposition of Sigma2 *****/
    AK_Basic::copyArray(SigmaTemp, Sigma2, LTp);
    F77_CALL(dspev)("V", "L", p, SigmaTemp, Lambda_dspev, V_dspev, p, dwork_misc, err);    /** eigen values in ascending order  **/
    if (*err){
      warning("%s: Spectral decomposition of Sigma[%d] failed.\n", fname, j2);    
      return;
    }
    //AK_LAPACK::spevAsc2spevDesc(Lambda2, V2, Lambda_dspev, V_dspev, p);                    /** eigen values in descending order **/
    // 05/02/2008:  CHANGE - eigenvalues are assumed to be in ASCENDING order
    AK_LAPACK::correctMatGE(V2, dwork_misc, iwork_misc, err, p);                             /** be sure that det(V2) = 1 and not -1 **/
    if (*err){
      warning("%s: Correction of V[%d] failed.\n", fname, j2);    
      return;
    }

    /***** Rotation matrix which corresponds to the reversible split move, P = (V1 %*% t(V2))^{1/2} *****/
    F77_CALL(dgemm)("N", "T", p, p, p, &AK_Basic::_ONE_DOUBLE, V1, p, V2, p, &AK_Basic::_ZERO_DOUBLE, P, p);       /*** P = V1 %*% t(V2) ***/
    AK_LAPACK::sqrtGE(P, P_im, VPinv_re, VPinv_im, complexP, sqrt_Plambda_re, sqrt_Plambda_im, VP_re, VP_im, dwork_misc, iwork_misc, err, p);
    if (*err){
      warning("%s: Computation of the square root of the rotation matrix failed.\n", fname);    
      return;
    }

    /***** Proposed eigenvectors:   Vstar = (1/2) * (t(P) %*% V1 + P %*% V2) *****/
    F77_CALL(dgemm)("T", "N", p, p, p, &AK_Basic::_ONE_DOUBLE, P, p, V1, p, &AK_Basic::_ZERO_DOUBLE, VP_re, p);       /*** VP_re = t(P) %*% V1  ***/
    F77_CALL(dgemm)("N", "N", p, p, p, &AK_Basic::_ONE_DOUBLE, P, p, V2, p, &AK_Basic::_ZERO_DOUBLE, Vstar, p);       /*** Vstar = P %*% V2     ***/

    /***** Proposed mean:  mustar = u1*mu1 + (1 - u1)*mu2                                          *****/
    /***** Finalize computation of Vstar (sum t(P) %*% V1 and P %*% V2 and multiply it by 0.5)     *****/
    mu1P    = mu1;
    mu2P    = mu2;
    mustarP = mustar;

    VstarP = Vstar;
    VP_reP = VP_re;

    for (i1 = 0; i1 < *p; i1++){
      *mustarP = *u1 * *mu1P + one_u1 * *mu2P;
      mu1P++;
      mu2P++;
      mustarP++;

      for (i0 = 0; i0 < *p; i0++){
        *VstarP += *VP_reP;
        *VstarP *= 0.5;
        VstarP++;
        VP_reP++;
      }
    }

    /***** Proposed eigenvalues                                                                                                *****/    
    /***** Auxiliary numbers u2 and u3 correspoding to the reversal split move                                                 *****/
    /***** Log-Jacobian, part 2                                                                                                *****/
    /***** Check also the adjacency condition from the reversal split move -> u2[p-1] must be positive                         *****/
    /****** -> if not satisfied, take abs(u2[p-1]) -> this should be equivalent to labelswitching which is then not necessary  *****/
    LambdastarP = Lambdastar;
    u2P         = u2;
    u3P         = u3;

    Lambda1P    = Lambda1;
    Lambda2P    = Lambda2;
    VstarP      = Vstar;

    for (i1 = 0; i1 < *p; i1++){
      mu1_vstar    = 0.0;
      mu2_vstar    = 0.0;
      mustar_vstar = 0.0;

      mu1P    = mu1;
      mu2P    = mu2;
      mustarP = mustar;
      
      for (i0 = 0; i0 < *p; i0++){
        mu1_vstar    += *mu1P * *VstarP;
        mu2_vstar    += *mu2P * *VstarP;
        mustar_vstar += *mustarP * *VstarP;
   
        mu1P++;
        mu2P++;
        mustarP++;
        VstarP++;
      }

      *LambdastarP = *u1 * (mu1_vstar * mu1_vstar + *Lambda1P) + one_u1 * (mu2_vstar * mu2_vstar + *Lambda2P) - mustar_vstar * mustar_vstar;
      if (*LambdastarP <= 0){
        return;
      }

      *u2P = ((mustar_vstar - mu1_vstar) / sqrt(*LambdastarP)) * sqrt_u1_ratio;
      if (i1 == *p - 1 && *u2P <= 0) *u2P *= (-1);
      one_minus_u2sq = 1 - *u2P * *u2P;
      *u3P = (*u1 * *Lambda1P) / (one_minus_u2sq * *LambdastarP);
      log_Jacob += 1.5 * AK_Basic::log_AK(*LambdastarP) + AK_Basic::log_AK(one_minus_u2sq);

      LambdastarP++;
      Lambda1P++;
      Lambda2P++;
      u2P++;
      u3P++;
    }
    log_Jacob += *p * log_u1_one_minus_u1_min32;

    /***** Proposed variance *****/
    AK_LAPACK::spevSY2SP(Sigmastar, Lambdastar, Vstar, p);

    /***** Cholesky decomposition of the proposed variance *****/
    AK_Basic::copyArray(Lstar, Sigmastar, LTp);
    F77_CALL(dpptrf)("L", p, Lstar, err);
    if (*err){ 
      warning("%s: Cholesky decomposition of proposed Sigmastar failed.\n", fname);    
      return;
    }

    /***** Inverted proposed variance *****/
    AK_Basic::copyArray(Qstar, Lstar, LTp);
    F77_CALL(dpptri)("L", p, Qstar, err);
    if (*err){
      warning("%s: Inversion of proposed Sigmastar failed.\n", fname);    
      return;
    }

    /***** log-dets for the proposed variance *****/
    log_detsstar[0] = 0.0;
    LstarP = Lstar;
    for (i0 = *p; i0 > 0; i0--){                       /** log_detsstar[0] = -sum(log(Lstar[i,i])) **/
      log_detsstar[0] -= AK_Basic::log_AK(*LstarP);
      LstarP += i0;
    }
    log_detsstar[1] = log_dets1[1];                    /** log_detsstar[1] = -p * log(sqrt(2*pi)) **/

    /***** log|d(Lambdastar,Vstar)/d(Sigmastar)|*****/        // 25/01/2008:  this part included in NMix::RJMCMC_logJac_part3
    //NMix::RJMCMC_logJacLambdaVSigma(log_dlambdaV_dSigma, dlambdaV_dSigma, dwork_misc, iwork_misc, err,
    //                                Lambdastar, Vstar, Sigmastar, p, &AK_Basic::_ZERO_INT);
    //if (*err){ 
    //  warning("%s: RJMCMC_logJacLambdaVSigma failed.\n", fname);    
    //  return;
    //}

    /***** Log-Jacobian, part 3                                *****/
    NMix::RJMCMC_logJac_part3(logJ_part3, Lambdastar, Vstar, P, p);
    log_Jacob += *logJ_part3;
  }                      /*** end of the code for a MULTIVARIATE mixture ***/

  /***** Log-density of the auxiliary vector *****/
  /***** =================================== *****/
  ld_u(log_dens_u, u, pars_dens_u, p);


  /***** Propose new allocations              *****/
  /***** Compute logarithm of reversal Palloc *****/
  /***** ==================================== *****/
  log_Palloc  = 0.0;                 /** to compute sum[i: r[i]=j1] log P(r[i]=j1|...) + sum[i: r[i]=j2] log P(r[i]=j2|...)    **/
  logL12[0]   = 0.0;                 /** to sum up log_phi for observations in the original two components                     **/
  logLstar[0] = 0.0;                 /** to sum up log_phi for observations belonging to the new combined component            **/

  *mixNstar = *mixN1 + *mixN2;

  /*** Loop for component j1 ***/
  yP            = y;                          /** all observations **/
  rInv1P        = rInv1;
  rInvPrev      = 0;
  for (i0 = 0; i0 < *mixN1; i0++){
    yP            += (*rInv1P - rInvPrev) * *p;

    /*** log(phi(y | mu1, Sigma1)), log(phi(y | mu2, Sigma2)), log(phi(y | mustar, Sigmastar)) ***/  
    Dist::ldMVN1(&log_phi1,    dwork_misc, yP, mu1,    Li1,   log_dets1,    p);
    Dist::ldMVN1(&log_phi2,    dwork_misc, yP, mu2,    Li2,   log_dets2,    p);
    Dist::ldMVN2(&log_phistar, dwork_misc, yP, mustar, Lstar, log_detsstar, p);

    /*** Probabilities of the full conditional of r (to compute log_Palloc of the reversal split move) ***/
    log_Prob_r1  = log_phi1 + *logw1;
    log_Prob_r2  = log_phi2 + *logw2;    
    max_log_Prob_r12 = (log_Prob_r1 > log_Prob_r2 ? log_Prob_r1 : log_Prob_r2);
    log_Prob_r1 -= max_log_Prob_r12;
    log_Prob_r2 -= max_log_Prob_r12;
    Prob_r1 = AK_Basic::exp_AK(log_Prob_r1);
    Prob_r2 = AK_Basic::exp_AK(log_Prob_r2);
    sum_Prob_r12 = Prob_r1 + Prob_r2;

    log_Palloc  += log_Prob_r1 - AK_Basic::log_AK(sum_Prob_r12);
    logL12[0]   += log_phi1;
    logLstar[0] += log_phistar;

    rInvPrev = *rInv1P;
    rInv1P++;
  }

  /*** Loop for component j2 ***/
  yP            = y;                          /** all observations **/
  rInv2P        = rInv2;
  rInvPrev      = 0;
  for (i0 = 0; i0 < *mixN2; i0++){
    yP            += (*rInv2P - rInvPrev) * *p;

    /*** log(phi(y | mu1, Sigma1)), log(phi(y | mu2, Sigma2)), log(phi(y | mustar, Sigmastar)) ***/  
    Dist::ldMVN1(&log_phi1,    dwork_misc, yP, mu1,    Li1,   log_dets1,    p);
    Dist::ldMVN1(&log_phi2,    dwork_misc, yP, mu2,    Li2,   log_dets2,    p);
    Dist::ldMVN2(&log_phistar, dwork_misc, yP, mustar, Lstar, log_detsstar, p);

    /*** Probabilities of the full conditional of r (to compute log_Palloc of the reversal split move) ***/
    log_Prob_r1  = log_phi1 + *logw1;
    log_Prob_r2  = log_phi2 + *logw2;    
    max_log_Prob_r12 = (log_Prob_r1 > log_Prob_r2 ? log_Prob_r1 : log_Prob_r2);
    log_Prob_r1 -= max_log_Prob_r12;
    log_Prob_r2 -= max_log_Prob_r12;
    Prob_r1 = AK_Basic::exp_AK(log_Prob_r1);
    Prob_r2 = AK_Basic::exp_AK(log_Prob_r2);
    sum_Prob_r12 = Prob_r1 + Prob_r2;

    log_Palloc  += log_Prob_r2 - AK_Basic::log_AK(sum_Prob_r12);
    logL12[0]   += log_phi2;
    logLstar[0] += log_phistar;

    rInvPrev = *rInv2P;
    rInv2P++;
  }

  logL12[1]   = *mixN1 * *logw1 + *mixN2 * *logw2;
  logLstar[1] = *mixNstar * *logwstar;


  /***** Logarithm of the likelihood ratio (of the reversal split move) *****/
  /***** ============================================================== *****/
  log_LikelihoodRatio = logL12[0] + logL12[1] - logLstar[0] - logLstar[1];


  /***** Logarithm of the prior ratio (of the reversal split move) *****/
  /***** ========================================================= *****/  

  /***** log-ratio of priors on mixture weights *****/
  log_PriorRatio = (*delta - 1) * (*logw1 + *logw2 - *logwstar) - lbeta(*delta, *K * *delta);
  
  /***** log-ratio of priors on K (+ factor comming from the equivalent ways that the components can produce the same likelihood) *****/
  switch (*priorK){
  case NMix::K_FIXED:
  case NMix::K_UNIF:      /*** K * (p(K)/p(K-1)) = K ***/
    log_PriorRatio += logK[*K - 1];
    break;
  case NMix::K_TPOISS:    /*** K * (p(K)/p(K-1)) = K * (lambda/K) = lambda ***/
    log_PriorRatio += *log_lambda;
    break;
  }

  /***** log-ratio of priors on mixture means *****/
  switch (*priormuQ){
  case NMix::MUQ_NC:
    Dist::ldMVN1(log_prior_mu1, dwork_misc, mu1, xi + j1 * *p, Li1, ZERO_ZERO, p);
    *log_prior_mu1 *= c[j1];
    *log_prior_mu1 += log_dets1[0] + log_dets1[1] + (*p * log_c[j1]) / 2;

    Dist::ldMVN1(log_prior_mu2, dwork_misc, mu2, xi + j2 * *p, Li2, ZERO_ZERO, p);
    *log_prior_mu2 *= c[j2];
    *log_prior_mu2 += log_dets2[0] + log_dets2[1] + (*p * log_c[j2]) / 2;

    Dist::ldMVN2(log_prior_mustar, dwork_misc, mustar, xi + jstar * *p, Lstar, ZERO_ZERO, p);
    *log_prior_mustar *= c[jstar];
    *log_prior_mustar += log_detsstar[0] + log_detsstar[1] + (*p * log_c[jstar]) / 2;
    break;

  case NMix::MUQ_IC:
    Dist::ldMVN1(log_prior_mu1,    dwork_misc, mu1,    xi + j1 * *p,    D_Li + j1 * LTp,    log_dets_D + j1 * 2,    p);
    Dist::ldMVN1(log_prior_mu2,    dwork_misc, mu2,    xi + j2 * *p,    D_Li + j2 * LTp,    log_dets_D + j2 * 2,    p);
    Dist::ldMVN1(log_prior_mustar, dwork_misc, mustar, xi + jstar * *p, D_Li + jstar * LTp, log_dets_D + jstar * 2, p);
    break;
  }
  log_PriorRatio += *log_prior_mu1 + *log_prior_mu2 - *log_prior_mustar;

  /***** log-ratio of priors on mixture (inverse) variances *****/
  Dist::ldWishart_diagS(log_prior_Q1,    Q1,    log_dets1,    log_Wishart_const, zeta, gammaInv, log_sqrt_detXiInv, p);
  Dist::ldWishart_diagS(log_prior_Q2,    Q2,    log_dets2,    log_Wishart_const, zeta, gammaInv, log_sqrt_detXiInv, p);
  Dist::ldWishart_diagS(log_prior_Qstar, Qstar, log_detsstar, log_Wishart_const, zeta, gammaInv, log_sqrt_detXiInv, p);
  log_PriorRatio += *log_prior_Q1 + *log_prior_Q2 - *log_prior_Qstar;


  /***** Logarithm of the proposal ratio (of the reversal split move) *****/
  /***** ============================================================ *****/
  log_ProposalRatio = logPcombine[*K - 1] - logPsplit[*K - 2] - log_Palloc - *log_dens_u;


  /***** Accept/reject *****/
  /***** ============= *****/
  *log_AR = -(log_LikelihoodRatio + log_PriorRatio + log_ProposalRatio + log_Jacob);
  if (*log_AR >= 0) *accept = 1;
  else{                           /** decide by sampling from the exponential distribution **/
    erand = exp_rand();
    *accept = (erand > -(*log_AR) ? 1 : 0);
  }


  /***** Update mixture values if proposal accepted *****/
  /***** ========================================== *****/
  // Remember that jstar < jremove (irrespective of values j1 and j2)
  //
  if (*accept){

    /*** r: loop for component j1 ***/
    rP            = r;                           /** all observations               **/
    rInv1P        = rInv1;                       /** observations from component j1 **/
    rInvPrev      = 0;
    for (i0 = 0; i0 < *mixN1; i0++){
      rP  += (*rInv1P - rInvPrev);
      *rP = jstar;

      rInvPrev = *rInv1P;
      rInv1P++;
    }

    /*** r: loop for component j2 ***/
    rP            = r;                           /** all observations               **/
    rInv2P        = rInv2;                       /** observations from component j2 **/
    rInvPrev      = 0;
    for (i0 = 0; i0 < *mixN2; i0++){
      rP  += (*rInv2P - rInvPrev);
      *rP = jstar;

      rInvPrev = *rInv2P;
      rInv2P++;
    }

    /*** w: weights ***/
    *wOldP = *wstar;
    wOldP += (jremove - jstar);           /** jump to the point from which everything must be shifted **/

    /*** logw: log-weights ***/
    *logwOldP = *logwstar;
    logwOldP += (jremove - jstar);        /** jump to the point from which everything must be shifted **/
    
    /*** mu:     means                                                                                           ***/
    /*** Q:      inverse variances                                                                               ***/
    /*** Sigma:  variances                                                                                       ***/
    /*** Li:     Cholesky decomposition of inverse variances, must be computed                                    ***/
    muNewP    = mustar;
    QNewP     = Qstar;
    SigmaNewP = Sigmastar;

    Listar    = LiOldP;
    for (i1 = 0; i1 < *p; i1++){
      *muOldP = *muNewP;
      muOldP++;
      muNewP++;

      for (i0 = i1; i0 < *p; i0++){
        *QOldP  = *QNewP;
        *LiOldP = *QNewP;     /* preparing to calculate Cholesky decomposition */
        QOldP++;
        LiOldP++;
        QNewP++;

        *SigmaOldP = *SigmaNewP;
        SigmaOldP++;
        SigmaNewP++;
      }
    }

    F77_CALL(dpptrf)("L", p, Listar, err);
    if (*err){ 
      error("%s: Cholesky decomposition of proposed Q(star) failed.\n", fname);     // this should never happen
    }

    muOldP    += *p * (jremove - jstar - 1);       /** jump to the point from which everything must be shifted **/
    QOldP     += LTp * (jremove - jstar - 1);      /** jump to the point from which everything must be shifted **/    
    SigmaOldP += LTp * (jremove - jstar - 1);      /** jump to the point from which everything must be shifted **/    
    LiOldP    += LTp * (jremove - jstar - 1);      /** jump to the point from which everything must be shifted **/    

    /*** log_dets ***/
    log_detsOldP[0] = log_detsstar[0];
    log_detsOldP++;
    log_detsOldP += 2 * (jremove - jstar - 1);     /** jump to the point from which everything must be shifted **/        

    /*** mixN ***/
    *mixNOldP = *mixNstar;
    mixNOldP += (jremove - jstar);                 /** jump to the point from which everything must be shifted **/

    /*** rInv ***/
    rInvP = *rrInvOldP;
    rP    = r;
    for (i0 = 0; i0 < *n; i0++){
      if (*rP == jstar){
        *rInvP = i0;
        rInvP++;
      }
      rP++;
    }
    rrInvOldP += (jremove - jstar);                /** jump to the point from which everything must be shifted **/

    /*** Shift forward components after the removed one ***/
    for (k = jremove; k < *K-1; k++){
      *wOldP = *(wOldP + 1);
      wOldP++;

      *logwOldP = *(logwOldP + 1);
      logwOldP++;
 
      for (i1 = 0; i1 < *p; i1++){
        *muOldP = *(muOldP + *p);
        muOldP++;

        for (i0 = i1; i0 < *p; i0++){
          *QOldP = *(QOldP + LTp);
          QOldP++;

          *SigmaOldP = *(SigmaOldP + LTp);
          SigmaOldP++;

          *LiOldP = *(LiOldP + LTp);
          LiOldP++;
        }
      }

      log_detsOldP[0] = log_detsOldP[2];
      log_detsOldP += 2;

      *mixNOldP = *(mixNOldP + 1);
      AK_Basic::copyArray(*rrInvOldP, *(rrInvOldP + 1), *mixNOldP);
      mixNOldP++;
      rrInvOldP++;
    }

    /*** K ***/
    *K -= 1;

    /*** order, rank ***/
    NMix::orderComp(order, rank, dwork_misc, &AK_Basic::_ZERO_INT, K, mu, p);   
  }                /*** end of if (*accept) ***/

  return;
}
Пример #17
0
double rpois(double mu)
{
    /* Factorial Table (0:9)! */
    const double fact[10] =
    {
        1., 1., 2., 6., 24., 120., 720., 5040., 40320., 362880.
    };

    /* These are static --- persistent between calls for same mu : */
    static int l, m;

    static double b1, b2, c, c0, c1, c2, c3;
    static double pp[36], p0, p, q, s, d, omega;
    static double big_l;/* integer "w/o overflow" */
    static double muprev = 0., muprev2 = 0.;/*, muold    = 0.*/

    /* Local Vars  [initialize some for -Wall]: */
    double del, difmuk= 0., E= 0., fk= 0., fx, fy, g, px, py, t, u= 0., v, x;
    double pois = -1.;
    int k, kflag, big_mu, new_big_mu = false;

    if (!R_FINITE(mu))
        ML_ERR_return_NAN;

    if (mu <= 0.)
        return 0.;

    big_mu = mu >= 10.;
    if(big_mu)
        new_big_mu = false;

    if (!(big_mu && mu == muprev)) {/* maybe compute new persistent par.s */

        if (big_mu) {
            new_big_mu = true;
            /* Case A. (recalculation of s,d,l  because mu has changed):
             * The poisson probabilities pk exceed the discrete normal
             * probabilities fk whenever k >= m(mu).
             */
            muprev = mu;
            s = sqrt(mu);
            d = 6. * mu * mu;
            big_l = FLOOR(mu - 1.1484);
            /* = an upper bound to m(mu) for all mu >= 10.*/
        }
        else { /* Small mu ( < 10) -- not using normal approx. */

            /* Case B. (start new table and calculate p0 if necessary) */

            /*muprev = 0.;-* such that next time, mu != muprev ..*/
            if (mu != muprev) {
                muprev = mu;
                m = std::max(1, (int) mu);
                l = 0; /* pp[] is already ok up to pp[l] */
                q = p0 = p = exp(-mu);
            }

            repeat {
                /* Step U. uniform sample for inversion method */
                u = unif_rand(BOOM::GlobalRng::rng);
                if (u <= p0)
                    return 0.;

                /* Step T. table comparison until the end pp[l] of the
                   pp-table of cumulative poisson probabilities
                   (0.458 > ~= pp[9](= 0.45792971447) for mu=10 ) */
                if (l != 0) {
                    for (k = (u <= 0.458) ? 1 : std::min(l, m);  k <= l; k++)
                        if (u <= pp[k])
                            return (double)k;
                    if (l == 35) /* u > pp[35] */
                        continue;
                }
                /* Step C. creation of new poisson
                   probabilities p[l..] and their cumulatives q =: pp[k] */
                l++;
                for (k = l; k <= 35; k++) {
                    p *= mu / k;
                    q += p;
                    pp[k] = q;
                    if (u <= q) {
                        l = k;
                        return (double)k;
                    }
                }
                l = 35;
            } /* end(repeat) */
        }/* mu < 10 */

    } /* end {initialize persistent vars} */

/* Only if mu >= 10 : ----------------------- */

    /* Step N. normal sample */
    g = mu + s * norm_rand(BOOM::GlobalRng::rng);/* norm_rand() ~ N(0,1), standard normal */

    if (g >= 0.) {
        pois = FLOOR(g);
        /* Step I. immediate acceptance if pois is large enough */
        if (pois >= big_l)
            return pois;
        /* Step S. squeeze acceptance */
        fk = pois;
        difmuk = mu - fk;
        u = unif_rand(BOOM::GlobalRng::rng); /* ~ U(0,1) - sample */
        if (d * u >= difmuk * difmuk * difmuk)
            return pois;
    }

    /* Step P. preparations for steps Q and H.
       (recalculations of parameters if necessary) */

    if (new_big_mu || mu != muprev2) {
        /* Careful! muprev2 is not always == muprev
           because one might have exited in step I or S
           */
        muprev2 = mu;
        omega = M_1_SQRT_2PI / s;
        /* The quantities b1, b2, c3, c2, c1, c0 are for the Hermite
         * approximations to the discrete normal probabilities fk. */

        b1 = one_24 / mu;
        b2 = 0.3 * b1 * b1;
        c3 = one_7 * b1 * b2;
        c2 = b2 - 15. * c3;
        c1 = b1 - 6. * b2 + 45. * c3;
        c0 = 1. - b1 + 3. * b2 - 15. * c3;
        c = 0.1069 / mu; /* guarantees majorization by the 'hat'-function. */
    }

    if (g >= 0.) {
        /* 'Subroutine' F is called (kflag=0 for correct return) */
        kflag = 0;
        goto Step_F;
    }


    repeat {
        /* Step E. Exponential Sample */

        E = exp_rand(BOOM::GlobalRng::rng);     /* ~ Exp(1) (standard exponential) */

        /*  sample t from the laplace 'hat'
            (if t <= -0.6744 then pk < fk for all mu >= 10.) */
        u = 2 * unif_rand(BOOM::GlobalRng::rng) - 1.;
        t = 1.8 + fsign(E, u);
        if (t > -0.6744) {
            pois = FLOOR(mu + s * t);
            fk = pois;
            difmuk = mu - fk;

            /* 'subroutine' F is called (kflag=1 for correct return) */
            kflag = 1;

          Step_F: /* 'subroutine' F : calculation of px,py,fx,fy. */

            if (pois < 10) { /* use factorials from table fact[] */
                px = -mu;
                py = pow(mu, pois) / fact[(int)pois];
            }
            else {
                /* Case pois >= 10 uses polynomial approximation
                   a0-a7 for accuracy when advisable */
                del = one_12 / fk;
                del = del * (1. - 4.8 * del * del);
                v = difmuk / fk;
                if (fabs(v) <= 0.25)
                    px = fk * v * v * (((((((a7 * v + a6) * v + a5) * v + a4) *
                                          v + a3) * v + a2) * v + a1) * v + a0)
                        - del;
                else /* |v| > 1/4 */
                    px = fk * log(1. + v) - difmuk - del;
                py = M_1_SQRT_2PI / sqrt(fk);
            }
            x = (0.5 - difmuk) / s;
            x *= x;/* x^2 */
            fx = -0.5 * x;
            fy = omega * (((c3 * x + c2) * x + c1) * x + c0);
            if (kflag > 0) {
                /* Step H. Hat acceptance (E is repeated on rejection) */
                if (c * fabs(u) <= py * exp(px + E) - fy * exp(fx + E))
                    break;
            } else
                /* Step Q. Quotient acceptance (rare case) */
                if (fy - u * fy <= py * exp(px - fx))
                    break;
        }/* t > -.67.. */
    }
    return pois;
}
Пример #18
0
void rextremalttbm(double *coord, int *nObs, int *nSite, int *dim,
		   int *covmod, int *grid, double *nugget, double *range,
		   double *smooth, double *DoF, double *uBound, int *nlines,
		   double *ans){
  /* This function generates random fields from the Extremal-t model

     coord: the coordinates of the locations
      nObs: the number of observations to be generated
    nSite: the number of locations
       dim: the random field is generated in R^dim
    covmod: the covariance model
      grid: Does coord specifies a grid?
      nugget: the nugget parameter
     range: the range parameter
    smooth: the smooth parameter
       DoF: the degree of freedom
 blockSize: simulated field is the maximum over blockSize ind. replicates
    nlines: the number of lines used for the TBM algo
       ans: the generated random field */

  int i, neffSite, lagi = 1, lagj = 1;
  double sill = 1 - *nugget;
  const double irange = 1 / *range;

  //rescale the coordinates
  for (i=(*nSite * *dim);i--;)
        coord[i] = coord[i] * irange;

  double *lines = malloc(3 * *nlines * sizeof(double));
  
  if ((*covmod == 3) && (*smooth == 2))
    //This is the gaussian case
    *covmod = 5;

  //Generate lines
  vandercorput(nlines, lines);

  if (*grid){
    neffSite = R_pow_di(*nSite, *dim);
    lagi = neffSite;
  }

  else{
    neffSite = *nSite;
    lagj = *nObs;
  }

  double *gp = malloc(neffSite * sizeof(double));

  GetRNGstate();
  
  for (i=*nObs;i--;){
    int nKO = neffSite;
    double poisson = 0;

    while (nKO){

      /* ------- Random rotation of the lines ----------*/
      double u = unif_rand() - 0.5,
	v = unif_rand() - 0.5,
	w = unif_rand() - 0.5,
	angle = runif(0, M_2PI),	
	inorm = 1 / sqrt(u * u + v * v + w * w);
      
      u *= inorm;
      v *= inorm;
      w *= inorm;
      
      rotation(lines, nlines, &u, &v, &w, &angle);
      /* -------------- end of rotation ---------------*/
      
      poisson += exp_rand();
      double ipoisson = 1 / poisson,
	thresh = *uBound * ipoisson;
      
      /* We simulate one realisation of a gaussian random field with
	 the required covariance function */
      for (int j=neffSite;j--;)
	gp[j] = 0;

      tbmcore(nSite, &neffSite, dim, covmod, grid, coord, nugget,
	      &sill, range, smooth, nlines, lines, gp);
      
      nKO = neffSite;
      for (int j=neffSite;j--;){
	double dummy = R_pow(fmax2(0, gp[j]), *DoF) * ipoisson;
	ans[j * lagj + i * lagi] = fmax2(dummy, ans[j * lagj + i * lagi]);
	nKO -= (thresh <= ans[j * lagj + i * lagi]);
      }    
    }
  }
  
  PutRNGstate();
  
  //Lastly we multiply by the normalizing constant
  const double imean = M_SQRT_PI * R_pow(2, -0.5 * (*DoF - 2)) /
    gammafn(0.5 * (*DoF + 1));
  
  for (i=(neffSite * *nObs);i--;)
    ans[i] *= imean;
  
  free(lines); free(gp);
  return;
}
Пример #19
0
void rextremaltcirc(int *nObs, int *ngrid, double *steps, int *dim,
		    int *covmod, double *nugget, double *range,
		    double *smooth, double *DoF, double *uBound, double *ans){
  /* This function generates random fields from the Schlather model

     nObs: the number of observations to be generated
    ngrid: the number of locations along one axis
      dim: the random field is generated in R^dim
   covmod: the covariance model
     nugget: the nugget parameter
    range: the range parameter
   smooth: the smooth parameter
      DoF: the degree of freedom
blockSize: see rextremalttbm
      ans: the generated random field */

  int i, j, k = -1, nbar = R_pow_di(*ngrid, *dim), r, m;
  const double zero = 0;
  double *rho, *irho, sill = 1 - *nugget;
    //Below is a table of highly composite numbers
  int HCN[39] = {1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240,
		 360, 720, 840, 1260, 1680, 2520, 5040, 7560,
		 10080, 15120, 20160, 25200, 27720, 45360, 50400,
		 55440, 83160, 110880, 166320, 221760, 277200,
		 332640, 498960, 554400, 665280, 720720, 1081080};

    
  /* Find the smallest size m for the circulant embedding matrix */
  {
    int dummy = 2 * (*ngrid - 1);
    do {
      k++;
      m = HCN[k];
    } while (m < dummy);
  }
  
  /* ---------- beginning of the embedding stage ---------- */
  int mbar = m * m, halfM = m / 2, notPosDef = 0;
  do {
    double *dist = (double *)R_alloc(mbar, sizeof(double));

    notPosDef = 0;
    //Computation of the distance
    for (r=mbar;r--;){
      i = r % m;
      j = r / m;
      
      if (i > halfM)
	i -= m;
      
      if (j > halfM)
	j -= m;
      
      dist[r] = hypot(steps[0] * i, steps[1] * j);
    }

    //Computations of the covariances
    rho = (double *)R_alloc(mbar, sizeof(double));
    irho = (double *)R_alloc(mbar, sizeof(double));
    for (i=mbar;i--;)
      irho[i] = 0;

    switch (*covmod){
    case 1:
      whittleMatern(dist, mbar, zero, sill, *range, *smooth, rho);
      break;
    case 2:
      cauchy(dist, mbar, zero, sill, *range, *smooth, rho);
      break;
    case 3:
      powerExp(dist, mbar, zero, sill, *range, *smooth, rho);
      break;
    case 4:
      bessel(dist, mbar, *dim, zero, sill, *range, *smooth, rho);
      break;
    }

    /* Compute the eigen values to check if the circulant embbeding
       matrix is positive definite */

    /* Note : The next lines is only valid for 2d random fields. I
       need to change if there are m_1 \neq m_2 as I suppose that m_1
       = m_2 = m */
    int maxf, maxp, *iwork;
    double *work;

    fft_factor(m, &maxf, &maxp);
    work = (double *)R_alloc(4 * maxf, sizeof(double));
    iwork = (int *)R_alloc(maxp, sizeof(int));
    fft_work(rho, irho, m, m, 1, -1, work, iwork);

    fft_factor(m, &maxf, &maxp);
    work = (double *)R_alloc(4 * maxf, sizeof(double));
    iwork = (int *)R_alloc(maxp, sizeof(int));
    fft_work(rho, irho, 1, m, m, -1, work, iwork);

    //Check if the eigenvalues are all positive
    for (i=mbar;i--;){
      notPosDef |= (rho[i] <= 0) || (fabs(irho[i]) > 0.001);
    }

    if (notPosDef){
      k++;
      m = HCN[k];
      halfM = m / 2;
      mbar = m * m;
    }

    if (k > 30)
      error("Impossible to embbed the covariance matrix");
    
  } while (notPosDef);
  /* --------- end of the embedding stage --------- */

  /* Computation of the square root of the eigenvalues */
  for (i=mbar;i--;){
    rho[i] = sqrt(rho[i]);
    irho[i] = 0;//No imaginary part
  }

  int mdag = m / 2 + 1, mdagbar = mdag * mdag;
  double isqrtMbar = 1 / sqrt(mbar);

  double *a = malloc(mbar * sizeof(double)),
    *ia = malloc(mbar * sizeof(double)),
    *gp = malloc(nbar * sizeof(double));

  GetRNGstate();
  for (int i=*nObs;i--;){
    int nKO = nbar;
    double poisson = 0;

    while (nKO){
      poisson += exp_rand();
      double ipoisson = 1 / poisson,
	thresh = *uBound * ipoisson;
      
      /* We simulate one realisation of a gaussian random field with
	 the required covariance function */
      circcore(rho, a, ia, m, halfM, mdag, mdagbar, *ngrid, nbar, isqrtMbar, *nugget, gp);
      
      nKO = nbar;
      for (int j=nbar;j--;){
	double dummy = R_pow(fmax2(gp[j], 0), *DoF) * ipoisson;
	ans[j + i * nbar] = fmax2(dummy, ans[j + i * nbar]);
	nKO -= (thresh <= ans[j + i * nbar]);
      }
    }
  }
  
  PutRNGstate();
  
  //Lastly we multiply by the normalizing constant
  const double imean = M_SQRT_PI * R_pow(2, -0.5 * (*DoF - 2)) /
    gammafn(0.5 * (*DoF + 1));
  for (i=(nbar * *nObs);i--;)
    ans[i] *= imean;
  
  free(a); free(ia); free(gp);
  return;
}
Пример #20
0
SEXP GillespieDirectCR(SEXP pre, SEXP post, SEXP h, SEXP M, SEXP T, SEXP delta,
		       SEXP runs, SEXP place, SEXP transition, SEXP rho)
{
  int k;

#ifdef RB_TIME
  clock_t c0, c1;
  c0 = clock();
#endif

  // Get dimensions of pre
  int *piTmp = INTEGER(getAttrib(pre, R_DimSymbol));
  int iTransitions = piTmp[0], iPlaces = piTmp[1];

  int *piPre = INTEGER(pre), *piPost = INTEGER(post);

  SEXP sexpTmp;

  int iTransition, iPlace, iTransitionPtr, iPlacePtr,
    iTransition2, iTransitionPtr2;

  // Find out which elements of h are doubles and which functions
  SEXP sexpFunction;
  PROTECT(sexpFunction = allocVector(VECSXP, iTransitions));
  double *pdH = (double *) R_alloc(iTransitions, sizeof(double));
  DL_FUNC *pCFunction = (DL_FUNC *) R_alloc(iTransitions, sizeof(DL_FUNC *));
  int *piHzType = (int *) R_alloc(iTransitions, sizeof(int));
  for (iTransition = 0; iTransition < iTransitions; iTransition++) {
    if (inherits(sexpTmp = VECTOR_ELT(h, iTransition), "NativeSymbol")) {
      pCFunction[iTransition] = (void *) R_ExternalPtrAddr(sexpTmp);
      piHzType[iTransition] = HZ_CFUNCTION;    
    } else if (isNumeric(sexpTmp)){
      pdH[iTransition] = REAL(sexpTmp)[0];
      piHzType[iTransition] = HZ_DOUBLE;
    } else  if (isFunction(sexpTmp)) {
      SET_VECTOR_ELT(sexpFunction, iTransition, lang1(sexpTmp));
      piHzType[iTransition] = HZ_RFUNCTION;
    } else {
      error("Unrecongnized transition function type\n");
    }
  }

  // Setup Matrix S
  int *piS = (int *) R_alloc(iTransitions * iPlaces, sizeof(int));

  // Position of non zero cells in pre per transition
  int *piPreNZxRow = (int *) R_alloc(iTransitions * iPlaces, sizeof(int));

  // Totals of non zero cells in pre per transition
  int *piPreNZxRowTot = (int *) R_alloc(iTransitions, sizeof(int));

  // Position of non zero cells in S per transition
  int *piSNZxRow = (int *) R_alloc(iTransitions * iPlaces, sizeof(int));

  // Totals of non zero cells in S per transition
  int *piSNZxRowTot = (int *) R_alloc(iTransitions, sizeof(int));

  for (iTransition = 0; iTransition < iTransitions; iTransition++) {
    int iPreNZxRow_col = 0;
    int iSNZxRow_col = 0;
    for (iPlace = 0; iPlace < iPlaces; iPlace++) {
      if (piPre[iTransition + iTransitions * iPlace]) {
	piPreNZxRow[iTransition + iTransitions * iPreNZxRow_col++] = iPlace;
      }
      if ((piS[iTransition + iTransitions * iPlace] = 
	   piPost[iTransition + iTransitions * iPlace] - piPre[iTransition + iTransitions * iPlace])) {
	piSNZxRow[iTransition + iTransitions * iSNZxRow_col++] = iPlace;
      }
    }
    piPreNZxRowTot[iTransition] = iPreNZxRow_col;
    piSNZxRowTot[iTransition] = iSNZxRow_col;
  }

  // Position of non zero cells in pre per place
  int *piPreNZxCol = (int *) R_alloc(iTransitions * iPlaces, sizeof(int));

  // Totals of non zero cells in pre per place
  int *piPreNZxColTot = (int *) R_alloc(iPlaces, sizeof(int));

  for (iPlace = 0; iPlace < iPlaces; iPlace++) {
    int iPreNZxCol_row = 0;
    for (iTransition = 0; iTransition < iTransitions; iTransition++) {
      if (piPre[iTransition + iTransitions * iPlace]) {
	piPreNZxCol[iPreNZxCol_row++ + iTransitions * iPlace] = iTransition;
      }
    }
    piPreNZxColTot[iPlace] = iPreNZxCol_row;
  }

  // Hazards that need to be recalculated if a given transition has happened
  int *piHazardsToModxRow = (int *) R_alloc((iTransitions + 1) * iTransitions, sizeof(int));

  // Totals of hazards to recalculate for each transition that has happened
  int *piHazardsToModxRowTot = (int *) R_alloc(iTransitions + 1, sizeof(int));
  
  for(iTransition = 0; iTransition < iTransitions; iTransition++) {
    int iHazardToCompTot = 0;
    for(iPlace = 0; iPlace < iPlaces; iPlace++) {
      if (piS[iTransition + iTransitions * iPlace]) {
	// Identify the transitions that need the hazards recalculated
	for(iTransitionPtr2 = 0; iTransitionPtr2 < piPreNZxColTot[iPlace]; iTransitionPtr2++) {
	  iTransition2 = piPreNZxCol[iTransitionPtr2 + iTransitions * iPlace];
	  int iAddThis = TRUE;
	  for (k = 0; k < iHazardToCompTot; k++) {
	    if(piHazardsToModxRow[iTransition + (iTransitions + 1) * k] == iTransition2) {
	      iAddThis = FALSE;
	      break;
	    }
	  }	    
	  if (iAddThis)
	    piHazardsToModxRow[iTransition + (iTransitions + 1) * iHazardToCompTot++] = iTransition2;
	}
      }
    }
    piHazardsToModxRowTot[iTransition] = iHazardToCompTot;
  }
  // For the initial calculation of all hazards...
  for(iTransition = 0; iTransition < iTransitions; iTransition++) {
    piHazardsToModxRow[iTransitions + (iTransitions + 1) * iTransition] = iTransition;
  }
  piHazardsToModxRowTot[iTransitions] = iTransitions;

  SEXP sexpCrntMarking;
  PROTECT(sexpCrntMarking = allocVector(REALSXP, iPlaces));
  double *pdCrntMarking = REAL(sexpCrntMarking);

  double dDelta = *REAL(delta);
  int iTotalSteps, iSectionSteps;
  double dT = 0;
  void *pCManage_time = 0;
  SEXP sexpRManage_time = 0;
  if (inherits(T, "NativeSymbol")) {
    pCManage_time = (void *) R_ExternalPtrAddr(T);
    dT = ((double(*)(double, double *)) pCManage_time)(-1, pdCrntMarking);
  } else if (isNumeric(T)){
    dT = *REAL(T);
  } else  if (isFunction(T)) {
    PROTECT(sexpRManage_time = lang1(T));

    defineVar(install("y"), sexpCrntMarking, rho);
    PROTECT(sexpTmp = allocVector(REALSXP, 1));
    *REAL(sexpTmp) = -1;
    defineVar(install("StartTime"), sexpTmp, rho);
    UNPROTECT_PTR(sexpTmp);
    dT = *REAL(VECTOR_ELT(eval(sexpRManage_time, rho),0));
  } else {
    error("Unrecognized time function type\n");
  }
  
  iTotalSteps = iSectionSteps = (int)(dT / dDelta) + 1;

  int iRun, iRuns = *INTEGER(runs);

  // Hazard vector
  double *pdTransitionHazard = (double *) R_alloc(iTransitions, sizeof(double));

  SEXP sexpRun;
  PROTECT(sexpRun = allocVector(VECSXP, iRuns));

  int iTotalUsedRandomNumbers = 0;

  // DiscTime Vector
  SEXP sexpD_time;
  PROTECT(sexpD_time = allocVector(REALSXP, iTotalSteps));
  double *pdDiscTime = REAL(sexpD_time);
  double dTmp = 0;
  for (k = 0; k < iTotalSteps; k++) {
    pdDiscTime[k] = dTmp;
    dTmp += dDelta;
  }

  SEXP sexpMarkingRowNames;
  PROTECT(sexpMarkingRowNames = allocVector(INTSXP, iTotalSteps));
  piTmp = INTEGER(sexpMarkingRowNames);
  for (k = 0; k < iTotalSteps; k++)
    piTmp[k] = k+1;

  double **ppdMarking = (double **) R_alloc(iPlaces, sizeof(double *));

  int iLevels = 7;
  int iGroups = pow(2, iLevels - 1);
  // Group holding the transitions that lie between boundaries
  int **ppiGroup = (int **) R_alloc(iGroups, sizeof(int *));
  // Number of transition each group has
  int *piGroupElm = (int *) R_alloc(iGroups, sizeof(int));
  // Total propensity hazard for each group
  int *piTotGroupTransitions = (int *) R_alloc(iGroups, sizeof(int));

  int *piTransitionInGroup = (int *) R_alloc(iTransitions, sizeof(int));
  int *piTransitionPositionInGroup = (int *) R_alloc(iTransitions, sizeof(int));

  int iGroup;
  for (iGroup = 0; iGroup < iGroups; iGroup++) {
    ppiGroup[iGroup] = (int *) R_alloc(iTransitions, sizeof(int));
  }

  node **ppnodeLevel = (node **) R_alloc(iLevels, sizeof(node *));
  int iLevel, iNode;
  int iNodesPerLevel = 1;
  for (iLevel = 0; iLevel < iLevels; iLevel++) {
    ppnodeLevel[iLevel] = (node *) R_alloc(iNodesPerLevel, sizeof(node));
    iNodesPerLevel *= 2;
  }
  node *pnodeRoot = &ppnodeLevel[0][0];
  pnodeRoot->parent = 0;
  node *pnodeGroup = ppnodeLevel[iLevels-1];

  iNodesPerLevel = 1;
  for (iLevel = 0; iLevel < iLevels; iLevel++) {
    for (iNode = 0; iNode < iNodesPerLevel; iNode++) {
      if (iLevel < iLevels-1) {
	ppnodeLevel[iLevel][iNode].iGroup = -1;
	ppnodeLevel[iLevel][iNode].left = &ppnodeLevel[iLevel+1][iNode*2];
	ppnodeLevel[iLevel][iNode].right = &ppnodeLevel[iLevel+1][iNode*2+1];
	ppnodeLevel[iLevel+1][iNode*2].parent = ppnodeLevel[iLevel+1][iNode*2+1].parent =
	  &ppnodeLevel[iLevel][iNode];
      } else {
	ppnodeLevel[iLevel][iNode].iGroup = iNode;
	ppnodeLevel[iLevel][iNode].left = ppnodeLevel[iLevel][iNode].right = 0;
      }
    }
    iNodesPerLevel *= 2;
  }

  double dNewHazard = 0;
  // Find minimum propensity
  double dMinHazard = DBL_MAX;
  for(iTransition = 0; iTransition < iTransitions; iTransition++) {
    switch(piHzType[iTransition]) {
    case HZ_DOUBLE:
      dNewHazard = pdH[iTransition];
      for(iPlacePtr = 0; iPlacePtr < piPreNZxRowTot[iTransition]; iPlacePtr++) {
	iPlace = piPreNZxRow[iTransition + iTransitions * iPlacePtr];
	for (k = 0; k < piPre[iTransition + iTransitions * iPlace]; k++)
	  dNewHazard *= (piPre[iTransition + iTransitions * iPlace] - k) / (double)(k+1);
      }
      if (dNewHazard > 0 && dNewHazard < dMinHazard)
	dMinHazard = dNewHazard;
      break;
    case HZ_CFUNCTION:	
      break;
    case HZ_RFUNCTION:
      break;
    }
  }

  GetRNGstate();
  for (iRun = 0; iRun < iRuns; iRun++) {

    int iUsedRandomNumbers = 0;
    Rprintf("%d ", iRun+1);

    // Totals for kind of transition vector
    SEXP sexpTotXTransition;
    PROTECT(sexpTotXTransition = allocVector(INTSXP, iTransitions));
    int *piTotTransitions = INTEGER(sexpTotXTransition);
  
    for(iTransition = 0; iTransition < iTransitions; iTransition++) {
      piTotTransitions[iTransition] = 0;
    }
  
    SEXP sexpMarking;
    PROTECT(sexpMarking = allocVector(VECSXP, iPlaces));
    //setAttrib(sexpMarking, R_NamesSymbol, place);
    //setAttrib(sexpMarking, R_RowNamesSymbol, sexpMarkingRowNames);
    //setAttrib(sexpMarking, R_ClassSymbol, ScalarString(mkChar("data.frame")));

    // Setup initial state
    double *pdTmp = REAL(M);
    for (iPlace = 0; iPlace < iPlaces; iPlace++) {
      SET_VECTOR_ELT(sexpMarking, iPlace, sexpTmp = allocVector(REALSXP, iTotalSteps));
      ppdMarking[iPlace] = REAL(sexpTmp);

      pdCrntMarking[iPlace] = pdTmp[iPlace];
    }
    
    for(iTransition = 0; iTransition < iTransitions; iTransition++) {
      pdTransitionHazard[iTransition] = 0;
      
      piTransitionInGroup[iTransition] = -1;
    }
    for (iGroup = 0; iGroup < iGroups; iGroup++) {
      piGroupElm[iGroup] = 0;
      piTotGroupTransitions[iGroup] = 0;
    }
    
    iNodesPerLevel = 1;
    for (iLevel = 0; iLevel < iLevels; iLevel++) {
      for (iNode = 0; iNode < iNodesPerLevel; iNode++) {
	ppnodeLevel[iLevel][iNode].dPartialAcumHazard = 0;
      }
      iNodesPerLevel *= 2;
    }
    node *pnode;
    
    double dTime = 0, dTarget = 0;
    int iTotTransitions = 0;

    int iStep = 0;
    int iInterruptCnt = 10000000;
    do {
      if (pCManage_time || sexpRManage_time) {
	double dEnd = 0;
	if (pCManage_time) {
	  dEnd = ((double(*)(double, double *)) pCManage_time)(dTarget, pdCrntMarking);
	} else {
	  defineVar(install("y"), sexpCrntMarking, rho);
	  PROTECT(sexpTmp = allocVector(REALSXP, 1));
	  *REAL(sexpTmp) = dTarget;
	  defineVar(install("StartTime"), sexpTmp, rho);
	  UNPROTECT_PTR(sexpTmp);

	  sexpTmp = eval(sexpRManage_time, rho);
	  dEnd = *REAL(VECTOR_ELT(sexpTmp,0));
	  for(iPlace = 0; iPlace < iPlaces; iPlace++) {
	    pdCrntMarking[iPlace] = REAL(VECTOR_ELT(sexpTmp,1))[iPlace];
	  }
	}
	iSectionSteps = (int)(dEnd / dDelta) + 1;
      }

      for(iPlace = 0; iPlace < iPlaces; iPlace++) {
	ppdMarking[iPlace][iStep] = pdCrntMarking[iPlace];
      }

      dTime = dTarget;
      dTarget += dDelta;
      
      // For the calculation of all hazards...
      int iLastTransition = iTransitions;
      
      do {
	// Get hazards only for the transitions associated with
	// places whose quantities changed in the last step.
	for(iTransitionPtr = 0; iTransitionPtr < piHazardsToModxRowTot[iLastTransition]; iTransitionPtr++) {
	  iTransition = piHazardsToModxRow[iLastTransition + (iTransitions + 1) * iTransitionPtr];
	  switch(piHzType[iTransition]) {
	  case HZ_DOUBLE:
	    dNewHazard = pdH[iTransition];
	    for(iPlacePtr = 0; iPlacePtr < piPreNZxRowTot[iTransition]; iPlacePtr++) {
	      iPlace = piPreNZxRow[iTransition + iTransitions * iPlacePtr];
	      for (k = 0; k < piPre[iTransition + iTransitions * iPlace]; k++)
		dNewHazard *= (pdCrntMarking[iPlace] - k) / (double)(k+1);
	    }
	    break;
	  case HZ_CFUNCTION:
	    dNewHazard = ((double(*)(double, double *)) pCFunction[iTransition])(dTime, pdCrntMarking);
	    break;
	  case HZ_RFUNCTION:
	    defineVar(install("y"), sexpCrntMarking, rho);
	    dNewHazard = REAL(eval(VECTOR_ELT(sexpFunction, iTransition), rho))[0];
	    break;
	  }

	  double dDeltaHazard;
	  frexp(dNewHazard/dMinHazard, &iGroup);
	  if (iGroup-- > 0) {
	    // Transition belongs to a group
	    if (iGroup == piTransitionInGroup[iTransition]) {
	      // Transitions will stay in same group as it was
	      dDeltaHazard = dNewHazard - pdTransitionHazard[iTransition];
	      pnode = &pnodeGroup[iGroup];
	      do {
		pnode->dPartialAcumHazard += dDeltaHazard;
	      } while ((pnode = pnode->parent));
	    } else if (piTransitionInGroup[iTransition] != -1) {
	      // Transition was in another group and needs to be moved to the new one
	      int iOldGroup = piTransitionInGroup[iTransition];
	      int iOldPositionInGroup = piTransitionPositionInGroup[iTransition];
	      dDeltaHazard = -pdTransitionHazard[iTransition];
	      pnode = &pnodeGroup[iOldGroup];
	      do {
		pnode->dPartialAcumHazard += dDeltaHazard;
	      } while ((pnode = pnode->parent));
	      piGroupElm[iOldGroup]--; // Old group will have one less element
	      // Now, piGroupElm[iOldGroup] is the index to last transition in group
	      if (iOldPositionInGroup != piGroupElm[iOldGroup]) {
		// Transition is not the last in group,
		// put the last transition in place of the one to be removed
		ppiGroup[iOldGroup][iOldPositionInGroup] = 
		  ppiGroup[iOldGroup][piGroupElm[iOldGroup]];
		// Update position of previous last transition in group
		piTransitionPositionInGroup[ppiGroup[iOldGroup][iOldPositionInGroup]] = 
		  iOldPositionInGroup;
	      }
	      dDeltaHazard = dNewHazard;
	      pnode = &pnodeGroup[iGroup];
	      do {
		pnode->dPartialAcumHazard += dDeltaHazard;
	      } while ((pnode = pnode->parent));
	      piTransitionInGroup[iTransition] = iGroup;
	      piTransitionPositionInGroup[iTransition] = piGroupElm[iGroup];
	      ppiGroup[iGroup][piGroupElm[iGroup]++] = iTransition;
	    } else if (piTransitionInGroup[iTransition] == -1) { // Transition was in no group
	      dDeltaHazard = dNewHazard;
	      pnode = &pnodeGroup[iGroup];
	      do {
		pnode->dPartialAcumHazard += dDeltaHazard;
	      } while ((pnode = pnode->parent));
	      piTransitionInGroup[iTransition] = iGroup;
	      piTransitionPositionInGroup[iTransition] = piGroupElm[iGroup];
	      ppiGroup[iGroup][piGroupElm[iGroup]++] = iTransition;
	    } else {
	    error("ERROR: Option not considered 1\n");
	    }
	  } else if (piTransitionInGroup[iTransition] != -1) {
	    // Transition will not belong to any group and needs to be removed from old
	    int iOldGroup = piTransitionInGroup[iTransition];
	    int iOldPositionInGroup = piTransitionPositionInGroup[iTransition];
	    dDeltaHazard = -pdTransitionHazard[iTransition];
	    pnode = &pnodeGroup[iOldGroup];
	    do {
	      pnode->dPartialAcumHazard += dDeltaHazard;
	    } while ((pnode = pnode->parent));
	    piGroupElm[iOldGroup]--; // Old group will have one less element
	    // Now, piGroupElm[iOldGroup] is the index to last transition in group
	    if (iOldPositionInGroup != piGroupElm[iOldGroup]) {
	      // Transition is not the last in group,
	      // put the last transition in place of the one to be removed
	      ppiGroup[iOldGroup][iOldPositionInGroup] = 
		ppiGroup[iOldGroup][piGroupElm[iOldGroup]];
	      // Update position of previous last transition in group
	      piTransitionPositionInGroup[ppiGroup[iOldGroup][iOldPositionInGroup]] = 
		iOldPositionInGroup;
	    }
	    piTransitionInGroup[iTransition] = -1;
	  }
	  pdTransitionHazard[iTransition] = dNewHazard;
	}
	
	// Get Time to transition
	dTime += exp_rand() / pnodeRoot->dPartialAcumHazard;
	iUsedRandomNumbers++;
	
	while (dTime >= dTarget) {
	  ++iStep;
	  // Update the state for the fixed incremented time.
	  for(iPlace = 0; iPlace < iPlaces; iPlace++)
	    ppdMarking[iPlace][iStep] = pdCrntMarking[iPlace];
	  if (iStep == iSectionSteps - 1)
	    goto EXIT_LOOP;

	  dTarget += dDelta;

	  // Force check if user interrupted
	  iInterruptCnt = 1;
	}
	if (! --iInterruptCnt) {
	  // Allow user interruption
	  R_CheckUserInterrupt();
	  iInterruptCnt = 10000000;
	}
	do {
	  // Find group containing firing transition
	  double dRnd = unif_rand() * pnodeRoot->dPartialAcumHazard;
	  iUsedRandomNumbers++;
	  pnode = pnodeRoot;
	  do {
	    if (dRnd < pnode->left->dPartialAcumHazard) {
	      pnode = pnode->left;
	    } else {
	      dRnd -= pnode->left->dPartialAcumHazard;
	      pnode = pnode->right;
	    }	      
	  } while (pnode->left);
	  // Next check is because
	  // once in a while it is generated a number that goes past
	  // the last group or selects a group with zero elements
	  // due to accumulated truncation errors.
	  // Discard this random number and try again.
	} while (piGroupElm[iGroup = pnode->iGroup] == 0);

	double dMaxInGroup = dMinHazard * pow(2, iGroup + 1);
	// Find transition in group
	while (1) {
	  if (! --iInterruptCnt) {
	    // Allow user interruption
	    R_CheckUserInterrupt();
	    iInterruptCnt = 10000000;
	  }
	  iTransitionPtr = (int) (unif_rand() * piGroupElm[iGroup]);
	  iUsedRandomNumbers++;
	  iTransition = ppiGroup[iGroup][iTransitionPtr];
	  iUsedRandomNumbers++;
	  if (pdTransitionHazard[iTransition] > unif_rand() * dMaxInGroup) {
	    piTotTransitions[iLastTransition = iTransition]++;
	    for(iPlacePtr = 0; iPlacePtr < piSNZxRowTot[iTransition]; iPlacePtr++) {
	      iPlace = piSNZxRow[iTransition + iTransitions * iPlacePtr];
	      
	      // Update the state
	      pdCrntMarking[iPlace] += piS[iTransition + iTransitions * iPlace];
	    }
	    break;
	  }
	}
	++iTotTransitions;
      } while (TRUE);
    EXIT_LOOP:;
      Rprintf(".");
    } while (iSectionSteps < iTotalSteps);
    iTotalUsedRandomNumbers += iUsedRandomNumbers;
    Rprintf("\t%d\t%d\t%d", iTotTransitions, iUsedRandomNumbers, iTotalUsedRandomNumbers);
#ifdef RB_SUBTIME
    c1 = clock();
    Rprintf ("\t To go: ");
    PrintfTime((double) (c1 - c0)/CLOCKS_PER_SEC/(iRun+1)*(iRuns-iRun-1));
#endif
    Rprintf ("\n");
    
    SEXP sexpTotTransitions;
    PROTECT(sexpTotTransitions = allocVector(INTSXP, 1));
    INTEGER(sexpTotTransitions)[0] = iTotTransitions;

    SEXP sexpThisRun;
    PROTECT(sexpThisRun = allocVector(VECSXP, 3));

    SET_VECTOR_ELT(sexpThisRun, 0, sexpMarking);
    UNPROTECT_PTR(sexpMarking);
    SET_VECTOR_ELT(sexpThisRun, 1, sexpTotXTransition);
    UNPROTECT_PTR(sexpTotXTransition);
    SET_VECTOR_ELT(sexpThisRun, 2, sexpTotTransitions);
    UNPROTECT_PTR(sexpTotTransitions);

    SEXP sexpNames;
    PROTECT(sexpNames = allocVector(VECSXP, 3));
    SET_VECTOR_ELT(sexpNames, 0, mkChar("M"));
    SET_VECTOR_ELT(sexpNames, 1, mkChar("transitions"));
    SET_VECTOR_ELT(sexpNames, 2, mkChar("tot.transitions"));
    setAttrib(sexpThisRun, R_NamesSymbol, sexpNames);
    UNPROTECT_PTR(sexpNames);

    SET_VECTOR_ELT(sexpRun, iRun, sexpThisRun);
    UNPROTECT_PTR(sexpThisRun);
  }
  PutRNGstate();

  SEXP sexpAns;
  PROTECT(sexpAns = allocVector(VECSXP, 4));
  SET_VECTOR_ELT(sexpAns, 0, place);
  SET_VECTOR_ELT(sexpAns, 1, transition);
  SET_VECTOR_ELT(sexpAns, 2, sexpD_time);
  UNPROTECT_PTR(sexpD_time);
  SET_VECTOR_ELT(sexpAns, 3, sexpRun);
  UNPROTECT_PTR(sexpRun);

  SEXP sexpNames;
  PROTECT(sexpNames = allocVector(VECSXP, 4));
  SET_VECTOR_ELT(sexpNames, 0, mkChar("place"));
  SET_VECTOR_ELT(sexpNames, 1, mkChar("transition"));
  SET_VECTOR_ELT(sexpNames, 2, mkChar("dt"));
  SET_VECTOR_ELT(sexpNames, 3, mkChar("run"));
  setAttrib(sexpAns, R_NamesSymbol, sexpNames);
  UNPROTECT_PTR(sexpNames);

#ifdef RB_TIME
  c1 = clock();
  double dCpuTime = (double) (c1 - c0)/CLOCKS_PER_SEC;
  Rprintf ("Elapsed CPU time: ");
  PrintfTime(dCpuTime);
  Rprintf ("\t(%fs)\n", dCpuTime);
#endif

  if (sexpRManage_time)
    UNPROTECT_PTR(sexpRManage_time);
  UNPROTECT_PTR(sexpFunction);
  UNPROTECT_PTR(sexpMarkingRowNames);
  UNPROTECT_PTR(sexpCrntMarking);
  UNPROTECT_PTR(sexpAns);
  return(sexpAns);
}
Пример #21
0
void rgeomdirect(double *coord, int *nObs, int *nSite, int *dim,
		 int *covmod, int *grid, double *sigma2, double *nugget,
		 double *range, double *smooth, double *uBound,
		 double *ans){
  /* This function generates random fields for the geometric model

     coord: the coordinates of the locations
      nObs: the number of observations to be generated
    nSite: the number of locations
       dim: the random field is generated in R^dim
    covmod: the covariance model
      grid: Does coord specifies a grid?
    sigma2: the variance of the geometric gaussian process
      nugget: the nugget parameter
     range: the range parameter
    smooth: the smooth parameter
       ans: the generated random field */

  int i, j, neffSite, lagi = 1, lagj = 1, oneInt = 1;
  const double loguBound = log(*uBound), halfSigma2 = 0.5 * *sigma2;
  double sigma = sqrt(*sigma2), sill = 1 - *nugget;

  if (*grid){
    neffSite = R_pow_di(*nSite, *dim);
    lagi = neffSite;
  }

  else{
    neffSite = *nSite;
    lagj = *nObs;
  }

  double *covmat = malloc(neffSite * neffSite * sizeof(double)),
    *gp = malloc(neffSite * sizeof(double));

  buildcovmat(nSite, grid, covmod, coord, dim, nugget, &sill, range,
	      smooth, covmat);
  
  /* Compute the Cholesky decomposition of the covariance matrix */
  int info = 0;
  F77_CALL(dpotrf)("U", &neffSite, covmat, &neffSite, &info);

  if (info != 0)
    error("error code %d from Lapack routine '%s'", info, "dpotrf");

  GetRNGstate();
  
  for (i=*nObs;i--;){
    double poisson = 0;
    int nKO = neffSite;
    
    while (nKO) {
      /* The stopping rule is reached when nKO = 0 i.e. when each site
	 satisfies the condition in Eq. (8) of Schlather (2002) */
      poisson += exp_rand();
      double ipoisson = -log(poisson), thresh = loguBound + ipoisson;
	
      /* We simulate one realisation of a gaussian random field with
	 the required covariance function */
      for (j=neffSite;j--;)
	gp[j] = norm_rand();
      
      F77_CALL(dtrmv)("U", "T", "N", &neffSite, covmat, &neffSite, gp, &oneInt);
      
      nKO = neffSite;
      double ipoissonMinusHalfSigma2 = ipoisson - halfSigma2;
      for (j=neffSite;j--;){
	ans[j * lagj + i * lagi] = fmax2(sigma * gp[j] + ipoissonMinusHalfSigma2,
				      ans[j * lagj + i * lagi]);
	
	nKO -= (thresh <= ans[j * lagj + i * lagi]);
	  
      }
    }
  }
  
  PutRNGstate();

  /* So fare we generate a max-stable process with standard Gumbel
     margins. Switch to unit Frechet ones */
  for (i=*nObs * neffSite;i--;)
    ans[i] = exp(ans[i]);

  free(covmat); free(gp);

  return;
}
Пример #22
0
void stateDRR::initSimulation(float M)
{
    std::queue<events *> eq;
    r = M/(NUM_SOURCES - 1);
    //SEED VALUE variation
    srand48(SEED);

    this->clock = 0;

    this->totalArrival = 0;
    this->currentPackets = 0;
    this->packetid.reserve(NUM_SOURCES);
    this->lastArrival.reserve(NUM_SOURCES);
    this->sourceStats.reserve(NUM_SOURCES);
    this->deficit.reserve(NUM_SOURCES);

    this->flows.reserve(NUM_SOURCES);
    /* clear globalstats */
    this->globalStats.totalPackets = 0;
    this->globalStats.totalSize = 0;
    this->globalStats.lastDeparture = 0;
    this->globalStats.totalResponse = 0;
    this->globalStats.totalWait = 0;

    for(int i=0;i<NUM_SOURCES;i++) {
        flows.push_back(queue<events *>());
        this->deficit[i] = 0;   //set to zero and later check for (deficit[i]+Q)
        this->packetid[i]=1;
        this->lastArrival[i] = 0;

        this->sourceStats[i].M = M;
        this->sourceStats[i].totalPackets = 1;
        this->sourceStats[i].totalResponse = 0;
        this->sourceStats[i].totalWait = 0;
        this->sourceStats[i].responseSqr = 0;
        this->sourceStats[i].waitSqr = 0;
        this->sourceStats[i].totalSize = 0;
        this->sourceStats[i].lastDeparture = 0;

        events *newEvent = new events(PKT_ARRIVE, i, this->packetid[i], 0, 0);
        switch(i) {
            case TELNET1:
            case TELNET2:
            case TELNET3:
            case TELNET4:
                newEvent->packetSize = exp_rand(L_TELNET);
                break;
            case FTP1:
            case FTP2:
            case FTP3:
            case FTP4:
            case FTP5:
            case FTP6:
                newEvent->packetSize = exp_rand(L_FTP);
                break;
            case ROGUE:
                newEvent->packetSize = L_ROGUE;
                break;
        }
        newEvent->eventTime = 0;
        newEvent->arrivalTime = newEvent->eventTime;
        newEvent->departureTime = INVAL;

        /* Update stats */
        this->totalArrival++;
        
        this->eventQueue.push(newEvent);
#ifdef DEBUG
        cout<<"+("<<newEvent->type<<", "<<newEvent->sourceId<<", "<<newEvent->packetId<<", "<<newEvent->packetSize<<")";
#endif
    }

}
Пример #23
0
void rgeomcirc(int *nObs, int *ngrid, double *steps, int *dim,
	       int *covmod, double *sigma2, double *nugget, double *range,
	       double *smooth, double *uBound, double *ans){
  /* This function generates random fields from the geometric model

     nObs: the number of observations to be generated
    ngrid: the number of locations along one axis
      dim: the random field is generated in R^dim
   covmod: the covariance model
     nugget: the nugget parameter
    range: the range parameter
   smooth: the smooth parameter
   uBound: the uniform upper bound for the stoch. proc.
      ans: the generated random field */

  int i, j, k = -1, nbar = R_pow_di(*ngrid, *dim), r, m;
  const double loguBound = log(*uBound), halfSigma2 = 0.5 * *sigma2,
    zero = 0;
  double sigma = sqrt(*sigma2), sill = 1 - *nugget, *rho, *irho, *dist;

  //Below is a table of highly composite numbers
  int HCN[39] = {1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240,
		 360, 720, 840, 1260, 1680, 2520, 5040, 7560,
		 10080, 15120, 20160, 25200, 27720, 45360, 50400,
		 55440, 83160, 110880, 166320, 221760, 277200,
		 332640, 498960, 554400, 665280, 720720, 1081080};

    
  /* Find the smallest size m for the circulant embedding matrix */
  {
    int dummy = 2 * (*ngrid - 1);
    do {
      k++;
      m = HCN[k];
    } while (m < dummy);
  }
  
  /* ---------- beginning of the embedding stage ---------- */
  int mbar = m * m, halfM = m / 2, notPosDef = 0;
  do {
    dist = (double *)R_alloc(mbar, sizeof(double));

    notPosDef = 0;
    //Computation of the distance
    for (r=mbar;r--;){
      i = r % m;
      j = r / m;
      
      if (i > halfM)
	i -= m;
      
      if (j > halfM)
	j -= m;
      
      dist[r] = hypot(steps[0] * i, steps[1] * j);
    }

    //Computations of the covariances
    rho = (double *)R_alloc(mbar, sizeof(double));
    irho = (double *)R_alloc(mbar, sizeof(double));
    for (i=mbar;i--;)
      irho[i] = 0;

    switch (*covmod){
    case 1:
      whittleMatern(dist, mbar, zero, sill, *range, *smooth, rho);
      break;
    case 2:
      cauchy(dist, mbar, zero, sill, *range, *smooth, rho);
      break;
    case 3:
      powerExp(dist, mbar, zero, sill, *range, *smooth, rho);
      break;
    case 4:
      bessel(dist, mbar, *dim, zero, sill, *range, *smooth, rho);
      break;
    }

    /* Compute the eigen values to check if the circulant embbeding
       matrix is positive definite */

    /* Note : The next lines is only valid for 2d random fields. I
       need to change if there are m_1 \neq m_2 as I suppose that m_1
       = m_2 = m */
    int maxf, maxp;

    fft_factor(m, &maxf, &maxp);
    double *work = (double *)R_alloc(4 * maxf, sizeof(double));
    int *iwork = (int *)R_alloc(maxp, sizeof(int));
    fft_work(rho, irho, m, m, 1, -1, work, iwork);

    fft_factor(m, &maxf, &maxp);
    work = (double *)R_alloc(4 * maxf, sizeof(double));
    iwork = (int *)R_alloc(maxp, sizeof(int));
    fft_work(rho, irho, 1, m, m, -1, work, iwork);

    //Check if the eigenvalues are all positive
    for (i=mbar;i--;){
      notPosDef |= (rho[i] <= 0) || (fabs(irho[i]) > 0.001);
    }

    if (notPosDef){
      k++;
      m = HCN[k];
      halfM = m / 2;
      mbar = m * m;
    }

    if (k > 30)
      error("Impossible to embbed the covariance matrix");
    
  } while (notPosDef);
  /* --------- end of the embedding stage --------- */

  /* Computation of the square root of the eigenvalues */
  for (i=mbar;i--;){
    rho[i] = sqrt(rho[i]);
    irho[i] = 0;//No imaginary part
  }

  int mdag = m / 2 + 1, mdagbar = mdag * mdag;
  double isqrtMbar = 1 / sqrt(mbar);

  double *a = (double *)R_alloc(mbar, sizeof(double));
  double *ia = (double *)R_alloc(mbar, sizeof(double));
  
  GetRNGstate();
  for (i=*nObs;i--;){
    int nKO = nbar;
    double poisson = 0;
    
    while (nKO) {
      /* The stopping rule is reached when nKO = 0 i.e. when each site
	 satisfies the condition in Eq. (8) of Schlather (2002) */
      int j;
      double *gp = (double *)R_alloc(nbar, sizeof(double));
      
      poisson += exp_rand();
      double ipoisson = -log(poisson), thresh = loguBound + ipoisson;
      
      /* We simulate one realisation of a gaussian random field with
	 the required covariance function */
      circcore(rho, a, ia, m, halfM, mdag, mdagbar, *ngrid, nbar, isqrtMbar, *nugget, gp);
      
      nKO = nbar;
      double ipoissonMinusHalfSigma2 = ipoisson - halfSigma2;
      for (j=nbar;j--;){
	ans[j + i * nbar] = fmax2(sigma * gp[j] + ipoissonMinusHalfSigma2,
				  ans[j + i * nbar]);
	nKO -= (thresh <= ans[j + i * nbar]);
	
      }
    }
  }
  
  PutRNGstate();

  /* So fare we generate a max-stable process with standard Gumbel
     margins. Switch to unit Frechet ones */
  for (i=*nObs * nbar;i--;)
    ans[i] = exp(ans[i]);
  
  return;
}
Пример #24
0
double rgeom(double p)
{
    if (!R_FINITE(p) || p <= 0 || p > 1) ML_ERR_return_NAN;

    return rpois(exp_rand() * ((1 - p) / p));
}
Пример #25
0
double rgamma(double a, double scale, JRNG *rng)
{
/* Constants : */
    const static double sqrt32 = 5.656854;
    const static double exp_m1 = 0.36787944117144232159;/* exp(-1) = 1/e */

    /* Coefficients q[k] - for q0 = sum(q[k]*a^(-k))
     * Coefficients a[k] - for q = q0+(t*t/2)*sum(a[k]*v^k)
     * Coefficients e[k] - for exp(q)-1 = sum(e[k]*q^k)
     */
    const static double q1 = 0.04166669;
    const static double q2 = 0.02083148;
    const static double q3 = 0.00801191;
    const static double q4 = 0.00144121;
    const static double q5 = -7.388e-5;
    const static double q6 = 2.4511e-4;
    const static double q7 = 2.424e-4;

    const static double a1 = 0.3333333;
    const static double a2 = -0.250003;
    const static double a3 = 0.2000062;
    const static double a4 = -0.1662921;
    const static double a5 = 0.1423657;
    const static double a6 = -0.1367177;
    const static double a7 = 0.1233795;

    /* State variables [FIXME for threading!] :*/
    static double aa = 0.;
    static double aaa = 0.;
    static double s, s2, d;    /* no. 1 (step 1) */
    static double q0, b, si, c;/* no. 2 (step 4) */

    double e, p, q, r, t, u, v, w, x, ret_val;

    if (!R_FINITE(a) || !R_FINITE(scale) || a < 0.0 || scale <= 0.0) {
	if(scale == 0.) return 0.;
	ML_ERR_return_NAN;
    }

    if (a < 1.) { /* GS algorithm for parameters a < 1 */
	if(a == 0)
	    return 0.;
	e = 1.0 + exp_m1 * a;
	repeat {
	    p = e * unif_rand(rng);
	    if (p >= 1.0) {
		x = -log((e - p) / a);
		if (exp_rand(rng) >= (1.0 - a) * log(x))
		    break;
	    } else {
		x = exp(log(p) / a);
		if (exp_rand(rng) >= x)
		    break;
	    }
	}
	return scale * x;
    }

    /* --- a >= 1 : GD algorithm --- */

    /* Step 1: Recalculations of s2, s, d if a has changed */
    if (a != aa) {
	aa = a;
	s2 = a - 0.5;
	s = sqrt(s2);
	d = sqrt32 - s * 12.0;
    }
    /* Step 2: t = standard normal deviate,
               x = (s,1/2) -normal deviate. */

    /* immediate acceptance (i) */
    t = norm_rand(rng);
    x = s + 0.5 * t;
    ret_val = x * x;
    if (t >= 0.0)
	return scale * ret_val;

    /* Step 3: u = 0,1 - uniform sample. squeeze acceptance (s) */
    u = unif_rand(rng);
    if (d * u <= t * t * t)
	return scale * ret_val;

    /* Step 4: recalculations of q0, b, si, c if necessary */

    if (a != aaa) {
	aaa = a;
	r = 1.0 / a;
	q0 = ((((((q7 * r + q6) * r + q5) * r + q4) * r + q3) * r
	       + q2) * r + q1) * r;

	/* Approximation depending on size of parameter a */
	/* The constants in the expressions for b, si and c */
	/* were established by numerical experiments */

	if (a <= 3.686) {
	    b = 0.463 + s + 0.178 * s2;
	    si = 1.235;
	    c = 0.195 / s - 0.079 + 0.16 * s;
	} else if (a <= 13.022) {
	    b = 1.654 + 0.0076 * s2;
	    si = 1.68 / s + 0.275;
	    c = 0.062 / s + 0.024;
	} else {
	    b = 1.77;
	    si = 0.75;
	    c = 0.1515 / s;
	}
    }
    /* Step 5: no quotient test if x not positive */

    if (x > 0.0) {
	/* Step 6: calculation of v and quotient q */
	v = t / (s + s);
	if (fabs(v) <= 0.25)
	    q = q0 + 0.5 * t * t * ((((((a7 * v + a6) * v + a5) * v + a4) * v
				      + a3) * v + a2) * v + a1) * v;
	else
	    q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v);


	/* Step 7: quotient acceptance (q) */
	if (log(1.0 - u) <= q)
	    return scale * ret_val;
    }

    repeat {
	/* Step 8: e = standard exponential deviate
	 *	u =  0,1 -uniform deviate
	 *	t = (b,si)-double exponential (laplace) sample */
	e = exp_rand(rng);
	u = unif_rand(rng);
	u = u + u - 1.0;
	if (u < 0.0)
	    t = b - si * e;
	else
	    t = b + si * e;
	/* Step	 9:  rejection if t < tau(1) = -0.71874483771719 */
	if (t >= -0.71874483771719) {
	    /* Step 10:	 calculation of v and quotient q */
	    v = t / (s + s);
	    if (fabs(v) <= 0.25)
		q = q0 + 0.5 * t * t *
		    ((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v
		      + a2) * v + a1) * v;
	    else
		q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v);
	    /* Step 11:	 hat acceptance (h) */
	    /* (if q not positive go to step 8) */
	    if (q > 0.0) {
		w = expm1(q);
		/*  ^^^^^ original code had approximation with rel.err < 2e-7 */
		/* if t is rejected sample again at step 8 */
		if (c * fabs(u) <= w * exp(e - 0.5 * t * t))
		    break;
	    }
	}
    } /* repeat .. until  `t' is accepted */
    x = s + 0.5 * t;
    return scale * x * x;
}
Пример #26
0
double rgeom_mt(BOOM::RNG & rng, double p)
{
    if (ISNAN(p) || p <= 0 || p > 1) ML_ERR_return_NAN;

    return rpois_mt(rng, exp_rand(rng) * ((1 - p) / p));
}
Пример #27
0
/***** ***************************************************************************************** *****/
void
RJMCMCdeath(int* accept,              double* log_AR,
            int* K,                   double* w,                        double* logw,                double* mu,    
            double* Q,                double* Li,                       double* Sigma,               double* log_dets,  
            int* order,               int* rank,                        int* mixN,
            int* jempty,              int* err,
            const int* p,             const int* n,
            const int* Kmax,          const double* logK,               const double* log_lambda,    const int* priorK,
            const double* logPbirth,  const double* logPdeath,          const double* delta)
{
  //const char *fname = "NMix::RJMCMCdeath";

  *err = 0;
  *accept = 0;

  /*** Some variables ***/
  static int j, i1, i0, jstar, LTp;
  static int Nempty;
  static double one_wstar, log_one_wstar, erand;

  /*** Some pointers ***/
  static double *wstar, *logwstar;

  static int *mixNP, *jemptyP;
  static double *wP, *logwP, *muP, *QP, *LiP, *SigmaP, *log_detsP;
  static const double *muPnext, *QPnext, *LiPnext, *SigmaPnext;

  if (*K == 1){
    *log_AR = R_NegInf;
    return;
  }

  LTp = (*p * (*p + 1))/2;

  /***** Compute the number of empty components and store their indeces *****/
  /***** ============================================================== *****/
  Nempty  = 0;
  jemptyP = jempty;
  mixNP   = mixN;
  for (j = 0; j < *K; j++){
    if (*mixNP == 0){
      Nempty++;
      *jemptyP = j;
      jemptyP++;
    }
    mixNP++;
  }

  /***** Directly reject the death move if there are no empty components *****/
  /***** =============================================================== *****/
  if (Nempty == 0){
    *log_AR = R_NegInf;
    return;
  }

  /***** Choose at random one of empty components *****/
  /***** ======================================== *****/
  j = (int)(floor(unif_rand() * Nempty));
  if (j == Nempty) j = Nempty - 1;              // this row is needed with theoretical probability 0 (in cases when unif_rand() returns 1)
  jstar = jempty[j];

  /***** Log-acceptance ratio *****/
  /***** ==================== *****/
  wstar         = w + jstar;
  logwstar      = logw + jstar;
  one_wstar     = 1 - *wstar;
  log_one_wstar = AK_Basic::log_AK(one_wstar);

//  *log_AR = -(logPdeath[*K - 1] - logPbirth[*K - 2] - AK_Basic::log_AK((double)(Nempty)) + lbeta(1, *K - 1) - lbeta(*delta, (*K - 1) * *delta)
//	      + (*delta - 1) * *logwstar + (*n + (*K - 1) * (*delta - 1) + 1) * log_one_wstar);    // this is according to the original paper Richardson and Green (1997)
  *log_AR = -(logPdeath[*K - 1] - logPbirth[*K - 2] - AK_Basic::log_AK((double)(Nempty)) + lbeta(1, *K - 1) - lbeta(*delta, (*K - 1) * *delta)
	      + (*delta - 1) * *logwstar + (*n + (*K - 1) * (*delta - 1)) * log_one_wstar);        // this is according to Corrigendum in JRSS, B (1998), p. 661

  /***** log-ratio of priors on K (+ factor comming from the equivalent ways that the components can produce the same likelihood) *****/
  switch (*priorK){
  case NMix::K_FIXED:
  case NMix::K_UNIF:      /*** K * (p(K)/p(K-1)) = K ***/
    *log_AR -= logK[*K - 1];
    break;
  case NMix::K_TPOISS:    /*** K * (p(K)/p(K-1)) = K * (lambda/K) = lambda ***/
    *log_AR -= *log_lambda;
    break;
  }


  /***** Accept/reject *****/
  /***** ============= *****/
  if (*log_AR >= 0) *accept = 1;
  else{                           /** decide by sampling from the exponential distribution **/
    erand = exp_rand();
    *accept = (erand > -(*log_AR) ? 1 : 0);
  }


  /***** Update mixture values if proposal accepted *****/
  /***** ========================================== *****/
  if (*accept){

    /***** Adjustment of the weights and their shift, new log-weights *****/
    wP    = w;
    logwP = logw;
    j     = 0;
    while (j < jstar){
      *logwP -= log_one_wstar;
      *wP     = AK_Basic::exp_AK(*logwP);
      wP++;
      logwP++;
      j++;
    }
    while (j < *K - 1){
      *logwP = *(logwP + 1) - log_one_wstar;
      *wP    = AK_Basic::exp_AK(*logwP);
      wP++;
      logwP++;
      j++;
    }

    /***** Mixture means, inverse variances, their Cholesky decompositions, variances, log_dets -> must be shifted *****/
    /***** mixN -> must be shifted                                                                                 *****/
    mixNP     = mixN + jstar;
    muP       = mu + jstar * *p;
    QP        = Q + jstar * LTp;
    LiP       = Li + jstar * LTp;
    SigmaP    = Sigma + jstar * LTp;  
    log_detsP = log_dets + jstar * 2;

    muPnext    = muP + *p;
    QPnext     = QP + LTp;
    LiPnext    = LiP + LTp;
    SigmaPnext = SigmaP + LTp;

    for (j = jstar; j < *K - 1; j++){
      *mixNP     = *(mixNP + 1);
      mixNP++;

      *log_detsP = *(log_detsP + 2);
      log_detsP += 2;

      for (i1 = 0; i1 < *p; i1++){
        *muP = *muPnext;
        muP++;
        muPnext++;

        for (i0 = i1; i0 < *p; i0++){
          *QP = *QPnext;
          QP++;
          QPnext++;

          *LiP = *LiPnext;
          LiP++;
          LiPnext++;

          *SigmaP = *SigmaPnext;
          SigmaP++;
          SigmaPnext++;
        }
      }      
    }

    /***** order, rank *****/
    NMix::orderComp_remove(order, rank, &jstar, K);

    /***** K *****/
    *K -= 1;
  }

  return;
}