///////////////////////////////////////////////////////////
// given a point X, sample indices of all input densities
///////////////////////////////////////////////////////////
// uses Npts, trees, ind, particles, variance, Cwtg
void sampleIndices(double* X) {
  unsigned int i,j,k;
  unsigned long z;
  BallTree::index zz;

  for (j=0;j<Ndens;j++) {
    unsigned long dNp = dNpts[j]; //trees[j].Npts();
    double pT = 0;

    for (z=0, zz=levelList[j][0]; z<dNp; zz=levelList[j][++z]) {
      p[z] = 0;
      for (i=0; i<Ndim; i++) {
        double tmp = X[i] - trees[j].mean(zz)[i];
        p[z] += (tmp*tmp)/ trees[j].bw(zz)[i];
        p[z] += log(trees[j].bw(zz)[i]);
      }
      p[z] = exp( -0.5 * p[z] ) * trees[j].weight(zz);
      pT += p[z];
    }
    for (z=0; z<dNp; z++) p[z] /= pT;

    for (z=1; z<dNp; z++) p[z] += p[z-1];    // construct CDF and sample a
    for (z=0, zz=levelList[j][0]; z<dNp-1; zz=levelList[j][++z])
      if (*randU <= p[z]) break;             //  new kernel from jth density
    ind[j] = zz;                             //  using those weights
    randU++;
  }
  calcIndices();                             // recompute particles, variance
}
///////////////////////////////////////////////////////////
// uses particles, variance, ind
// uses newPoints, newIndices, trees, Ndens
void gibbs2(unsigned int _Ndens, const BallTreeDensity* _trees, 
            unsigned long Np, unsigned int Niter,
            double *_pts, BallTree::index *_ind,
            double *_randU, double* _randN)
{
  unsigned int i,j,l;
  unsigned long s, maxNp;

  Ndens = _Ndens;                       // SET UP GLOBALS
  trees = _trees;
  newPoints = _pts; newIndices = _ind;
  randU = _randU; randN = _randN;
  Ndim  = trees[0].Ndim();              // dimension of densities    
  maxNp = 0;                            // largest # of particles we deal with
  for (unsigned int j=0; j<Ndens; j++)  // compute Max Np over all densities
    if (maxNp < trees[j].Npts()) maxNp = trees[j].Npts();

  ind = new BallTree::index[Ndens];     // ALLOCATE GLOBALS
  p = new double[maxNp];
  
  Nlevels = (unsigned int) (log((double)maxNp)/log((double)2))+1;          // how many levels to a balanced binary tree?

  particles = new double[Ndim*Ndens];
  variance  = new double[Ndim*Ndens];

  dNpts = new unsigned long[Ndens];
  levelList = new BallTree::index*[Ndens];
  levelListNew = new BallTree::index*[Ndens];
  for (j=0;j<Ndens;j++) { 
    levelList[j] = new BallTree::index[maxNp];
    levelListNew[j] = new BallTree::index[maxNp];
  }

  for (s=0; s<Np; s++) {                       

    levelInit();
    initIndices();
    calcIndices();

    ///////////////////////////////////////////////////////////////
    // Perform Gibbs sampling only if multiple densities in product
    ///////////////////////////////////////////////////////////////
    samplePoint(newPoints);
    for (l=0;l<Nlevels;l++) {
      levelDown();
      for (i=0;i<Niter;i++) {
        sampleIndices(newPoints);
        samplePoint(newPoints);
    }}

    for (unsigned int j=0; j<Ndens; j++)              // save and
      newIndices[j] = trees[j].getIndexOf(ind[j])+1;  // return particle label
    newIndices += Ndens;                              // move pointers to next sample
    newPoints  += Ndim;
  }

  for (j=0;j<Ndens;j++) { delete[] levelList[j];  delete[] levelListNew[j]; }
  delete[] levelList; delete[] levelListNew;
  delete[] dNpts;

  delete[] ind; delete[] p; delete[] particles; delete[] variance;
};
 void MesherFixedEvenStem::getIndices(otTriangles& triangles, unsigned int offset)
 {
   vertexOffset += offset;
   calcIndices(&triangles);
 }