 jet 1 as real jet
        jets.push_back(*j1);
        jets[jets.size()-1].v.build_etaphi();
        // a bug where the contents has non-zero size has been cropping
        // up in many contexts -- so catch it!
        assert(j1->contents.size() > 0);
        jets[jets.size()-1].pass = particles[j1->contents[0]].index;
#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
        cand_refs.erase(j1->v.ref);
#endif
        candidates->erase(j1);

	//// test that the hardest jet pass the potential cut-off
	//if ((candidates->size()!=0) &&
	//    (candidates->begin()->sm_var2<SM_var2_hardest_cut_off)){
	//  candidates->clear();
	//}
      }
    }
  } while (candidates->size()>0);

  // sort jets by pT
  sort(jets.begin(), jets.end(), jets_pt_less);
#ifdef DEBUG_SPLIT_MERGE
      show();
#endif

  return jets.size();
}



// save the event on disk
//  - flux   stream used to save jet contents
//--------------------------------------------
int Csplit_merge::save_contents(FILE *flux){
  jet_iterator it_j;
  Cjet *j1;
  int i1, i2;

  fprintf(flux, "# %d jets found\n", (int) jets.size());
  fprintf(flux, "# columns are: eta, phi, pt and number of particles for each jet\n");
  for (it_j = jets.begin(), i1=0 ; it_j!= jets.end() ; it_j++, i1++){
    j1 = &(*it_j);
    j1->v.build_etaphi();
    fprintf(flux, "%f\t%f\t%e\t%d\n",
	    j1->v.eta, j1->v.phi, j1->v.perp(), j1->n);
  }

  fprintf(flux, "# jet contents\n");
  fprintf(flux, "# columns are: eta, phi, pt, particle index and jet number\n");
  for (it_j = jets.begin(), i1=0 ; it_j!= jets.end() ; it_j++, i1++){
    j1 = &(*it_j);
    for (i2=0;i2<j1->n;i2++)
      fprintf(flux, "%f\t%f\t%e\t%d\t%d\n",
      	      particles[j1->contents[i2]].eta, particles[j1->contents[i2]].phi,
      	      particles[j1->contents[i2]].perp(), j1->contents[i2], i1);
  }

  return 0;
}


// show current jets/candidate status
//------------------------------------
int Csplit_merge::show(){
  jet_iterator it_j;
  cjet_iterator it_c;
  Cjet *j;
  const Cjet *c;
  int i1, i2;

  for (it_j = jets.begin(), i1=0 ; it_j!= jets.end() ; it_j++, i1++){
    j = &(*it_j);
    fprintf(stdout, "jet %2d: %e\t%e\t%e\t%e\t", i1+1,
	    j->v.px, j->v.py, j->v.pz, j->v.E);
    for (i2=0;i2<j->n;i2++)
      fprintf(stdout, "%d ", j->contents[i2]);
    fprintf(stdout, "\n");
  }

  for (it_c = candidates->begin(), i1=0 ; it_c!= candidates->end() ; it_c++, i1++){
    c = &(*it_c);
    fprintf(stdout, "cdt %2d: %e\t%e\t%e\t%e\t%e\t", i1+1,
	    c->v.px, c->v.py, c->v.pz, c->v.E, sqrt(c->sm_var2));
    for (i2=0;i2<c->n;i2++)
      fprintf(stdout, "%d ", c->contents[i2]);
    fprintf(stdout, "\n");
  }

  fprintf(stdout, "\n");
  return 0;
}


// get the overlap between 2 jets
//  - j1        first jet
//  - j2        second jet
//  - overlap2  returned overlap^2 (determined by the choice of SM variable)
// return true if overlapping, false if disjoint
//---------------------------------------------------------------------
bool Csplit_merge::get_overlap(const Cjet &j1, const Cjet &j2, double *overlap2){
  // check if ranges overlap
  if (!is_range_overlap(j1.range,j2.range))
    return false;

  int i1,i2;
  bool is_overlap;

  // initialise
  i1=i2=idx_size=0;
  is_overlap = false;
  Cmomentum v;
  double pt_tilde=0.0;

  // compute overlap
  // at the same time, we store union in indices
  do{
    if (j1.contents[i1]<j2.contents[i2]){
      indices[idx_size] = j1.contents[i1];
      i1++;
    } else if (j1.contents[i1]>j2.contents[i2]){
      indices[idx_size] = j2.contents[i2];
      i2++;
    } else { // (j1.contents[i1]==j2.contents[i2])
      v += particles[j1.contents[i1]];
      pt_tilde += pt[j1.contents[i1]];
      indices[idx_size] = j1.contents[i1];
      i1++;
      i2++;
      is_overlap = true;
    }
    idx_size++;
  } while ((i1<j1.n) && (i2<j2.n));

  // finish computing union
  // (only needed if overlap!)
  if (is_overlap){
    while (i1<j1.n){
      indices[idx_size] = j1.contents[i1];
      i1++;
      idx_size++;
    }
    while (i2<j2.n){
      indices[idx_size] = j2.contents[i2];
      i2++;
      idx_size++;
    }
  }

  // assign the overlapping var as return variable
  (*overlap2) = get_sm_var2(v, pt_tilde);

  return is_overlap;
}



// split the two given jet.
// during this procedure, the jets j1 & j2 are replaced
// by 2 new jets. Common particles are associted to the
// closest initial jet.
//  - it_j1  iterator of the first jet in 'candidates'
//  - it_j2  iterator of the second jet in 'candidates'
//  - j1     first jet (Cjet instance)
//  - j2     second jet (Cjet instance)
// return true on success, false on error
////////////////////////////////////////////////////////////////
bool Csplit_merge::split(cjet_iterator &it_j1, cjet_iterator &it_j2){
  int i1, i2;
  Cjet jet1, jet2;
  double eta1, phi1, pt1_weight, eta2, phi2, pt2_weight;
  double dx1, dy1, dx2, dy2;
  Cmomentum tmp;
  Cmomentum *v;

  // shorthand to avoid having "->" all over the place
  const Cjet & j1 = * it_j1;
  const Cjet & j2 = * it_j2;

  i1=i2=0;
  jet2.v = jet1.v = Cmomentum();
  jet2.pt_tilde = jet1.pt_tilde = 0.0;

  // compute centroids
  // When use_pt_weighted_splitting is activated, the
  // "geometrical" distance is weighted