31 #include "fastjet/internal/ClosestPair2D.hh" 
   38 FASTJET_BEGIN_NAMESPACE      
 
   40 const unsigned int twopow31      = 2147483648U;
 
   46 void ClosestPair2D::_point2shuffle(Point & point, Shuffle & shuffle, 
 
   49   Coord2D renorm_point = (point.coord - _left_corner)/_range;
 
   52   assert(renorm_point.x >=0);
 
   53   assert(renorm_point.x <=1);
 
   54   assert(renorm_point.y >=0);
 
   55   assert(renorm_point.y <=1);
 
   57   shuffle.x = 
static_cast<unsigned int>(twopow31 * renorm_point.x) + shift;
 
   58   shuffle.y = 
static_cast<unsigned int>(twopow31 * renorm_point.y) + shift;
 
   59   shuffle.point = &point;
 
   64 bool ClosestPair2D::Shuffle::operator<(
const Shuffle & q)
 const {
 
   78 void ClosestPair2D::_initialize(
const std::vector<Coord2D> & positions, 
 
   79                              const Coord2D & left_corner, 
 
   80                              const Coord2D & right_corner,
 
   81                              unsigned int max_size) {
 
   83   unsigned int n_positions = positions.size();
 
   84   assert(max_size >= n_positions);
 
   89   _points.resize(max_size);
 
   92   for (
unsigned int i = n_positions; i < max_size; i++) {
 
   93     _available_points.push(&(_points[i]));
 
   96   _left_corner = left_corner;
 
   97   _range       = max((right_corner.x - left_corner.x),
 
   98                      (right_corner.y - left_corner.y));
 
  102   vector<Shuffle> shuffles(n_positions);
 
  103   for (
unsigned int i = 0; i < n_positions; i++) {
 
  105     _points[i].coord = positions[i];
 
  106     _points[i].neighbour_dist2 = numeric_limits<double>::max();
 
  107     _points[i].review_flag = 0;
 
  110     _point2shuffle(_points[i], shuffles[i], 0);
 
  114   for (
unsigned ishift = 0; ishift < _nshift; ishift++) {
 
  117    _shifts[ishift] = 
static_cast<unsigned int>(((twopow31*1.0)*ishift)/_nshift);
 
  118     if (ishift == 0) {_rel_shifts[ishift] = 0;}
 
  119     else {_rel_shifts[ishift] = _shifts[ishift] - _shifts[ishift-1];}
 
  130   _cp_search_range = 30;
 
  131   _points_under_review.reserve(_nshift * _cp_search_range);
 
  134   for (
unsigned int ishift = 0; ishift < _nshift; ishift++) {
 
  138       unsigned rel_shift = _rel_shifts[ishift];
 
  139       for (
unsigned int i = 0; i < shuffles.size(); i++) {
 
  140         shuffles[i] += rel_shift; }
 
  144     sort(shuffles.begin(), shuffles.end());
 
  147     _trees[ishift] = auto_ptr<Tree>(
new Tree(shuffles, max_size));
 
  150     circulator circ = _trees[ishift]->somewhere(), start=circ;
 
  152     unsigned int CP_range = min(_cp_search_range, n_positions-1);
 
  154       Point * this_point = circ->point;
 
  156       this_point->circ[ishift] = circ;
 
  158       circulator other = circ;
 
  159       for (
unsigned i=0; i < CP_range; i++) {
 
  161         double dist2 = this_point->distance2(*other->point);
 
  162         if (dist2 < this_point->neighbour_dist2) {
 
  163           this_point->neighbour_dist2 = dist2;
 
  164           this_point->neighbour       = other->point;
 
  167     } 
while (++circ != start);
 
  172   vector<double> mindists2(n_positions);
 
  173   for (
unsigned int i = 0; i < n_positions; i++) {
 
  174     mindists2[i] = _points[i].neighbour_dist2;}
 
  176   _heap = auto_ptr<MinHeap>(
new MinHeap(mindists2, max_size));
 
  181 void ClosestPair2D::closest_pair(
unsigned int & ID1, 
unsigned int & ID2, 
 
  182                                  double & distance2)
 const {
 
  183   ID1 = _heap->minloc();
 
  184   ID2 = _ID(_points[ID1].neighbour);
 
  185   distance2 = _points[ID1].neighbour_dist2;
 
  190   if (ID1 > ID2) std::swap(ID1,ID2);
 
  195 inline void ClosestPair2D::_add_label(Point * point, 
unsigned int review_flag) {
 
  199   if (point->review_flag == 0) _points_under_review.push_back(point);
 
  202   point->review_flag |= review_flag;
 
  206 inline void ClosestPair2D::_set_label(Point * point, 
unsigned int review_flag) {
 
  210   if (point->review_flag == 0) _points_under_review.push_back(point);
 
  213   point->review_flag = review_flag;
 
  217 void ClosestPair2D::remove(
unsigned int ID) {
 
  221   Point * point_to_remove = & (_points[ID]);
 
  224   _remove_from_search_tree(point_to_remove);
 
  228   _deal_with_points_to_review();
 
  233 void ClosestPair2D::_remove_from_search_tree(Point * point_to_remove) {
 
  238   _available_points.push(point_to_remove);
 
  241   _set_label(point_to_remove, _remove_heap_entry);
 
  247   unsigned int CP_range = min(_cp_search_range, size()-1);
 
  250   for (
unsigned int ishift = 0; ishift < _nshift; ishift++) {
 
  253     circulator removed_circ = point_to_remove->circ[ishift];
 
  254     circulator right_end = removed_circ.next();
 
  256     _trees[ishift]->remove(removed_circ);
 
  259     circulator left_end  = right_end, orig_right_end = right_end;
 
  260     for (
unsigned int i = 0; i < CP_range; i++) {left_end--;}
 
  262     if (size()-1 < _cp_search_range) {
 
  267       left_end--; right_end--;
 
  274       Point * left_point = left_end->point;
 
  278       if (left_point->neighbour == point_to_remove) {
 
  280         _add_label(left_point, _review_neighbour);
 
  283         double dist2 = left_point->distance2(*right_end->point);
 
  284         if (dist2 < left_point->neighbour_dist2) {
 
  285           left_point->neighbour = right_end->point;
 
  286           left_point->neighbour_dist2 = dist2;
 
  288           _add_label(left_point, _review_heap_entry);
 
  292     } 
while (++left_end != orig_right_end);
 
  299 void ClosestPair2D::_deal_with_points_to_review() {
 
  303   unsigned int CP_range = min(_cp_search_range, size()-1);
 
  307   while(_points_under_review.size() > 0) {
 
  309     Point * this_point = _points_under_review.back();
 
  311     _points_under_review.pop_back();  
 
  313     if (this_point->review_flag & _remove_heap_entry) {
 
  315       assert(!(this_point->review_flag ^ _remove_heap_entry));
 
  316       _heap->remove(_ID(this_point));
 
  320       if (this_point->review_flag & _review_neighbour) {
 
  321         this_point->neighbour_dist2 = numeric_limits<double>::max();
 
  323         for (
unsigned int ishift = 0; ishift < _nshift; ishift++) {
 
  324           circulator other = this_point->circ[ishift];
 
  326           for (
unsigned i=0; i < CP_range; i++) {
 
  328             double dist2 = this_point->distance2(*other->point);
 
  329             if (dist2 < this_point->neighbour_dist2) {
 
  330               this_point->neighbour_dist2 = dist2;
 
  331               this_point->neighbour       = other->point;
 
  338       _heap->update(_ID(this_point), this_point->neighbour_dist2);
 
  342     this_point->review_flag = 0; 
 
  349 unsigned int ClosestPair2D::insert(
const Coord2D & new_coord) {
 
  352   assert(_available_points.size() > 0);
 
  353   Point * new_point = _available_points.top();
 
  354   _available_points.pop();
 
  357   new_point->coord = new_coord;
 
  360   _insert_into_search_tree(new_point);
 
  364   _deal_with_points_to_review();
 
  367   return _ID(new_point);
 
  371 unsigned int ClosestPair2D::replace(
unsigned int ID1, 
unsigned int ID2, 
 
  372                                     const Coord2D & position) {
 
  375   Point * point_to_remove = & (_points[ID1]);
 
  376   _remove_from_search_tree(point_to_remove);
 
  378   point_to_remove = & (_points[ID2]);
 
  379   _remove_from_search_tree(point_to_remove);
 
  383   Point * new_point = _available_points.top();
 
  384   _available_points.pop();
 
  387   new_point->coord = position;
 
  390   _insert_into_search_tree(new_point);
 
  394   _deal_with_points_to_review();
 
  397   return _ID(new_point);
 
  403 void ClosestPair2D::replace_many(
 
  404                   const std::vector<unsigned int> & IDs_to_remove,
 
  405                   const std::vector<Coord2D> & new_positions,
 
  406                   std::vector<unsigned int> & new_IDs) {
 
  409   for (
unsigned int i = 0; i < IDs_to_remove.size(); i++) {
 
  410     _remove_from_search_tree(& (_points[IDs_to_remove[i]]));
 
  415   for (
unsigned int i = 0; i < new_positions.size(); i++) {
 
  416     Point * new_point = _available_points.top();
 
  417     _available_points.pop();
 
  419     new_point->coord = new_positions[i];
 
  421     _insert_into_search_tree(new_point);
 
  423     new_IDs.push_back(_ID(new_point));
 
  428   _deal_with_points_to_review();
 
  434 void ClosestPair2D::_insert_into_search_tree(Point * new_point) {
 
  437   _set_label(new_point, _review_heap_entry);
 
  440   new_point->neighbour_dist2 = numeric_limits<double>::max();
 
  443   unsigned int CP_range = min(_cp_search_range, size()-1);
 
  445   for (
unsigned ishift = 0; ishift < _nshift; ishift++) {
 
  448     _point2shuffle(*new_point, new_shuffle, _shifts[ishift]);
 
  451     circulator new_circ = _trees[ishift]->insert(new_shuffle);
 
  452     new_point->circ[ishift] = new_circ;
 
  456     circulator right_edge = new_circ; right_edge++;
 
  457     circulator left_edge  = new_circ;
 
  458     for (
unsigned int i = 0; i < CP_range; i++) {left_edge--;}
 
  462       Point * left_point  = left_edge->point;
 
  463       Point * right_point = right_edge->point;
 
  467       double new_dist2 = left_point->distance2(*new_point);
 
  468       if (new_dist2 < left_point->neighbour_dist2) {
 
  469         left_point->neighbour_dist2 = new_dist2;
 
  470         left_point->neighbour       = new_point;
 
  471         _add_label(left_point, _review_heap_entry);
 
  476       new_dist2 = new_point->distance2(*right_point);
 
  477       if (new_dist2 < new_point->neighbour_dist2) {
 
  478         new_point->neighbour_dist2 = new_dist2;
 
  479         new_point->neighbour = right_point;
 
  488       if (left_point->neighbour == right_point) {
 
  489         _add_label(left_point, _review_neighbour);
 
  494     } 
while (++left_edge != new_circ);
 
  498 FASTJET_END_NAMESPACE
 
bool floor_ln2_less(unsigned x, unsigned y)
returns true if floor(ln_base2(x)) < floor(ln_base2(y)), using Chan's neat trick...