LCOV - code coverage report
Current view: top level - PYTHIA8/pythia8210dev/src - FJcore.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 2749 0.1 %
Date: 2016-06-14 17:26:59 Functions: 2 813 0.2 %

          Line data    Source code
       1             : // fjcore -- extracted from FastJet v3.0.5 (http://fastjet.fr)
       2             : //
       3             : // fjcore constitutes a digest of the main FastJet functionality.
       4             : // The files fjcore.hh and fjcore.cc are meant to provide easy access to these
       5             : // core functions, in the form of single files and without the need of a full
       6             : // FastJet installation:
       7             : //
       8             : //     g++ main.cc fjcore.cc
       9             : //
      10             : // with main.cc including fjcore.hh.
      11             : //
      12             : // The results are expected to be identical to those obtained by linking to
      13             : // the full FastJet distribution.
      14             : //
      15             : // NOTE THAT, IN ORDER TO MAKE IT POSSIBLE FOR FJCORE AND THE FULL FASTJET
      16             : // TO COEXIST, THE FORMER USES THE "fjcore" NAMESPACE INSTEAD OF "fastjet".
      17             : //
      18             : // In particular, fjcore provides:
      19             : //
      20             : //   - access to all native pp and ee algorithms, kt, anti-kt, C/A.
      21             : //     For C/A, the NlnN method is available, while anti-kt and kt
      22             : //     are limited to the N^2 one (still the fastest for N < 20k particles)
      23             : //   - access to selectors, for implementing cuts and selections
      24             : //   - access to all functionalities related to pseudojets (e.g. a jet's
      25             : //     structure or user-defined information)
      26             : //
      27             : // Instead, it does NOT provide:
      28             : //
      29             : //   - jet areas functionality
      30             : //   - background estimation
      31             : //   - access to other algorithms via plugins
      32             : //   - interface to CGAL
      33             : //   - fastjet tools, e.g. filters, taggers
      34             : //
      35             : // If these functionalities are needed, the full FastJet installation must be
      36             : // used. The code will be fully compatible, with the sole replacement of the
      37             : // header files and of the fjcore namespace with the fastjet one.
      38             : //
      39             : // fjcore.hh and fjcore.cc are not meant to be human-readable.
      40             : // For documentation, see the full FastJet manual and doxygen at http://fastjet.fr
      41             : //
      42             : // Like FastJet, fjcore is released under the terms of the GNU General Public
      43             : // License version 2 (GPLv2). If you use this code as part of work towards a
      44             : // scientific publication, whether directly or contained within another program
      45             : // (e.g. Delphes, SpartyJet, Rivet, LHC collaboration software frameworks,
      46             : // etc.), you should include a citation to
      47             : //
      48             : //   EPJC72(2012)1896 [arXiv:1111.6097] (FastJet User Manual)
      49             : //   and, optionally, Phys.Lett.B641 (2006) 57 [arXiv:hep-ph/0512210]
      50             : //
      51             : // Copyright (c) 2005-2013, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
      52             : //
      53             : //----------------------------------------------------------------------
      54             : // This file is part of FastJet.
      55             : //
      56             : //  FastJet is free software; you can redistribute it and/or modify
      57             : //  it under the terms of the GNU General Public License as published by
      58             : //  the Free Software Foundation; either version 2 of the License, or
      59             : //  (at your option) any later version.
      60             : //
      61             : //  The algorithms that underlie FastJet have required considerable
      62             : //  development and are described in hep-ph/0512210. If you use
      63             : //  FastJet as part of work towards a scientific publication, please
      64             : //  include a citation to the FastJet paper.
      65             : //
      66             : //  FastJet is distributed in the hope that it will be useful,
      67             : //  but WITHOUT ANY WARRANTY; without even the implied warranty of
      68             : //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      69             : //  GNU General Public License for more details.
      70             : //
      71             : //  You should have received a copy of the GNU General Public License
      72             : //  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
      73             : //----------------------------------------------------------------------
      74             : //
      75             : //#include "fjcore.hh"
      76             : // For inclusion in Pythia8 line above is replaced by line below.
      77             : #include "Pythia8/FJcore.h"
      78             : #ifndef __FJCORE_VERSION_HH__
      79             : #define __FJCORE_VERSION_HH__
      80             : #include<string>
      81             : FJCORE_BEGIN_NAMESPACE
      82             : const char* fastjet_version = FJCORE_PACKAGE_VERSION;
      83             : FJCORE_END_NAMESPACE
      84             : #endif // __FJCORE_VERSION_HH__
      85             : #ifndef __FJCORE_CLUSTERQUENCE_N2_ICC__
      86             : #define __FJCORE_CLUSTERQUENCE_N2_ICC__
      87             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
      88             : template<class BJ> void ClusterSequence::_simple_N2_cluster() {
      89           0 :   int n = _jets.size();
      90           0 :   BJ * briefjets = new BJ[n];
      91           0 :   BJ * jetA = briefjets, * jetB;
      92           0 :   for (int i = 0; i< n; i++) {
      93           0 :     _bj_set_jetinfo(jetA, i);
      94           0 :     jetA++; // move on to next entry of briefjets
      95             :   }
      96           0 :   BJ * tail = jetA; // a semaphore for the end of briefjets
      97             :   BJ * head = briefjets; // a nicer way of naming start
      98           0 :   for (jetA = head + 1; jetA != tail; jetA++) {
      99           0 :     _bj_set_NN_crosscheck(jetA, head, jetA);
     100             :   }
     101           0 :   double * diJ = new double[n];
     102           0 :   jetA = head;
     103           0 :   for (int i = 0; i < n; i++) {
     104           0 :     diJ[i] = _bj_diJ(jetA);
     105           0 :     jetA++; // have jetA follow i
     106             :   }
     107           0 :   int history_location = n-1;
     108           0 :   while (tail != head) {
     109           0 :     double diJ_min = diJ[0];
     110             :     int diJ_min_jet = 0;
     111           0 :     for (int i = 1; i < n; i++) {
     112           0 :       if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min  = diJ[i];}
     113             :     }
     114           0 :     history_location++;
     115           0 :     jetA = & briefjets[diJ_min_jet];
     116           0 :     jetB = static_cast<BJ *>(jetA->NN);
     117           0 :     diJ_min *= _invR2;
     118           0 :     if (jetB != NULL) {
     119           0 :       if (jetA < jetB) {std::swap(jetA,jetB);}
     120           0 :       int nn; // new jet index
     121           0 :       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
     122           0 :       _bj_set_jetinfo(jetB, nn);
     123           0 :     } else {
     124           0 :       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
     125             :     }
     126           0 :     tail--; n--;
     127           0 :     *jetA = *tail;
     128           0 :     diJ[jetA - head] = diJ[tail-head];
     129           0 :     for (BJ * jetI = head; jetI != tail; jetI++) {
     130           0 :       if (jetI->NN == jetA || jetI->NN == jetB) {
     131           0 :         _bj_set_NN_nocross(jetI, head, tail);
     132           0 :         diJ[jetI-head] = _bj_diJ(jetI); // update diJ
     133           0 :       }
     134           0 :       if (jetB != NULL) {
     135           0 :         double dist = _bj_dist(jetI,jetB);
     136           0 :         if (dist < jetI->NN_dist) {
     137           0 :           if (jetI != jetB) {
     138           0 :             jetI->NN_dist = dist;
     139           0 :             jetI->NN = jetB;
     140           0 :             diJ[jetI-head] = _bj_diJ(jetI); // update diJ...
     141           0 :           }
     142             :         }
     143           0 :         if (dist < jetB->NN_dist) {
     144           0 :           if (jetI != jetB) {
     145           0 :             jetB->NN_dist = dist;
     146           0 :             jetB->NN      = jetI;}
     147             :         }
     148           0 :       }
     149           0 :       if (jetI->NN == tail) {jetI->NN = jetA;}
     150             :     }
     151           0 :     if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
     152           0 :   }
     153           0 :   delete[] diJ;
     154           0 :   delete[] briefjets;
     155           0 : }
     156             : FJCORE_END_NAMESPACE
     157             : #endif // __FJCORE_CLUSTERQUENCE_N2_ICC__
     158             : #ifndef __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
     159             : #define __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
     160             : #include<vector>
     161             : #include<string>
     162             : #include<iostream>
     163             : #include<sstream>
     164             : #include<cassert>
     165             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
     166             : class EtaPhi {
     167             : public:
     168             :   double first, second;
     169           0 :   EtaPhi() {}
     170           0 :   EtaPhi(double a, double b) {first = a; second = b;}
     171             :   void sanitize() {
     172           0 :     if (second <  0)     second += twopi;
     173           0 :     if (second >= twopi) second -= twopi;
     174           0 :   }
     175             : };
     176             : class DnnError {
     177             : public:
     178             :   DnnError() {;};
     179             :   DnnError(const std::string & message_in) {
     180             :     _message = message_in; std::cerr << message_in << std::endl;};
     181             :   std::string message() const {return _message;};
     182             : private:
     183             :   std::string _message;
     184             : };
     185             : class DynamicNearestNeighbours {
     186             : public:
     187             :   virtual int NearestNeighbourIndex(const int & ii) const = 0;
     188             :   virtual double NearestNeighbourDistance(const int & ii) const = 0;
     189             :   virtual bool Valid(const int & index) const = 0;
     190             :   virtual void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
     191             :                           const std::vector<EtaPhi> & points_to_add,
     192             :                           std::vector<int> & indices_added,
     193             :                           std::vector<int> & indices_of_updated_neighbours) = 0;
     194             :   inline void RemovePoint (const int & index,
     195             :                            std::vector<int> & indices_of_updated_neighbours) {
     196             :     std::vector<int> indices_added;
     197             :     std::vector<EtaPhi> points_to_add;
     198             :     std::vector<int> indices_to_remove(1);
     199             :     indices_to_remove[0] = index;
     200             :     RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
     201             :                        indices_of_updated_neighbours
     202             :                        );};
     203             :   inline void RemoveCombinedAddCombination(
     204             :                         const int & index1, const int & index2,
     205             :                         const EtaPhi & newpoint,
     206             :                         int & index3,
     207             :                         std::vector<int> & indices_of_updated_neighbours) {
     208             :     std::vector<int> indices_added(1);
     209             :     std::vector<EtaPhi> points_to_add(1);
     210             :     std::vector<int> indices_to_remove(2);
     211             :     indices_to_remove[0] = index1;
     212             :     indices_to_remove[1] = index2;
     213             :     points_to_add[0] = newpoint;
     214             :     RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
     215             :                        indices_of_updated_neighbours
     216             :                        );
     217             :     index3 = indices_added[0];
     218             :   };
     219             :   virtual ~DynamicNearestNeighbours () {}
     220             : };
     221             : FJCORE_END_NAMESPACE
     222             : #endif // __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
     223             : #ifndef __FJCORE_SEARCHTREE_HH__
     224             : #define __FJCORE_SEARCHTREE_HH__
     225             : #include<vector>
     226             : #include<cassert>
     227             : #include<cstddef>
     228             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
     229           0 : template<class T> class SearchTree {
     230             : public:
     231             :   class Node;
     232             :   class circulator;
     233             :   class const_circulator;
     234             :   SearchTree(const std::vector<T> & init);
     235           0 :   SearchTree(const std::vector<T> & init, unsigned int max_size);
     236             :   void remove(unsigned node_index);
     237             :   void remove(typename SearchTree::Node * node);
     238             :   void remove(typename SearchTree::circulator & circ);
     239             :   circulator insert(const T & value);
     240             :   const Node & operator[](int i) const {return _nodes[i];};
     241           0 :   unsigned int size() const {return _nodes.size() - _available_nodes.size();}
     242             :   void verify_structure();
     243             :   void verify_structure_linear() const;
     244             :   void verify_structure_recursive(const Node * , const Node * , const Node * ) const;
     245             :   void print_elements();
     246             : #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
     247             :   inline unsigned int max_depth() const {return _max_depth;};
     248             : #else
     249             :   inline unsigned int max_depth() const {return 0;};
     250             : #endif
     251             :   int loc(const Node * node) const ;
     252             :   Node * _find_predecessor(const Node *);
     253             :   Node * _find_successor(const Node *);
     254             :   const Node & operator[](unsigned int i) const {return _nodes[i];};
     255             :   const_circulator somewhere() const;
     256             :   circulator somewhere();
     257             : private:
     258             :   void _initialize(const std::vector<T> & init);
     259             :   std::vector<Node> _nodes;
     260             :   std::vector<Node *> _available_nodes;
     261             :   Node * _top_node;
     262             :   unsigned int _n_removes;
     263             :   void _do_initial_connections(unsigned int this_one, unsigned int scale,
     264             :                                unsigned int left_edge, unsigned int right_edge,
     265             :                                unsigned int depth);
     266             : #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
     267             :   unsigned int _max_depth;
     268             : #endif
     269             : };
     270             : template<class T> class SearchTree<T>::Node{
     271             : public:
     272           0 :   Node() {}; /// default constructor
     273             :   bool treelinks_null() const {
     274           0 :     return ((parent==0) && (left==0) && (right==0));};
     275             :   inline void nullify_treelinks() {
     276           0 :     parent = NULL;
     277           0 :     left   = NULL;
     278           0 :     right  = NULL;
     279           0 :   };
     280             :   void reset_parents_link_to_me(Node * XX);
     281             :   T      value;
     282             :   Node * left;
     283             :   Node * right;
     284             :   Node * parent;
     285             :   Node * successor;
     286             :   Node * predecessor;
     287             : };
     288             : template<class T> void SearchTree<T>::Node::reset_parents_link_to_me(typename SearchTree<T>::Node * XX) {
     289           0 :   if (parent == NULL) {return;}
     290           0 :   if (parent->right == this) {parent->right = XX;}
     291           0 :   else {parent->left = XX;}
     292           0 : }
     293             : template<class T> class SearchTree<T>::circulator{
     294             : public:
     295             :   // Next line commented out, by author agreement, to avoid compiler warning.
     296             :   //template<class U> friend class SearchTree<U>::const_circulator;
     297             :   friend class SearchTree<T>;
     298           0 :   circulator() : _node(NULL) {}
     299           0 :   circulator(Node * node) : _node(node) {}
     300             :   const T * operator->() const {return &(_node->value);}
     301           0 :   T * operator->() {return &(_node->value);}
     302             :   const T & operator*() const {return _node->value;}
     303             :   T & operator*() {return _node->value;}
     304             :   circulator & operator++() {
     305           0 :     _node = _node->successor;
     306           0 :     return *this;}
     307             :   circulator operator++(int) {
     308           0 :     circulator tmp = *this;
     309           0 :     _node = _node->successor;
     310           0 :     return tmp;}
     311             :   circulator & operator--() {
     312             :     _node = _node->predecessor;
     313             :     return *this;}
     314             :   circulator operator--(int) {
     315           0 :     circulator tmp = *this;
     316           0 :     _node = _node->predecessor;
     317           0 :     return tmp;}
     318             :   circulator next() const {
     319           0 :     return circulator(_node->successor);}
     320             :   circulator previous() const {
     321             :     return circulator(_node->predecessor);}
     322           0 :   bool operator!=(const circulator & other) const {return other._node != _node;}
     323             :   bool operator==(const circulator & other) const {return other._node == _node;}
     324             : private:
     325             :   Node * _node;
     326             : };
     327             : template<class T> class SearchTree<T>::const_circulator{
     328             : public:
     329             :   const_circulator() : _node(NULL) {}
     330             :   const_circulator(const Node * node) : _node(node) {}
     331             :   const_circulator(const circulator & circ) :_node(circ._node) {}
     332             :   const T * operator->() {return &(_node->value);}
     333             :   const T & operator*() const {return _node->value;}
     334             :   const_circulator & operator++() {
     335             :     _node = _node->successor;
     336             :     return *this;}
     337             :   const_circulator operator++(int) {
     338             :     const_circulator tmp = *this;
     339             :     _node = _node->successor;
     340             :     return tmp;}
     341             :   const_circulator & operator--() {
     342             :     _node = _node->predecessor;
     343             :     return *this;}
     344             :   const_circulator operator--(int) {
     345             :     const_circulator tmp = *this;
     346             :     _node = _node->predecessor;
     347             :     return tmp;}
     348             :   const_circulator next() const {
     349             :     return const_circulator(_node->successor);}
     350             :   const_circulator previous() const {
     351             :     return const_circulator(_node->predecessor);}
     352             :   bool operator!=(const const_circulator & other) const {return other._node != _node;}
     353             :   bool operator==(const const_circulator & other) const {return other._node == _node;}
     354             : private:
     355             :   const Node * _node;
     356             : };
     357             : template<class T> SearchTree<T>::SearchTree(const std::vector<T> & init,
     358             :                                             unsigned int max_size) :
     359           0 :   _nodes(max_size) {
     360           0 :   _available_nodes.reserve(max_size);
     361           0 :   _available_nodes.resize(max_size - init.size());
     362           0 :   for (unsigned int i = init.size(); i < max_size; i++) {
     363           0 :     _available_nodes[i-init.size()] = &(_nodes[i]);
     364             :   }
     365           0 :   _initialize(init);
     366           0 : }
     367             : template<class T> SearchTree<T>::SearchTree(const std::vector<T> & init) :
     368             :   _nodes(init.size()), _available_nodes(0) {
     369             :   _available_nodes.reserve(init.size());
     370             :   _initialize(init);
     371             : }
     372             : template<class T> void SearchTree<T>::_initialize(const std::vector<T> & init) {
     373           0 :   _n_removes = 0;
     374           0 :   unsigned n = init.size();
     375           0 :   assert(n>=1);
     376             : #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
     377             :   _max_depth     = 0;
     378             : #endif
     379           0 :   for (unsigned int i = 1; i<n; i++) {
     380           0 :     assert(!(init[i] < init[i-1]));
     381             :   }
     382           0 :   for(unsigned int i = 0; i < n; i++) {
     383           0 :     _nodes[i].value = init[i];
     384           0 :     _nodes[i].predecessor = (& (_nodes[i])) - 1;
     385           0 :     _nodes[i].successor   = (& (_nodes[i])) + 1;
     386           0 :     _nodes[i].nullify_treelinks();
     387             :   }
     388           0 :   _nodes[0].predecessor = (& (_nodes[n-1]));
     389           0 :   _nodes[n-1].successor = (& (_nodes[0]));
     390           0 :   unsigned int scale = (n+1)/2;
     391           0 :   unsigned int top   = std::min(n-1,scale);
     392           0 :   _nodes[top].parent = NULL;
     393           0 :   _top_node = &(_nodes[top]);
     394           0 :   _do_initial_connections(top, scale, 0, n, 0);
     395           0 : }
     396             : template<class T> inline  int SearchTree<T>::loc(const Node * node) const {return node == NULL?
     397             :       -999 : node - &(_nodes[0]);}
     398             : template<class T> void SearchTree<T>::_do_initial_connections(
     399             :                                          unsigned int this_one,
     400             :                                          unsigned int scale,
     401             :                                          unsigned int left_edge,
     402             :                                          unsigned int right_edge,
     403             :                                          unsigned int depth
     404             :                                          ) {
     405             : #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
     406             :   _max_depth = max(depth, _max_depth);
     407             : #endif
     408           0 :   unsigned int ref_new_scale = (scale+1)/2;
     409             :   unsigned new_scale = ref_new_scale;
     410             :   bool     did_child  = false;
     411           0 :   while(true) {
     412           0 :     int left = this_one - new_scale; // be careful here to use signed int...
     413           0 :     if (left >= static_cast<int>(left_edge)
     414           0 :                         && _nodes[left].treelinks_null() ) {
     415           0 :       _nodes[left].parent = &(_nodes[this_one]);
     416           0 :       _nodes[this_one].left = &(_nodes[left]);
     417           0 :       _do_initial_connections(left, new_scale, left_edge, this_one, depth+1);
     418             :       did_child = true;
     419           0 :       break;
     420             :     }
     421             :     unsigned int old_new_scale = new_scale;
     422           0 :     new_scale = (old_new_scale + 1)/2;
     423           0 :     if (new_scale == old_new_scale) break;
     424           0 :   }
     425           0 :   if (!did_child) {_nodes[this_one].left = NULL;}
     426             :   new_scale = ref_new_scale;
     427             :   did_child  = false;
     428           0 :   while(true) {
     429           0 :     unsigned int right = this_one + new_scale;
     430           0 :     if (right < right_edge  && _nodes[right].treelinks_null()) {
     431           0 :       _nodes[right].parent = &(_nodes[this_one]);
     432           0 :       _nodes[this_one].right = &(_nodes[right]);
     433           0 :       _do_initial_connections(right, new_scale, this_one+1,right_edge,depth+1);
     434             :       did_child = true;
     435           0 :       break;
     436             :     }
     437             :     unsigned int old_new_scale = new_scale;
     438           0 :     new_scale = (old_new_scale + 1)/2;
     439           0 :     if (new_scale == old_new_scale) break;
     440           0 :   }
     441           0 :   if (!did_child) {_nodes[this_one].right = NULL;}
     442           0 : }
     443             : template<class T> void SearchTree<T>::remove(unsigned int node_index) {
     444             :   remove(&(_nodes[node_index]));
     445             : }
     446             : template<class T> void SearchTree<T>::remove(circulator & circ) {
     447           0 :   remove(circ._node);
     448           0 : }
     449             : template<class T> void SearchTree<T>::remove(typename SearchTree<T>::Node * node) {
     450           0 :   assert(size() > 1); // switch this to throw...?
     451           0 :   assert(!node->treelinks_null());
     452           0 :   node->predecessor->successor = node->successor;
     453           0 :   node->successor->predecessor = node->predecessor;
     454           0 :   if (node->left == NULL && node->right == NULL) {
     455           0 :     node->reset_parents_link_to_me(NULL);
     456           0 :   } else if (node->left != NULL && node->right == NULL){
     457           0 :     node->reset_parents_link_to_me(node->left);
     458           0 :     node->left->parent = node->parent;
     459           0 :     if (_top_node == node) {_top_node = node->left;}
     460           0 :   } else if (node->left == NULL && node->right != NULL){
     461           0 :     node->reset_parents_link_to_me(node->right);
     462           0 :     node->right->parent = node->parent;
     463           0 :     if (_top_node == node) {_top_node = node->right;}
     464             :   } else {
     465             :     Node * replacement;
     466           0 :     bool use_predecessor = (_n_removes % 2 == 1);
     467           0 :     if (use_predecessor) {
     468           0 :       replacement = node->predecessor;
     469           0 :       assert(replacement->right == NULL); // guaranteed if it's our predecessor
     470           0 :       if (replacement != node->left) {
     471           0 :         if (replacement->left != NULL) {
     472           0 :           replacement->left->parent = replacement->parent;}
     473           0 :         replacement->reset_parents_link_to_me(replacement->left);
     474           0 :         replacement->left   = node->left;
     475           0 :       }
     476           0 :       replacement->parent = node->parent;
     477           0 :       replacement->right  = node->right;
     478           0 :     } else {
     479           0 :       replacement = node->successor;
     480           0 :       assert(replacement->left == NULL); // guaranteed if it's our successor
     481           0 :       if (replacement != node->right) {
     482           0 :         if (replacement->right != NULL) {
     483           0 :           replacement->right->parent = replacement->parent;}
     484           0 :         replacement->reset_parents_link_to_me(replacement->right);
     485           0 :         replacement->right  = node->right;
     486           0 :       }
     487           0 :       replacement->parent = node->parent;
     488           0 :       replacement->left   = node->left;
     489             :     }
     490           0 :     node->reset_parents_link_to_me(replacement);
     491           0 :     if (node->left  != replacement) {node->left->parent  = replacement;}
     492           0 :     if (node->right != replacement) {node->right->parent = replacement;}
     493           0 :     if (_top_node == node) {_top_node = replacement;}
     494             :   }
     495           0 :   node->nullify_treelinks();
     496           0 :   node->predecessor = NULL;
     497           0 :   node->successor   = NULL;
     498           0 :   _n_removes++;
     499           0 :   _available_nodes.push_back(node);
     500           0 : }
     501             : template<class T> typename SearchTree<T>::circulator SearchTree<T>::insert(const T & value) {
     502           0 :   assert(_available_nodes.size() > 0);
     503           0 :   Node * node = _available_nodes.back();
     504           0 :   _available_nodes.pop_back();
     505           0 :   node->value = value;
     506           0 :   Node * location = _top_node;
     507             :   Node * old_location = NULL;
     508             :   bool             on_left = true; // (init not needed -- but soothes g++4)
     509             : #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
     510             :   unsigned int depth = 0;
     511             : #endif
     512           0 :   while(location != NULL) {
     513             : #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
     514             :     depth++;
     515             : #endif
     516             :     old_location = location;
     517           0 :     on_left = value < location->value;
     518           0 :     if (on_left) {location = location->left;}
     519           0 :     else {location = location->right;}
     520             :   }
     521             : #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
     522             :   _max_depth = max(depth, _max_depth);
     523             : #endif
     524           0 :   node->parent = old_location;
     525           0 :   if (on_left) {node->parent->left = node;}
     526           0 :   else {node->parent->right = node;}
     527           0 :   node->left = NULL;
     528           0 :   node->right = NULL;
     529           0 :   node->predecessor = _find_predecessor(node);
     530           0 :   if (node->predecessor != NULL) {
     531           0 :     node->successor = node->predecessor->successor;
     532           0 :     node->predecessor->successor = node;
     533           0 :     node->successor->predecessor = node;
     534           0 :   } else {
     535           0 :     node->successor = _find_successor(node);
     536           0 :     assert(node->successor != NULL); // can only happen if we're sole element
     537           0 :     node->predecessor = node->successor->predecessor;
     538           0 :     node->successor->predecessor = node;
     539           0 :     node->predecessor->successor = node;
     540             :   }
     541           0 :   return circulator(node);
     542           0 : }
     543             : template<class T> void SearchTree<T>::verify_structure() {
     544             :   verify_structure_linear();
     545             :   const Node * left_limit = _top_node;
     546             :   while (left_limit->left != NULL) {left_limit = left_limit->left;}
     547             :   const Node * right_limit = _top_node;
     548             :   while (right_limit->right != NULL) {right_limit = right_limit->right;}
     549             :   verify_structure_recursive(_top_node, left_limit, right_limit);
     550             : }
     551             : template<class T> void SearchTree<T>::verify_structure_recursive(
     552             :                       const typename SearchTree<T>::Node * element,
     553             :                       const typename SearchTree<T>::Node * left_limit,
     554             :                       const typename SearchTree<T>::Node * right_limit)  const {
     555             :   assert(!(element->value < left_limit->value));
     556             :   assert(!(right_limit->value < element->value));
     557             :   const Node * left = element->left;
     558             :   if (left != NULL) {
     559             :     assert(!(element->value < left->value));
     560             :     if (left != left_limit) {
     561             :       verify_structure_recursive(left, left_limit, element);}
     562             :   }
     563             :   const Node * right = element->right;
     564             :   if (right != NULL) {
     565             :     assert(!(right->value < element->value));
     566             :     if (right != right_limit) {
     567             :       verify_structure_recursive(right, element, right_limit);}
     568             :   }
     569             : }
     570             : template<class T> void SearchTree<T>::verify_structure_linear() const {
     571             :   unsigned n_top = 0;
     572             :   unsigned n_null = 0;
     573             :   for(unsigned i = 0; i < _nodes.size(); i++) {
     574             :     const typename SearchTree<T>::Node * node = &(_nodes[i]);
     575             :     if (node->treelinks_null()) {n_null++; continue;}
     576             :     if (node->parent == NULL) {
     577             :       n_top++;
     578             :     } else {
     579             :       assert((node->parent->left == node) ^ (node->parent->right == node));
     580             :     }
     581             :     if (node->left != NULL) {
     582             :       assert(!(node->value < node->left->value ));}
     583             :     if (node->right != NULL) {
     584             :       assert(!(node->right->value < node->value ));}
     585             :   }
     586             :   assert(n_top == 1 || (n_top == 0 && size() <= 1) );
     587             :   assert(n_null == _available_nodes.size() ||
     588             :          (n_null == _available_nodes.size() + 1 && size() == 1));
     589             : }
     590             : template<class T> typename SearchTree<T>::Node * SearchTree<T>::_find_predecessor(const typename SearchTree<T>::Node * node) {
     591             :   typename SearchTree<T>::Node * newnode;
     592           0 :   if (node->left != NULL) {
     593             :     newnode = node->left;
     594           0 :     while(newnode->right != NULL) {newnode = newnode->right;}
     595           0 :     return newnode;
     596             :   } else {
     597             :     const typename SearchTree<T>::Node * lastnode = node;
     598           0 :     newnode = node->parent;
     599           0 :     while(newnode != NULL) {
     600           0 :       if (newnode->right == lastnode) {return newnode;}
     601             :       lastnode = newnode;
     602           0 :       newnode = newnode->parent;
     603             :     }
     604           0 :     return newnode;
     605             :   }
     606           0 : }
     607             : template<class T> typename SearchTree<T>::Node * SearchTree<T>::_find_successor(const typename SearchTree<T>::Node * node) {
     608             :   typename SearchTree<T>::Node * newnode;
     609           0 :   if (node->right != NULL) {
     610             :     newnode = node->right;
     611           0 :     while(newnode->left != NULL) {newnode = newnode->left;}
     612           0 :     return newnode;
     613             :   } else {
     614             :     const typename SearchTree<T>::Node * lastnode = node;
     615           0 :     newnode = node->parent;
     616           0 :     while(newnode != NULL) {
     617           0 :       if (newnode->left == lastnode) {return newnode;}
     618             :       lastnode = newnode;
     619           0 :       newnode = newnode->parent;
     620             :     }
     621           0 :     return newnode;
     622             :   }
     623           0 : }
     624             : template<class T> void SearchTree<T>::print_elements() {
     625             :   typename SearchTree<T>::Node * base_node = &(_nodes[0]);
     626             :   typename SearchTree<T>::Node * node = base_node;
     627             :   int n = _nodes.size();
     628             :   for(; node - base_node < n ; node++) {
     629             :     printf("%4d parent:%4d left:%4d right:%4d pred:%4d succ:%4d value:%10.6f\n",loc(node), loc(node->parent), loc(node->left), loc(node->right), loc(node->predecessor),loc(node->successor),node->value);
     630             :   }
     631             : }
     632             : template<class T> typename SearchTree<T>::circulator SearchTree<T>::somewhere() {
     633           0 :   return circulator(_top_node);
     634             : }
     635             : template<class T> typename SearchTree<T>::const_circulator SearchTree<T>::somewhere() const {
     636             :   return const_circulator(_top_node);
     637             : }
     638             : FJCORE_END_NAMESPACE
     639             : #endif // __FJCORE_SEARCHTREE_HH__
     640             : #ifndef __FJCORE_MINHEAP__HH__
     641             : #define __FJCORE_MINHEAP__HH__
     642             : #include<vector>
     643             : #include<cassert>
     644             : #include<memory>
     645             : #include<limits>
     646             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
     647           0 : class MinHeap {
     648             : public:
     649             :   MinHeap (const std::vector<double> & values, unsigned int max_size) :
     650           0 :     _heap(max_size) {_initialise(values);};
     651             :   MinHeap (const std::vector<double> & values) :
     652           0 :     _heap(values.size()) {_initialise(values);};
     653             :   inline unsigned int minloc() const {
     654           0 :     return (_heap[0].minloc) - &(_heap[0]);};
     655           0 :   inline double       minval() const {return _heap[0].minloc->value;};
     656             :   inline double operator[](int i) const {return _heap[i].value;};
     657             :   void remove(unsigned int loc) {
     658           0 :     update(loc,std::numeric_limits<double>::max());};
     659             :   void update(unsigned int, double);
     660             : private:
     661             :   struct ValueLoc{
     662             :     double value;
     663             :     ValueLoc * minloc;
     664             :   };
     665             :   std::vector<ValueLoc> _heap;
     666             :   void _initialise(const std::vector<double> & values);
     667             : };
     668             : FJCORE_END_NAMESPACE
     669             : #endif // __FJCORE_MINHEAP__HH__
     670             : #ifndef __FJCORE_CLOSESTPAIR2DBASE__HH__
     671             : #define __FJCORE_CLOSESTPAIR2DBASE__HH__
     672             : #include<vector>
     673             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
     674             : class Coord2D {
     675             : public:
     676             :   double x, y;
     677           0 :   Coord2D() {};
     678           0 :   Coord2D(double a, double b): x(a), y(b) {};
     679             :   Coord2D operator-(const Coord2D & other) const {
     680           0 :     return Coord2D(x - other.x,  y - other.y);};
     681             :   Coord2D operator+(const Coord2D & other) const {
     682             :     return Coord2D(x + other.x,  y + other.y);};
     683             :   Coord2D operator*(double factor) const {return Coord2D(factor*x,factor*y);};
     684             :   friend Coord2D operator*(double factor, const Coord2D & coord) {
     685             :     return Coord2D(factor*coord.x,factor*coord.y);
     686             :   }
     687             :   Coord2D operator/(double divisor) const {
     688           0 :     return Coord2D(x / divisor,  y / divisor);};
     689             :   friend double distance2(const Coord2D & a, const Coord2D & b) {
     690             :     double dx = a.x - b.x, dy = a.y-b.y;
     691             :     return dx*dx+dy*dy;
     692             :   };
     693             :   double distance2(const Coord2D & b) const {
     694           0 :     double dx = x - b.x, dy = y-b.y;
     695           0 :     return dx*dx+dy*dy;
     696             :   };
     697             : };
     698           0 : class ClosestPair2DBase {
     699             : public:
     700             :   virtual void closest_pair(unsigned int & ID1, unsigned int & ID2,
     701             :                             double & distance2) const = 0;
     702             :   virtual void remove(unsigned int ID) = 0;
     703             :   virtual unsigned int insert(const Coord2D & position) = 0;
     704             :   virtual unsigned int replace(unsigned int ID1, unsigned int ID2,
     705             :                                const Coord2D & position) {
     706           0 :     remove(ID1);
     707           0 :     remove(ID2);
     708           0 :     unsigned new_ID = insert(position);
     709           0 :     return(new_ID);
     710             :   };
     711             :   virtual void replace_many(const std::vector<unsigned int> & IDs_to_remove,
     712             :                        const std::vector<Coord2D> & new_positions,
     713             :                        std::vector<unsigned int> & new_IDs) {
     714           0 :     for(unsigned i = 0; i < IDs_to_remove.size(); i++) {
     715           0 :       remove(IDs_to_remove[i]);}
     716           0 :     new_IDs.resize(0);
     717           0 :     for(unsigned i = 0; i < new_positions.size(); i++) {
     718           0 :       new_IDs.push_back(insert(new_positions[i]));}
     719           0 :   }
     720             :   virtual unsigned int size() = 0;
     721           0 :   virtual ~ClosestPair2DBase() {};
     722             : };
     723             : FJCORE_END_NAMESPACE
     724             : #endif // __FJCORE_CLOSESTPAIR2DBASE__HH__
     725             : #ifndef __FJCORE_CLOSESTPAIR2D__HH__
     726             : #define __FJCORE_CLOSESTPAIR2D__HH__
     727             : #include<vector>
     728             : #include<stack>
     729             : #include<iostream>
     730             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
     731           0 : class ClosestPair2D : public ClosestPair2DBase {
     732             : public:
     733           0 :   ClosestPair2D(const std::vector<Coord2D> & positions,
     734           0 :                 const Coord2D & left_corner, const Coord2D & right_corner) {
     735           0 :     _initialize(positions, left_corner, right_corner, positions.size());
     736           0 :   };
     737             :   ClosestPair2D(const std::vector<Coord2D> & positions,
     738             :                 const Coord2D & left_corner, const Coord2D & right_corner,
     739             :                 const unsigned int max_size) {
     740             :     _initialize(positions, left_corner, right_corner, max_size);
     741             :   };
     742             :   void closest_pair(unsigned int & ID1, unsigned int & ID2,
     743             :                     double & distance2) const;
     744             :   void remove(unsigned int ID);
     745             :   unsigned int insert(const Coord2D &);
     746             :   virtual unsigned int replace(unsigned int ID1, unsigned int ID2,
     747             :                                const Coord2D & position);
     748             :   virtual void replace_many(const std::vector<unsigned int> & IDs_to_remove,
     749             :                             const std::vector<Coord2D> & new_positions,
     750             :                             std::vector<unsigned int> & new_IDs);
     751             :   inline void print_tree_depths(std::ostream & outdev) const {
     752             :     outdev    << _trees[0]->max_depth() << " "
     753             :               << _trees[1]->max_depth() << " "
     754             :               << _trees[2]->max_depth() << "\n";
     755             :   };
     756             :   unsigned int size();
     757             : private:
     758             :   void _initialize(const std::vector<Coord2D> & positions,
     759             :               const Coord2D & left_corner, const Coord2D & right_corner,
     760             :               const unsigned int max_size);
     761             :   static const unsigned int _nshift = 3;
     762             :   class Point; // will be defined below
     763           0 :   template<class T> class triplet {
     764             :   public:
     765             :     inline const T & operator[](unsigned int i) const {return _contents[i];};
     766           0 :     inline       T & operator[](unsigned int i)       {return _contents[i];};
     767             :   private:
     768             :     T _contents[_nshift];
     769             :   };
     770             :   class Shuffle {
     771             :   public:
     772             :     unsigned int x, y;
     773             :     Point * point;
     774             :     bool operator<(const Shuffle &) const;
     775           0 :     void operator+=(unsigned int shift) {x += shift; y+= shift;};
     776             :   };
     777             :   typedef SearchTree<Shuffle>     Tree;
     778             :   typedef Tree::circulator        circulator;
     779             :   typedef Tree::const_circulator  const_circulator;
     780             :   triplet<std::auto_ptr<Tree> >  _trees;
     781             :   std::auto_ptr<MinHeap> _heap;
     782             :   std::vector<Point>     _points;
     783             :   std::stack<Point *>    _available_points;
     784             :   std::vector<Point *>   _points_under_review;
     785             :   static const unsigned int _remove_heap_entry = 1;
     786             :   static const unsigned int _review_heap_entry = 2;
     787             :   static const unsigned int _review_neighbour  = 4;
     788             :   void _add_label(Point * point, unsigned int review_flag);
     789             :   void _set_label(Point * point, unsigned int review_flag);
     790             :   void _deal_with_points_to_review();
     791             :   void _remove_from_search_tree(Point * point_to_remove);
     792             :   void _insert_into_search_tree(Point * new_point);
     793             :   void _point2shuffle(Point & , Shuffle & , unsigned int shift);
     794             :   Coord2D _left_corner;
     795             :   double _range;
     796             :   int _ID(const Point *) const;
     797             :   triplet<unsigned int> _shifts;     // absolute shifts
     798             :   triplet<unsigned int> _rel_shifts; // shifts relative to previous shift
     799             :   unsigned int _cp_search_range;
     800             : };
     801           0 : class ClosestPair2D::Point {
     802             : public:
     803             :   Coord2D coord;
     804             :   Point * neighbour;
     805             :   double  neighbour_dist2;
     806             :   triplet<circulator> circ;
     807             :   unsigned int review_flag;
     808             :   double distance2(const Point & other) const {
     809           0 :     return coord.distance2(other.coord);
     810             :   };
     811             : };
     812             : inline bool floor_ln2_less(unsigned x, unsigned y) {
     813           0 :   if (x>y) return false;
     814           0 :   return (x < (x^y)); // beware of operator precedence...
     815           0 : }
     816             : inline int ClosestPair2D::_ID(const Point * point) const {
     817           0 :   return point - &(_points[0]);
     818             : }
     819             : inline unsigned int ClosestPair2D::size() {
     820           0 :   return _points.size() - _available_points.size();
     821             : }
     822             : FJCORE_END_NAMESPACE
     823             : #endif // __FJCORE_CLOSESTPAIR2D__HH__
     824             : #include<limits>
     825             : #include<iostream>
     826             : #include<iomanip>
     827             : #include<algorithm>
     828             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
     829             : // Next line commented out, by author agreement, to avoid compiler warning.
     830             : //const unsigned int huge_unsigned = 4294967295U;
     831             : const unsigned int twopow31      = 2147483648U;
     832             : using namespace std;
     833             : void ClosestPair2D::_point2shuffle(Point & point, Shuffle & shuffle,
     834             :                                   unsigned int shift) {
     835           0 :   Coord2D renorm_point = (point.coord - _left_corner)/_range;
     836           0 :   assert(renorm_point.x >=0);
     837           0 :   assert(renorm_point.x <=1);
     838           0 :   assert(renorm_point.y >=0);
     839           0 :   assert(renorm_point.y <=1);
     840           0 :   shuffle.x = static_cast<unsigned int>(twopow31 * renorm_point.x) + shift;
     841           0 :   shuffle.y = static_cast<unsigned int>(twopow31 * renorm_point.y) + shift;
     842           0 :   shuffle.point = &point;
     843           0 : }
     844             : bool ClosestPair2D::Shuffle::operator<(const Shuffle & q) const {
     845           0 :   if (floor_ln2_less(x ^ q.x, y ^ q.y)) {
     846           0 :     return (y < q.y);
     847             :   } else {
     848           0 :     return (x < q.x);
     849             :   }
     850           0 : }
     851             : void ClosestPair2D::_initialize(const std::vector<Coord2D> & positions,
     852             :                              const Coord2D & left_corner,
     853             :                              const Coord2D & right_corner,
     854             :                              unsigned int max_size) {
     855           0 :   unsigned int n_positions = positions.size();
     856           0 :   assert(max_size >= n_positions);
     857           0 :   _points.resize(max_size);
     858           0 :   for (unsigned int i = n_positions; i < max_size; i++) {
     859           0 :     _available_points.push(&(_points[i]));
     860             :   }
     861           0 :   _left_corner = left_corner;
     862           0 :   _range       = max((right_corner.x - left_corner.x),
     863           0 :                      (right_corner.y - left_corner.y));
     864           0 :   vector<Shuffle> shuffles(n_positions);
     865           0 :   for (unsigned int i = 0; i < n_positions; i++) {
     866           0 :     _points[i].coord = positions[i];
     867           0 :     _points[i].neighbour_dist2 = numeric_limits<double>::max();
     868           0 :     _points[i].review_flag = 0;
     869           0 :     _point2shuffle(_points[i], shuffles[i], 0);
     870             :   }
     871           0 :   for (unsigned ishift = 0; ishift < _nshift; ishift++) {
     872           0 :    _shifts[ishift] = static_cast<unsigned int>(((twopow31*1.0)*ishift)/_nshift);
     873           0 :     if (ishift == 0) {_rel_shifts[ishift] = 0;}
     874           0 :     else {_rel_shifts[ishift] = _shifts[ishift] - _shifts[ishift-1];}
     875             :   }
     876           0 :   _cp_search_range = 30;
     877           0 :   _points_under_review.reserve(_nshift * _cp_search_range);
     878           0 :   for (unsigned int ishift = 0; ishift < _nshift; ishift++) {
     879           0 :     if (ishift > 0) {
     880           0 :       unsigned rel_shift = _rel_shifts[ishift];
     881           0 :       for (unsigned int i = 0; i < shuffles.size(); i++) {
     882           0 :         shuffles[i] += rel_shift; }
     883           0 :     }
     884           0 :     sort(shuffles.begin(), shuffles.end());
     885           0 :     _trees[ishift] = auto_ptr<Tree>(new Tree(shuffles, max_size));
     886           0 :     circulator circ = _trees[ishift]->somewhere(), start=circ;
     887           0 :     unsigned int CP_range = min(_cp_search_range, n_positions-1);
     888           0 :     do {
     889           0 :       Point * this_point = circ->point;
     890           0 :       this_point->circ[ishift] = circ;
     891           0 :       circulator other = circ;
     892           0 :       for (unsigned i=0; i < CP_range; i++) {
     893           0 :         ++other;
     894           0 :         double dist2 = this_point->distance2(*other->point);
     895           0 :         if (dist2 < this_point->neighbour_dist2) {
     896           0 :           this_point->neighbour_dist2 = dist2;
     897           0 :           this_point->neighbour       = other->point;
     898           0 :         }
     899             :       }
     900           0 :     } while (++circ != start);
     901           0 :   }
     902           0 :   vector<double> mindists2(n_positions);
     903           0 :   for (unsigned int i = 0; i < n_positions; i++) {
     904           0 :     mindists2[i] = _points[i].neighbour_dist2;}
     905           0 :   _heap = auto_ptr<MinHeap>(new MinHeap(mindists2, max_size));
     906           0 : }
     907             : void ClosestPair2D::closest_pair(unsigned int & ID1, unsigned int & ID2,
     908             :                                  double & distance2) const {
     909           0 :   ID1 = _heap->minloc();
     910           0 :   ID2 = _ID(_points[ID1].neighbour);
     911           0 :   distance2 = _points[ID1].neighbour_dist2;
     912           0 :   if (ID1 > ID2) std::swap(ID1,ID2);
     913           0 : }
     914             : inline void ClosestPair2D::_add_label(Point * point, unsigned int review_flag) {
     915           0 :   if (point->review_flag == 0) _points_under_review.push_back(point);
     916           0 :   point->review_flag |= review_flag;
     917           0 : }
     918             : inline void ClosestPair2D::_set_label(Point * point, unsigned int review_flag) {
     919           0 :   if (point->review_flag == 0) _points_under_review.push_back(point);
     920           0 :   point->review_flag = review_flag;
     921           0 : }
     922             : void ClosestPair2D::remove(unsigned int ID) {
     923           0 :   Point * point_to_remove = & (_points[ID]);
     924           0 :   _remove_from_search_tree(point_to_remove);
     925           0 :   _deal_with_points_to_review();
     926           0 : }
     927             : void ClosestPair2D::_remove_from_search_tree(Point * point_to_remove) {
     928           0 :   _available_points.push(point_to_remove);
     929           0 :   _set_label(point_to_remove, _remove_heap_entry);
     930           0 :   unsigned int CP_range = min(_cp_search_range, size()-1);
     931           0 :   for (unsigned int ishift = 0; ishift < _nshift; ishift++) {
     932           0 :     circulator removed_circ = point_to_remove->circ[ishift];
     933           0 :     circulator right_end = removed_circ.next();
     934           0 :     _trees[ishift]->remove(removed_circ);
     935           0 :     circulator left_end  = right_end, orig_right_end = right_end;
     936           0 :     for (unsigned int i = 0; i < CP_range; i++) {left_end--;}
     937           0 :     if (size()-1 < _cp_search_range) {
     938           0 :       left_end--; right_end--;
     939           0 :     }
     940             :     do {
     941           0 :       Point * left_point = left_end->point;
     942           0 :       if (left_point->neighbour == point_to_remove) {
     943             :         // we'll deal with it later...
     944           0 :         _add_label(left_point, _review_neighbour);
     945           0 :       } else {
     946             :         // check to see if right point has become its closest neighbour
     947           0 :         double dist2 = left_point->distance2(*right_end->point);
     948           0 :         if (dist2 < left_point->neighbour_dist2) {
     949           0 :           left_point->neighbour = right_end->point;
     950           0 :           left_point->neighbour_dist2 = dist2;
     951             :           // NB: (LESSER) REVIEW NEEDED HERE TOO...
     952           0 :           _add_label(left_point, _review_heap_entry);
     953           0 :         }
     954             :       }
     955           0 :       ++right_end;
     956           0 :     } while (++left_end != orig_right_end);
     957           0 :   } // ishift...
     958           0 : }
     959             : void ClosestPair2D::_deal_with_points_to_review() {
     960           0 :   unsigned int CP_range = min(_cp_search_range, size()-1);
     961           0 :   while(_points_under_review.size() > 0) {
     962           0 :     Point * this_point = _points_under_review.back();
     963           0 :     _points_under_review.pop_back();
     964           0 :     if (this_point->review_flag & _remove_heap_entry) {
     965           0 :       assert(!(this_point->review_flag ^ _remove_heap_entry));
     966           0 :       _heap->remove(_ID(this_point));
     967           0 :     }
     968             :     else {
     969           0 :       if (this_point->review_flag & _review_neighbour) {
     970           0 :         this_point->neighbour_dist2 = numeric_limits<double>::max();
     971             :         // among all three shifts
     972           0 :         for (unsigned int ishift = 0; ishift < _nshift; ishift++) {
     973           0 :           circulator other = this_point->circ[ishift];
     974             :           // among points within CP_range
     975           0 :           for (unsigned i=0; i < CP_range; i++) {
     976           0 :             ++other;
     977           0 :             double dist2 = this_point->distance2(*other->point);
     978           0 :             if (dist2 < this_point->neighbour_dist2) {
     979           0 :               this_point->neighbour_dist2 = dist2;
     980           0 :               this_point->neighbour       = other->point;
     981           0 :             }
     982             :           }
     983           0 :         }
     984           0 :       }
     985           0 :       _heap->update(_ID(this_point), this_point->neighbour_dist2);
     986             :     }
     987           0 :     this_point->review_flag = 0;
     988             :   }
     989           0 : }
     990             : unsigned int ClosestPair2D::insert(const Coord2D & new_coord) {
     991           0 :   assert(_available_points.size() > 0);
     992           0 :   Point * new_point = _available_points.top();
     993           0 :   _available_points.pop();
     994           0 :   new_point->coord = new_coord;
     995           0 :   _insert_into_search_tree(new_point);
     996           0 :   _deal_with_points_to_review();
     997           0 :   return _ID(new_point);
     998             : }
     999             : unsigned int ClosestPair2D::replace(unsigned int ID1, unsigned int ID2,
    1000             :                                     const Coord2D & position) {
    1001           0 :   Point * point_to_remove = & (_points[ID1]);
    1002           0 :   _remove_from_search_tree(point_to_remove);
    1003           0 :   point_to_remove = & (_points[ID2]);
    1004           0 :   _remove_from_search_tree(point_to_remove);
    1005           0 :   Point * new_point = _available_points.top();
    1006           0 :   _available_points.pop();
    1007           0 :   new_point->coord = position;
    1008           0 :   _insert_into_search_tree(new_point);
    1009           0 :   _deal_with_points_to_review();
    1010           0 :   return _ID(new_point);
    1011             : }
    1012             : void ClosestPair2D::replace_many(
    1013             :                   const std::vector<unsigned int> & IDs_to_remove,
    1014             :                   const std::vector<Coord2D> & new_positions,
    1015             :                   std::vector<unsigned int> & new_IDs) {
    1016           0 :   for (unsigned int i = 0; i < IDs_to_remove.size(); i++) {
    1017           0 :     _remove_from_search_tree(& (_points[IDs_to_remove[i]]));
    1018             :   }
    1019           0 :   new_IDs.resize(0);
    1020           0 :   for (unsigned int i = 0; i < new_positions.size(); i++) {
    1021           0 :     Point * new_point = _available_points.top();
    1022           0 :     _available_points.pop();
    1023           0 :     new_point->coord = new_positions[i];
    1024           0 :     _insert_into_search_tree(new_point);
    1025           0 :     new_IDs.push_back(_ID(new_point));
    1026             :   }
    1027           0 :   _deal_with_points_to_review();
    1028           0 : }
    1029             : void ClosestPair2D::_insert_into_search_tree(Point * new_point) {
    1030           0 :   _set_label(new_point, _review_heap_entry);
    1031           0 :   new_point->neighbour_dist2 = numeric_limits<double>::max();
    1032           0 :   unsigned int CP_range = min(_cp_search_range, size()-1);
    1033           0 :   for (unsigned ishift = 0; ishift < _nshift; ishift++) {
    1034           0 :     Shuffle new_shuffle;
    1035           0 :     _point2shuffle(*new_point, new_shuffle, _shifts[ishift]);
    1036           0 :     circulator new_circ = _trees[ishift]->insert(new_shuffle);
    1037           0 :     new_point->circ[ishift] = new_circ;
    1038           0 :     circulator right_edge = new_circ; right_edge++;
    1039           0 :     circulator left_edge  = new_circ;
    1040           0 :     for (unsigned int i = 0; i < CP_range; i++) {left_edge--;}
    1041           0 :     do {
    1042           0 :       Point * left_point  = left_edge->point;
    1043           0 :       Point * right_point = right_edge->point;
    1044           0 :       double new_dist2 = left_point->distance2(*new_point);
    1045           0 :       if (new_dist2 < left_point->neighbour_dist2) {
    1046           0 :         left_point->neighbour_dist2 = new_dist2;
    1047           0 :         left_point->neighbour       = new_point;
    1048           0 :         _add_label(left_point, _review_heap_entry);
    1049           0 :       }
    1050           0 :       new_dist2 = new_point->distance2(*right_point);
    1051           0 :       if (new_dist2 < new_point->neighbour_dist2) {
    1052           0 :         new_point->neighbour_dist2 = new_dist2;
    1053           0 :         new_point->neighbour = right_point;
    1054           0 :       }
    1055           0 :       if (left_point->neighbour == right_point) {
    1056           0 :         _add_label(left_point, _review_neighbour);
    1057           0 :       }
    1058           0 :       right_edge++;
    1059           0 :     } while (++left_edge != new_circ);
    1060           0 :   }
    1061           0 : }
    1062             : FJCORE_END_NAMESPACE
    1063             : #include<iostream>
    1064             : #include<sstream>
    1065             : #include<fstream>
    1066             : #include<cmath>
    1067             : #include<cstdlib>
    1068             : #include<cassert>
    1069             : #include<string>
    1070             : #include<set>
    1071             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    1072             : using namespace std;
    1073             : std::ostream * ClusterSequence::_fastjet_banner_ostr = &cout;
    1074           0 : ClusterSequence::~ClusterSequence () {
    1075           0 :   if (_structure_shared_ptr()){
    1076           0 :     ClusterSequenceStructure* csi = dynamic_cast<ClusterSequenceStructure*>(_structure_shared_ptr());
    1077           0 :     assert(csi != NULL);
    1078           0 :     csi->set_associated_cs(NULL);
    1079           0 :     if (_deletes_self_when_unused) {
    1080           0 :       _structure_shared_ptr.set_count(_structure_shared_ptr.use_count()
    1081           0 :                                         + _structure_use_count_after_construction);
    1082             :     }
    1083           0 :   }
    1084           0 : }
    1085             : void ClusterSequence::signal_imminent_self_deletion() const {
    1086           0 :   assert(_deletes_self_when_unused);
    1087           0 :   _deletes_self_when_unused = false;
    1088           0 : }
    1089             : void ClusterSequence::_initialise_and_run (
    1090             :                                   const JetDefinition & jet_def_in,
    1091             :                                   const bool & writeout_combinations) {
    1092           0 :   _decant_options(jet_def_in, writeout_combinations);
    1093           0 :   _initialise_and_run_no_decant();
    1094           0 : }
    1095             : void ClusterSequence::_initialise_and_run_no_decant () {
    1096           0 :   _fill_initial_history();
    1097           0 :   if (n_particles() == 0) return;
    1098           0 :   if (_jet_algorithm == plugin_algorithm) {
    1099           0 :     _plugin_activated = true;
    1100           0 :     _jet_def.plugin()->run_clustering( (*this) );
    1101           0 :     _plugin_activated = false;
    1102           0 :     _update_structure_use_count();
    1103           0 :     return;
    1104           0 :   } else if (_jet_algorithm == ee_kt_algorithm ||
    1105           0 :              _jet_algorithm == ee_genkt_algorithm) {
    1106           0 :     _strategy = N2Plain;
    1107           0 :     if (_jet_algorithm == ee_kt_algorithm) {
    1108           0 :       assert(_Rparam > 2.0);
    1109           0 :       _invR2 = 1.0;
    1110           0 :     } else {
    1111           0 :       if (_Rparam > pi) {
    1112             :         // choose a value that ensures that back-to-back particles will
    1113             :         // always recombine
    1114             :         //_R2 = 4.0000000000001;
    1115           0 :         _R2 = 2 * ( 3.0 + cos(_Rparam) );
    1116           0 :       } else {
    1117           0 :         _R2    = 2 * ( 1.0 - cos(_Rparam) );
    1118             :       }
    1119           0 :       _invR2 = 1.0/_R2;
    1120             :     }
    1121           0 :     _simple_N2_cluster_EEBriefJet();
    1122           0 :     return;
    1123           0 :   } else if (_jet_algorithm == undefined_jet_algorithm) {
    1124           0 :     throw Error("A ClusterSequence cannot be created with an uninitialised JetDefinition");
    1125             :   }
    1126           0 :   if (_strategy == Best) {
    1127           0 :     int N = _jets.size();
    1128           0 :     if (min(1.0,max(0.1,_Rparam)*3.3)*N <= 30) {
    1129           0 :       _strategy = N2Plain;
    1130           0 :     } else if (N > 6200/pow(_Rparam,2.0) && _jet_def.jet_algorithm() == cambridge_algorithm) {
    1131           0 :       _strategy = NlnNCam;
    1132             : #ifndef __FJCORE_DROP_CGAL
    1133             :     } else if ((N > 16000/pow(_Rparam,1.15) && _jet_def.jet_algorithm() != antikt_algorithm)
    1134             :                || N > 35000/pow(_Rparam,1.15)) {
    1135             :       _strategy = NlnN;
    1136             : #endif  // __FJCORE_DROP_CGAL
    1137           0 :     } else if (N <= 450) {
    1138           0 :       _strategy = N2Tiled;
    1139           0 :     } else {
    1140           0 :       _strategy = N2MinHeapTiled;
    1141             :     }
    1142           0 :   }
    1143           0 :   if (_Rparam >= twopi) {
    1144           0 :     if (   _strategy == NlnN
    1145           0 :         || _strategy == NlnN3pi
    1146           0 :         || _strategy == NlnNCam
    1147           0 :         || _strategy == NlnNCam2pi2R
    1148           0 :         || _strategy == NlnNCam4pi) {
    1149             : #ifdef __FJCORE_DROP_CGAL
    1150           0 :       _strategy = N2MinHeapTiled;
    1151             : #else
    1152             :       _strategy = NlnN4pi;
    1153             : #endif
    1154           0 :     }
    1155           0 :     if (_jet_def.strategy() != Best && _strategy != _jet_def.strategy()) {
    1156           0 :       ostringstream oss;
    1157           0 :       oss << "Cluster strategy " << strategy_string(_jet_def.strategy())
    1158           0 :           << " automatically changed to " << strategy_string()
    1159           0 :           << " because the former is not supported for R = " << _Rparam
    1160           0 :           << " >= 2pi";
    1161           0 :       _changed_strategy_warning.warn(oss.str());
    1162           0 :     }
    1163             :   }
    1164           0 :   if (_strategy == N2Plain) {
    1165           0 :     this->_simple_N2_cluster_BriefJet();
    1166           0 :   } else if (_strategy == N2Tiled) {
    1167           0 :     this->_faster_tiled_N2_cluster();
    1168           0 :   } else if (_strategy == N2MinHeapTiled) {
    1169           0 :     this->_minheap_faster_tiled_N2_cluster();
    1170           0 :   } else if (_strategy == NlnN) {
    1171           0 :     this->_delaunay_cluster();
    1172           0 :   } else if (_strategy == NlnNCam) {
    1173           0 :     this->_CP2DChan_cluster_2piMultD();
    1174           0 :   } else if (_strategy == NlnN3pi || _strategy == NlnN4pi ) {
    1175           0 :     this->_delaunay_cluster();
    1176           0 :   } else if (_strategy ==  N3Dumb ) {
    1177           0 :     this->_really_dumb_cluster();
    1178           0 :   } else if (_strategy == N2PoorTiled) {
    1179           0 :     this->_tiled_N2_cluster();
    1180           0 :   } else if (_strategy == NlnNCam4pi) {
    1181           0 :     this->_CP2DChan_cluster();
    1182           0 :   } else if (_strategy == NlnNCam2pi2R) {
    1183           0 :     this->_CP2DChan_cluster_2pi2R();
    1184             :   } else {
    1185           0 :     ostringstream err;
    1186           0 :     err << "Unrecognised value for strategy: "<<_strategy;
    1187           0 :     throw Error(err.str());
    1188           0 :   }
    1189           0 : }
    1190             : bool ClusterSequence::_first_time = true;
    1191             : int ClusterSequence::_n_exclusive_warnings = 0;
    1192             : string fastjet_version_string() {
    1193           0 :   return "FastJet version "+string(fastjet_version)+" [fjcore]";
    1194           0 : }
    1195             : void ClusterSequence::print_banner() {
    1196           0 :   if (!_first_time) {return;}
    1197           0 :   _first_time = false;
    1198           0 :   ostream * ostr = _fastjet_banner_ostr;
    1199           0 :   if (!ostr) return;
    1200           0 :   (*ostr) << "#--------------------------------------------------------------------------\n";
    1201           0 :   (*ostr) << "#                     FastJet release " << fastjet_version << " [fjcore]" << endl;
    1202           0 :   (*ostr) << "#                 M. Cacciari, G.P. Salam and G. Soyez                  \n";
    1203           0 :   (*ostr) << "#     A software package for jet finding and analysis at colliders      \n";
    1204           0 :   (*ostr) << "#                           http://fastjet.fr                           \n";
    1205           0 :   (*ostr) << "#                                                                            \n";
    1206           0 :   (*ostr) << "# Please cite EPJC72(2012)1896 [arXiv:1111.6097] if you use this package\n";
    1207           0 :   (*ostr) << "# for scientific work and optionally PLB641(2006)57 [hep-ph/0512210].   \n";
    1208           0 :   (*ostr) << "#                                                                       \n";
    1209           0 :   (*ostr) << "# FastJet is provided without warranty under the terms of the GNU GPLv2.\n";
    1210           0 :   (*ostr) << "# It uses T. Chan's closest pair algorithm, S. Fortune's Voronoi code";
    1211             : #ifndef __FJCORE_DROP_CGAL
    1212             :   (*ostr) << ",\n# CGAL ";
    1213             : #else
    1214           0 :   (*ostr) << "\n# ";
    1215             : #endif  // __FJCORE_DROP_CGAL
    1216           0 :   (*ostr) << "and 3rd party plugin jet algorithms. See COPYING file for details.\n";
    1217           0 :   (*ostr) << "#--------------------------------------------------------------------------\n";
    1218           0 :   ostr->flush();
    1219           0 : }
    1220             : void ClusterSequence::_decant_options(const JetDefinition & jet_def_in,
    1221             :                                       const bool & writeout_combinations) {
    1222           0 :   _jet_def = jet_def_in;
    1223           0 :   _writeout_combinations = writeout_combinations;
    1224           0 :   _structure_shared_ptr.reset(new ClusterSequenceStructure(this));
    1225           0 :   _decant_options_partial();
    1226           0 : }
    1227             : void ClusterSequence::_decant_options_partial() {
    1228           0 :   print_banner();
    1229           0 :   _jet_algorithm = _jet_def.jet_algorithm();
    1230           0 :   _Rparam = _jet_def.R();  _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
    1231           0 :   _strategy = _jet_def.strategy();
    1232           0 :   _plugin_activated = false;
    1233           0 :   _update_structure_use_count(); // make sure it's correct already here
    1234           0 : }
    1235             : void ClusterSequence::_fill_initial_history () {
    1236           0 :   _jets.reserve(_jets.size()*2);
    1237           0 :   _history.reserve(_jets.size()*2);
    1238           0 :   _Qtot = 0;
    1239           0 :   for (int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
    1240           0 :     history_element element;
    1241           0 :     element.parent1 = InexistentParent;
    1242           0 :     element.parent2 = InexistentParent;
    1243           0 :     element.child   = Invalid;
    1244           0 :     element.jetp_index = i;
    1245           0 :     element.dij     = 0.0;
    1246           0 :     element.max_dij_so_far = 0.0;
    1247           0 :     _history.push_back(element);
    1248           0 :     _jet_def.recombiner()->preprocess(_jets[i]);
    1249           0 :     _jets[i].set_cluster_hist_index(i);
    1250           0 :     _set_structure_shared_ptr(_jets[i]);
    1251           0 :     _Qtot += _jets[i].E();
    1252           0 :   }
    1253           0 :   _initial_n = _jets.size();
    1254           0 :   _deletes_self_when_unused = false;
    1255           0 : }
    1256             : string ClusterSequence::strategy_string (Strategy strategy_in)  const {
    1257           0 :   string strategy;
    1258           0 :   switch(strategy_in) {
    1259             :   case NlnN:
    1260           0 :     strategy = "NlnN"; break;
    1261             :   case NlnN3pi:
    1262           0 :     strategy = "NlnN3pi"; break;
    1263             :   case NlnN4pi:
    1264           0 :     strategy = "NlnN4pi"; break;
    1265             :   case N2Plain:
    1266           0 :     strategy = "N2Plain"; break;
    1267             :   case N2Tiled:
    1268           0 :     strategy = "N2Tiled"; break;
    1269             :   case N2MinHeapTiled:
    1270           0 :     strategy = "N2MinHeapTiled"; break;
    1271             :   case N2PoorTiled:
    1272           0 :     strategy = "N2PoorTiled"; break;
    1273             :   case N3Dumb:
    1274           0 :     strategy = "N3Dumb"; break;
    1275             :   case NlnNCam4pi:
    1276           0 :     strategy = "NlnNCam4pi"; break;
    1277             :   case NlnNCam2pi2R:
    1278           0 :     strategy = "NlnNCam2pi2R"; break;
    1279             :   case NlnNCam:
    1280           0 :     strategy = "NlnNCam"; break; // 2piMultD
    1281             :   case plugin_strategy:
    1282           0 :     strategy = "plugin strategy"; break;
    1283             :   default:
    1284           0 :     strategy = "Unrecognized";
    1285             :   }
    1286             :   return strategy;
    1287           0 : }
    1288             : double ClusterSequence::jet_scale_for_algorithm(
    1289             :                                   const PseudoJet & jet) const {
    1290           0 :   if (_jet_algorithm == kt_algorithm)             {return jet.kt2();}
    1291           0 :   else if (_jet_algorithm == cambridge_algorithm) {return 1.0;}
    1292           0 :   else if (_jet_algorithm == antikt_algorithm) {
    1293           0 :     double kt2=jet.kt2();
    1294           0 :     return kt2 > 1e-300 ? 1.0/kt2 : 1e300;
    1295           0 :   } else if (_jet_algorithm == genkt_algorithm) {
    1296           0 :     double kt2 = jet.kt2();
    1297           0 :     double p   = jet_def().extra_param();
    1298           0 :     if (p <= 0 && kt2 < 1e-300) kt2 = 1e-300; // dodgy safety check
    1299           0 :     return pow(kt2, p);
    1300           0 :   } else if (_jet_algorithm == cambridge_for_passive_algorithm) {
    1301           0 :     double kt2 = jet.kt2();
    1302           0 :     double lim = _jet_def.extra_param();
    1303           0 :     if (kt2 < lim*lim && kt2 != 0.0) {
    1304           0 :       return 1.0/kt2;
    1305           0 :     } else {return 1.0;}
    1306           0 :   } else {throw Error("Unrecognised jet algorithm");}
    1307           0 : }
    1308             : void ClusterSequence::transfer_from_sequence(const ClusterSequence & from_seq,
    1309             :                                              const FunctionOfPseudoJet<PseudoJet> * action_on_jets){
    1310           0 :   if (will_delete_self_when_unused())
    1311           0 :     throw(Error("cannot use CS::transfer_from_sequence after a call to delete_self_when_unused()"));
    1312           0 :   _jet_def                 = from_seq._jet_def                ;
    1313           0 :   _writeout_combinations   = from_seq._writeout_combinations  ;
    1314           0 :   _initial_n               = from_seq._initial_n              ;
    1315           0 :   _Rparam                  = from_seq._Rparam                 ;
    1316           0 :   _R2                      = from_seq._R2                     ;
    1317           0 :   _invR2                   = from_seq._invR2                  ;
    1318           0 :   _strategy                = from_seq._strategy               ;
    1319           0 :   _jet_algorithm           = from_seq._jet_algorithm          ;
    1320           0 :   _plugin_activated        = from_seq._plugin_activated       ;
    1321           0 :   if (action_on_jets)
    1322           0 :     _jets     = (*action_on_jets)(from_seq._jets);
    1323             :   else
    1324           0 :     _jets     = from_seq._jets;
    1325           0 :   _history  = from_seq._history;
    1326           0 :   _extras   = from_seq._extras;
    1327           0 :   if (_structure_shared_ptr()) {
    1328           0 :     if (_deletes_self_when_unused) throw Error("transfer_from_sequence cannot be used for a cluster sequence that deletes self when unused");
    1329           0 :     ClusterSequenceStructure* csi = dynamic_cast<ClusterSequenceStructure*>(_structure_shared_ptr());
    1330           0 :     assert(csi != NULL);
    1331           0 :     csi->set_associated_cs(NULL);
    1332           0 :   }
    1333           0 :   _structure_shared_ptr.reset(new ClusterSequenceStructure(this));
    1334           0 :   _update_structure_use_count();
    1335           0 :   for (unsigned int i=0; i<_jets.size(); i++){
    1336           0 :     _jets[i].set_cluster_hist_index(from_seq._jets[i].cluster_hist_index());
    1337           0 :     _set_structure_shared_ptr(_jets[i]);
    1338             :   }
    1339           0 : }
    1340             : void ClusterSequence::plugin_record_ij_recombination(
    1341             :            int jet_i, int jet_j, double dij,
    1342             :            const PseudoJet & newjet, int & newjet_k) {
    1343           0 :   plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
    1344           0 :   int tmp_index = _jets[newjet_k].cluster_hist_index();
    1345           0 :   _jets[newjet_k] = newjet;
    1346           0 :   _jets[newjet_k].set_cluster_hist_index(tmp_index);
    1347           0 :   _set_structure_shared_ptr(_jets[newjet_k]);
    1348           0 : }
    1349             : vector<PseudoJet> ClusterSequence::inclusive_jets (const double & ptmin) const{
    1350           0 :   double dcut = ptmin*ptmin;
    1351           0 :   int i = _history.size() - 1; // last jet
    1352           0 :   vector<PseudoJet> jets_local;
    1353           0 :   if (_jet_algorithm == kt_algorithm) {
    1354           0 :     while (i >= 0) {
    1355           0 :       if (_history[i].max_dij_so_far < dcut) {break;}
    1356           0 :       if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
    1357             :         // for beam jets
    1358           0 :         int parent1 = _history[i].parent1;
    1359           0 :         jets_local.push_back(_jets[_history[parent1].jetp_index]);}
    1360           0 :       i--;
    1361             :     }
    1362           0 :   } else if (_jet_algorithm == cambridge_algorithm) {
    1363           0 :     while (i >= 0) {
    1364           0 :       if (_history[i].parent2 != BeamJet) {break;}
    1365           0 :       int parent1 = _history[i].parent1;
    1366           0 :       const PseudoJet & jet = _jets[_history[parent1].jetp_index];
    1367           0 :       if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
    1368           0 :       i--;
    1369             :     }
    1370           0 :   } else if (_jet_algorithm == plugin_algorithm
    1371           0 :              || _jet_algorithm == ee_kt_algorithm
    1372           0 :              || _jet_algorithm == antikt_algorithm
    1373           0 :              || _jet_algorithm == genkt_algorithm
    1374           0 :              || _jet_algorithm == ee_genkt_algorithm
    1375           0 :              || _jet_algorithm == cambridge_for_passive_algorithm) {
    1376           0 :     while (i >= 0) {
    1377           0 :       if (_history[i].parent2 == BeamJet) {
    1378           0 :         int parent1 = _history[i].parent1;
    1379           0 :         const PseudoJet & jet = _jets[_history[parent1].jetp_index];
    1380           0 :         if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
    1381           0 :       }
    1382           0 :       i--;
    1383             :     }
    1384           0 :   } else {throw Error("cs::inclusive_jets(...): Unrecognized jet algorithm");}
    1385             :   return jets_local;
    1386           0 : }
    1387             : int ClusterSequence::n_exclusive_jets (const double & dcut) const {
    1388           0 :   int i = _history.size() - 1; // last jet
    1389           0 :   while (i >= 0) {
    1390           0 :     if (_history[i].max_dij_so_far <= dcut) {break;}
    1391           0 :     i--;
    1392             :   }
    1393           0 :   int stop_point = i + 1;
    1394           0 :   int njets = 2*_initial_n - stop_point;
    1395           0 :   return njets;
    1396             : }
    1397             : vector<PseudoJet> ClusterSequence::exclusive_jets (const double & dcut) const {
    1398           0 :   int njets = n_exclusive_jets(dcut);
    1399           0 :   return exclusive_jets(njets);
    1400           0 : }
    1401             : vector<PseudoJet> ClusterSequence::exclusive_jets (const int & njets) const {
    1402           0 :   if (njets > _initial_n) {
    1403           0 :     ostringstream err;
    1404           0 :     err << "Requested " << njets << " exclusive jets, but there were only "
    1405           0 :         << _initial_n << " particles in the event";
    1406           0 :     throw Error(err.str());
    1407           0 :   }
    1408           0 :   return exclusive_jets_up_to(njets);
    1409           0 : }
    1410             : vector<PseudoJet> ClusterSequence::exclusive_jets_up_to (const int & njets) const {
    1411           0 :   if (( _jet_def.jet_algorithm() != kt_algorithm) &&
    1412           0 :       ( _jet_def.jet_algorithm() != cambridge_algorithm) &&
    1413           0 :       ( _jet_def.jet_algorithm() != ee_kt_algorithm) &&
    1414           0 :       (((_jet_def.jet_algorithm() != genkt_algorithm) &&
    1415           0 :         (_jet_def.jet_algorithm() != ee_genkt_algorithm)) ||
    1416           0 :        (_jet_def.extra_param() <0)) &&
    1417           0 :       ((_jet_def.jet_algorithm() != plugin_algorithm) ||
    1418           0 :        (!_jet_def.plugin()->exclusive_sequence_meaningful())) &&
    1419           0 :       (_n_exclusive_warnings < 5)) {
    1420           0 :     _n_exclusive_warnings++;
    1421           0 :     cerr << "FastJet WARNING: dcut and exclusive jets for jet-finders other than kt should be interpreted with care." << endl;
    1422           0 :   }
    1423           0 :   int stop_point = 2*_initial_n - njets;
    1424           0 :   if (stop_point < _initial_n) stop_point = _initial_n;
    1425           0 :   if (2*_initial_n != static_cast<int>(_history.size())) {
    1426           0 :     ostringstream err;
    1427           0 :     err << "2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
    1428           0 :     throw Error(err.str());
    1429           0 :   }
    1430           0 :   vector<PseudoJet> jets_local;
    1431           0 :   for (unsigned int i = stop_point; i < _history.size(); i++) {
    1432           0 :     int parent1 = _history[i].parent1;
    1433           0 :     if (parent1 < stop_point) {
    1434           0 :       jets_local.push_back(_jets[_history[parent1].jetp_index]);
    1435             :     }
    1436           0 :     int parent2 = _history[i].parent2;
    1437           0 :     if (parent2 < stop_point && parent2 > 0) {
    1438           0 :       jets_local.push_back(_jets[_history[parent2].jetp_index]);
    1439             :     }
    1440             :   }
    1441           0 :   if (int(jets_local.size()) != min(_initial_n, njets)) {
    1442           0 :     ostringstream err;
    1443           0 :     err << "ClusterSequence::exclusive_jets: size of returned vector ("
    1444           0 :          <<jets_local.size()<<") does not coincide with requested number of jets ("
    1445           0 :          <<njets<<")";
    1446           0 :     throw Error(err.str());
    1447           0 :   }
    1448             :   return jets_local;
    1449           0 : }
    1450             : double ClusterSequence::exclusive_dmerge (const int & njets) const {
    1451           0 :   assert(njets >= 0);
    1452           0 :   if (njets >= _initial_n) {return 0.0;}
    1453           0 :   return _history[2*_initial_n-njets-1].dij;
    1454           0 : }
    1455             : double ClusterSequence::exclusive_dmerge_max (const int & njets) const {
    1456           0 :   assert(njets >= 0);
    1457           0 :   if (njets >= _initial_n) {return 0.0;}
    1458           0 :   return _history[2*_initial_n-njets-1].max_dij_so_far;
    1459           0 : }
    1460             : std::vector<PseudoJet> ClusterSequence::exclusive_subjets
    1461             :    (const PseudoJet & jet, const double & dcut) const {
    1462           0 :   set<const history_element*> subhist;
    1463           0 :   get_subhist_set(subhist, jet, dcut, 0);
    1464           0 :   vector<PseudoJet> subjets;
    1465           0 :   subjets.reserve(subhist.size());
    1466           0 :   for (set<const history_element*>::iterator elem = subhist.begin();
    1467           0 :        elem != subhist.end(); elem++) {
    1468           0 :     subjets.push_back(_jets[(*elem)->jetp_index]);
    1469             :   }
    1470             :   return subjets;
    1471           0 : }
    1472             : int ClusterSequence::n_exclusive_subjets(const PseudoJet & jet,
    1473             :                         const double & dcut) const {
    1474           0 :   set<const history_element*> subhist;
    1475           0 :   get_subhist_set(subhist, jet, dcut, 0);
    1476           0 :   return subhist.size();
    1477           0 : }
    1478             : std::vector<PseudoJet> ClusterSequence::exclusive_subjets
    1479             :    (const PseudoJet & jet, int nsub) const {
    1480           0 :   vector<PseudoJet> subjets = exclusive_subjets_up_to(jet, nsub);
    1481           0 :   if (int(subjets.size()) < nsub) {
    1482           0 :     ostringstream err;
    1483           0 :     err << "Requested " << nsub << " exclusive subjets, but there were only "
    1484           0 :         << subjets.size() << " particles in the jet";
    1485           0 :     throw Error(err.str());
    1486           0 :   }
    1487             :   return subjets;
    1488           0 : }
    1489             : std::vector<PseudoJet> ClusterSequence::exclusive_subjets_up_to
    1490             :    (const PseudoJet & jet, int nsub) const {
    1491           0 :   set<const history_element*> subhist;
    1492           0 :   vector<PseudoJet> subjets;
    1493           0 :   if (nsub <  0) throw Error("Requested a negative number of subjets. This is nonsensical.");
    1494           0 :   if (nsub == 0) return subjets;
    1495           0 :   get_subhist_set(subhist, jet, -1.0, nsub);
    1496           0 :   subjets.reserve(subhist.size());
    1497           0 :   for (set<const history_element*>::iterator elem = subhist.begin();
    1498           0 :        elem != subhist.end(); elem++) {
    1499           0 :     subjets.push_back(_jets[(*elem)->jetp_index]);
    1500             :   }
    1501           0 :   return subjets;
    1502           0 : }
    1503             : double ClusterSequence::exclusive_subdmerge(const PseudoJet & jet, int nsub) const {
    1504           0 :   set<const history_element*> subhist;
    1505           0 :   get_subhist_set(subhist, jet, -1.0, nsub);
    1506           0 :   set<const history_element*>::iterator highest = subhist.end();
    1507           0 :   highest--;
    1508           0 :   return (*highest)->dij;
    1509           0 : }
    1510             : double ClusterSequence::exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const {
    1511           0 :   set<const history_element*> subhist;
    1512           0 :   get_subhist_set(subhist, jet, -1.0, nsub);
    1513           0 :   set<const history_element*>::iterator highest = subhist.end();
    1514           0 :   highest--;
    1515           0 :   return (*highest)->max_dij_so_far;
    1516           0 : }
    1517             : void ClusterSequence::get_subhist_set(set<const history_element*> & subhist,
    1518             :                                      const  PseudoJet & jet,
    1519             :                                      double dcut, int maxjet) const {
    1520           0 :   assert(contains(jet));
    1521           0 :   subhist.clear();
    1522           0 :   subhist.insert(&(_history[jet.cluster_hist_index()]));
    1523             :   int njet = 1;
    1524           0 :   while (true) {
    1525           0 :     set<const history_element*>::iterator highest = subhist.end();
    1526           0 :     assert (highest != subhist.begin());
    1527           0 :     highest--;
    1528           0 :     const history_element* elem = *highest;
    1529           0 :     if (njet == maxjet) break;
    1530           0 :     if (elem->parent1 < 0)            break;
    1531           0 :     if (elem->max_dij_so_far <= dcut) break;
    1532           0 :     subhist.erase(highest);
    1533           0 :     subhist.insert(&(_history[elem->parent1]));
    1534           0 :     subhist.insert(&(_history[elem->parent2]));
    1535           0 :     njet++;
    1536           0 :   }
    1537           0 : }
    1538             : bool ClusterSequence::object_in_jet(const PseudoJet & object,
    1539             :                                     const PseudoJet & jet) const {
    1540           0 :   assert(contains(object) && contains(jet));
    1541             :   const PseudoJet * this_object = &object;
    1542           0 :   const PseudoJet * childp;
    1543           0 :   while(true) {
    1544           0 :     if (this_object->cluster_hist_index() == jet.cluster_hist_index()) {
    1545           0 :       return true;
    1546           0 :     } else if (has_child(*this_object, childp)) {
    1547           0 :       this_object = childp;
    1548             :     } else {
    1549           0 :       return false;
    1550             :     }
    1551             :   }
    1552           0 : }
    1553             : bool ClusterSequence::has_parents(const PseudoJet & jet, PseudoJet & parent1,
    1554             :                               PseudoJet & parent2) const {
    1555           0 :   const history_element & hist = _history[jet.cluster_hist_index()];
    1556           0 :   assert ((hist.parent1 >= 0 && hist.parent2 >= 0) ||
    1557             :           (hist.parent1 < 0 && hist.parent2 < 0));
    1558           0 :   if (hist.parent1 < 0) {
    1559           0 :     parent1 = PseudoJet(0.0,0.0,0.0,0.0);
    1560           0 :     parent2 = parent1;
    1561           0 :     return false;
    1562             :   } else {
    1563           0 :     parent1 = _jets[_history[hist.parent1].jetp_index];
    1564           0 :     parent2 = _jets[_history[hist.parent2].jetp_index];
    1565           0 :     if (parent1.perp2() < parent2.perp2()) std::swap(parent1,parent2);
    1566           0 :     return true;
    1567             :   }
    1568           0 : }
    1569             : bool ClusterSequence::has_child(const PseudoJet & jet, PseudoJet & child) const {
    1570           0 :   const PseudoJet * childp;
    1571           0 :   bool res = has_child(jet, childp);
    1572           0 :   if (res) {
    1573           0 :     child = *childp;
    1574           0 :     return true;
    1575             :   } else {
    1576           0 :     child = PseudoJet(0.0,0.0,0.0,0.0);
    1577           0 :     return false;
    1578             :   }
    1579           0 : }
    1580             : bool ClusterSequence::has_child(const PseudoJet & jet, const PseudoJet * & childp) const {
    1581           0 :   const history_element & hist = _history[jet.cluster_hist_index()];
    1582           0 :   if (hist.child >= 0 && _history[hist.child].jetp_index >= 0) {
    1583           0 :     childp = &(_jets[_history[hist.child].jetp_index]);
    1584           0 :     return true;
    1585             :   } else {
    1586           0 :     childp = NULL;
    1587           0 :     return false;
    1588             :   }
    1589           0 : }
    1590             : bool ClusterSequence::has_partner(const PseudoJet & jet,
    1591             :                               PseudoJet & partner) const {
    1592           0 :   const history_element & hist = _history[jet.cluster_hist_index()];
    1593           0 :   if (hist.child >= 0 && _history[hist.child].parent2 >= 0) {
    1594           0 :     const history_element & child_hist = _history[hist.child];
    1595           0 :     if (child_hist.parent1 == jet.cluster_hist_index()) {
    1596           0 :       partner = _jets[_history[child_hist.parent2].jetp_index];
    1597           0 :     } else {
    1598           0 :       partner = _jets[_history[child_hist.parent1].jetp_index];
    1599             :     }
    1600             :     return true;
    1601             :   } else {
    1602           0 :     partner = PseudoJet(0.0,0.0,0.0,0.0);
    1603           0 :     return false;
    1604             :   }
    1605           0 : }
    1606             : vector<PseudoJet> ClusterSequence::constituents (const PseudoJet & jet) const {
    1607           0 :   vector<PseudoJet> subjets;
    1608           0 :   add_constituents(jet, subjets);
    1609             :   return subjets;
    1610           0 : }
    1611             : void ClusterSequence::print_jets_for_root(const std::vector<PseudoJet> & jets_in,
    1612             :                                           ostream & ostr) const {
    1613           0 :   for (unsigned i = 0; i < jets_in.size(); i++) {
    1614           0 :     ostr << i  << " "
    1615           0 :          << jets_in[i].px() << " "
    1616           0 :          << jets_in[i].py() << " "
    1617           0 :          << jets_in[i].pz() << " "
    1618           0 :          << jets_in[i].E() << endl;
    1619           0 :     vector<PseudoJet> cst = constituents(jets_in[i]);
    1620           0 :     for (unsigned j = 0; j < cst.size() ; j++) {
    1621           0 :       ostr << " " << j << " "
    1622           0 :            << cst[j].rap() << " "
    1623           0 :            << cst[j].phi() << " "
    1624           0 :            << cst[j].perp() << endl;
    1625             :     }
    1626           0 :     ostr << "#END" << endl;
    1627           0 :   }
    1628           0 : }
    1629             : void ClusterSequence::print_jets_for_root(const std::vector<PseudoJet> & jets_in,
    1630             :                                           const std::string & filename,
    1631             :                                           const std::string & comment ) const {
    1632           0 :   std::ofstream ostr(filename.c_str());
    1633           0 :   if (comment != "") ostr << "# " << comment << endl;
    1634           0 :   print_jets_for_root(jets_in, ostr);
    1635           0 : }
    1636             : vector<int> ClusterSequence::particle_jet_indices(
    1637             :                         const vector<PseudoJet> & jets_in) const {
    1638           0 :   vector<int> indices(n_particles());
    1639           0 :   for (unsigned ipart = 0; ipart < n_particles(); ipart++)
    1640           0 :     indices[ipart] = -1;
    1641           0 :   for (unsigned ijet = 0; ijet < jets_in.size(); ijet++) {
    1642           0 :     vector<PseudoJet> jet_constituents(constituents(jets_in[ijet]));
    1643           0 :     for (unsigned ip = 0; ip < jet_constituents.size(); ip++) {
    1644           0 :       unsigned iclust = jet_constituents[ip].cluster_hist_index();
    1645           0 :       unsigned ipart = history()[iclust].jetp_index;
    1646           0 :       indices[ipart] = ijet;
    1647             :     }
    1648           0 :   }
    1649             :   return indices;
    1650           0 : }
    1651             : void ClusterSequence::add_constituents (
    1652             :            const PseudoJet & jet, vector<PseudoJet> & subjet_vector) const {
    1653           0 :   int i = jet.cluster_hist_index();
    1654           0 :   int parent1 = _history[i].parent1;
    1655           0 :   int parent2 = _history[i].parent2;
    1656           0 :   if (parent1 == InexistentParent) {
    1657           0 :     subjet_vector.push_back(_jets[i]);
    1658           0 :     return;
    1659             :   }
    1660           0 :   add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
    1661           0 :   if (parent2 != BeamJet) {
    1662           0 :     add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
    1663           0 :   }
    1664           0 : }
    1665             : void ClusterSequence::_add_step_to_history (
    1666             :                const int & step_number, const int & parent1,
    1667             :                const int & parent2, const int & jetp_index,
    1668             :                const double & dij) {
    1669           0 :   history_element element;
    1670           0 :   element.parent1 = parent1;
    1671           0 :   element.parent2 = parent2;
    1672           0 :   element.jetp_index = jetp_index;
    1673           0 :   element.child = Invalid;
    1674           0 :   element.dij   = dij;
    1675           0 :   element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
    1676           0 :   _history.push_back(element);
    1677           0 :   int local_step = _history.size()-1;
    1678           0 :   assert(local_step == step_number);
    1679           0 :   assert(parent1 >= 0);
    1680           0 :   _history[parent1].child = local_step;
    1681           0 :   if (parent2 >= 0) {_history[parent2].child = local_step;}
    1682           0 :   if (jetp_index != Invalid) {
    1683           0 :     assert(jetp_index >= 0);
    1684           0 :     _jets[jetp_index].set_cluster_hist_index(local_step);
    1685           0 :     _set_structure_shared_ptr(_jets[jetp_index]);
    1686           0 :   }
    1687           0 :   if (_writeout_combinations) {
    1688           0 :     cout << local_step << ": "
    1689           0 :          << parent1 << " with " << parent2
    1690           0 :          << "; y = "<< dij<<endl;
    1691           0 :   }
    1692           0 : }
    1693             : vector<int> ClusterSequence::unique_history_order() const {
    1694           0 :   valarray<int> lowest_constituent(_history.size());
    1695           0 :   int hist_n = _history.size();
    1696           0 :   lowest_constituent = hist_n; // give it a large number
    1697           0 :   for (int i = 0; i < hist_n; i++) {
    1698           0 :     lowest_constituent[i] = min(lowest_constituent[i],i);
    1699           0 :     if (_history[i].child > 0) lowest_constituent[_history[i].child]
    1700           0 :       = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
    1701             :   }
    1702           0 :   valarray<bool> extracted(_history.size()); extracted = false;
    1703           0 :   vector<int> unique_tree;
    1704           0 :   unique_tree.reserve(_history.size());
    1705           0 :   for (unsigned i = 0; i < n_particles(); i++) {
    1706           0 :     if (!extracted[i]) {
    1707           0 :       unique_tree.push_back(i);
    1708           0 :       extracted[i] = true;
    1709           0 :       _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
    1710             :     }
    1711             :   }
    1712             :   return unique_tree;
    1713           0 : }
    1714             : void ClusterSequence::_extract_tree_children(
    1715             :        int position,
    1716             :        valarray<bool> & extracted,
    1717             :        const valarray<int> & lowest_constituent,
    1718             :        vector<int> & unique_tree) const {
    1719           0 :   if (!extracted[position]) {
    1720           0 :     _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
    1721           0 :   }
    1722           0 :   int child = _history[position].child;
    1723           0 :   if (child  >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
    1724           0 : }
    1725             : vector<PseudoJet> ClusterSequence::unclustered_particles() const {
    1726           0 :   vector<PseudoJet> unclustered;
    1727           0 :   for (unsigned i = 0; i < n_particles() ; i++) {
    1728           0 :     if (_history[i].child == Invalid)
    1729           0 :       unclustered.push_back(_jets[_history[i].jetp_index]);
    1730             :   }
    1731             :   return unclustered;
    1732           0 : }
    1733             : vector<PseudoJet> ClusterSequence::childless_pseudojets() const {
    1734           0 :   vector<PseudoJet> unclustered;
    1735           0 :   for (unsigned i = 0; i < _history.size() ; i++) {
    1736           0 :     if ((_history[i].child == Invalid) && (_history[i].parent2 != BeamJet))
    1737           0 :       unclustered.push_back(_jets[_history[i].jetp_index]);
    1738             :   }
    1739             :   return unclustered;
    1740           0 : }
    1741             : bool ClusterSequence::contains(const PseudoJet & jet) const {
    1742           0 :   return jet.cluster_hist_index() >= 0
    1743           0 :     &&   jet.cluster_hist_index() < int(_history.size())
    1744           0 :     &&   jet.has_valid_cluster_sequence()
    1745           0 :     &&   jet.associated_cluster_sequence() == this;
    1746             : }
    1747             : void ClusterSequence::_extract_tree_parents(
    1748             :        int position,
    1749             :        valarray<bool> & extracted,
    1750             :        const valarray<int> & lowest_constituent,
    1751             :        vector<int> & unique_tree) const {
    1752           0 :   if (!extracted[position]) {
    1753           0 :     int parent1 = _history[position].parent1;
    1754           0 :     int parent2 = _history[position].parent2;
    1755           0 :     if (parent1 >= 0 && parent2 >= 0) {
    1756           0 :       if (lowest_constituent[parent1] > lowest_constituent[parent2])
    1757           0 :         std::swap(parent1, parent2);
    1758             :     }
    1759           0 :     if (parent1 >= 0 && !extracted[parent1])
    1760           0 :       _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
    1761           0 :     if (parent2 >= 0 && !extracted[parent2])
    1762           0 :       _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
    1763           0 :     unique_tree.push_back(position);
    1764           0 :     extracted[position] = true;
    1765           0 :   }
    1766           0 : }
    1767             : void ClusterSequence::_do_ij_recombination_step(
    1768             :                                const int & jet_i, const int & jet_j,
    1769             :                                const double & dij,
    1770             :                                int & newjet_k) {
    1771           0 :   PseudoJet newjet(false);
    1772           0 :   _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
    1773           0 :   _jets.push_back(newjet);
    1774           0 :   newjet_k = _jets.size()-1;
    1775           0 :   int newstep_k = _history.size();
    1776           0 :   _jets[newjet_k].set_cluster_hist_index(newstep_k);
    1777           0 :   int hist_i = _jets[jet_i].cluster_hist_index();
    1778           0 :   int hist_j = _jets[jet_j].cluster_hist_index();
    1779           0 :   _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
    1780             :                        newjet_k, dij);
    1781           0 : }
    1782             : void ClusterSequence::_do_iB_recombination_step(
    1783             :                                   const int & jet_i, const double & diB) {
    1784           0 :   int newstep_k = _history.size();
    1785           0 :   _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
    1786           0 :                        Invalid, diB);
    1787           0 : }
    1788           6 : LimitedWarning ClusterSequence::_changed_strategy_warning;
    1789             : void ClusterSequence::_set_structure_shared_ptr(PseudoJet & j) {
    1790           0 :   j.set_structure_shared_ptr(_structure_shared_ptr);
    1791           0 :   _update_structure_use_count();
    1792           0 : }
    1793             : void ClusterSequence::_update_structure_use_count() {
    1794           0 :   _structure_use_count_after_construction = _structure_shared_ptr.use_count();
    1795           0 : }
    1796             : void ClusterSequence::delete_self_when_unused() {
    1797           0 :   int new_count = _structure_shared_ptr.use_count() - _structure_use_count_after_construction;
    1798           0 :   if (new_count <= 0) {
    1799           0 :     throw Error("delete_self_when_unused may only be called if at least one object outside the CS (e.g. a jet) is already associated with the CS");
    1800             :   }
    1801           0 :   _structure_shared_ptr.set_count(new_count);
    1802           0 :   _deletes_self_when_unused = true;
    1803           0 : }
    1804             : FJCORE_END_NAMESPACE
    1805             : #include<limits>
    1806             : #include<vector>
    1807             : #include<cmath>
    1808             : #include<iostream>
    1809             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    1810             : using namespace std;
    1811             : namespace Private {
    1812             :   class MirrorInfo{
    1813             :   public:
    1814             :     int orig, mirror;
    1815           0 :     MirrorInfo(int a, int b) : orig(a), mirror(b) {};
    1816           0 :     MirrorInfo() {};
    1817             :   };
    1818             :   bool make_mirror(Coord2D & point, double Dlim) {
    1819           0 :     if (point.y < Dlim)       {point.y += twopi; return true;}
    1820           0 :     if (twopi-point.y < Dlim) {point.y -= twopi; return true;}
    1821           0 :     return false;
    1822           0 :   }
    1823             : }
    1824             : using namespace Private;
    1825             : void ClusterSequence::_CP2DChan_limited_cluster (double Dlim) {
    1826           0 :   unsigned int n = _initial_n;
    1827           0 :   vector<MirrorInfo>   coordIDs(2*n); // coord IDs of a given jetID
    1828           0 :   vector<int>          jetIDs(2*n);   // jet ID for a given coord ID
    1829           0 :   vector<Coord2D>      coords(2*n);   // our coordinates (and copies)
    1830           0 :   double Dlim4mirror = min(Dlim,pi);
    1831           0 :   double minrap = numeric_limits<double>::max();
    1832           0 :   double maxrap = -minrap;
    1833             :   int coord_index = -1;
    1834             :   int n_active = 0;
    1835           0 :   for (unsigned jet_i = 0; jet_i < _jets.size(); jet_i++) {
    1836           0 :     if (_history[_jets[jet_i].cluster_hist_index()].child != Invalid ||
    1837           0 :         (_jets[jet_i].E() == abs(_jets[jet_i].pz()) &&
    1838           0 :          _jets[jet_i].perp2() == 0.0)
    1839             :         ) {continue;}
    1840           0 :     n_active++;
    1841           0 :     coordIDs[jet_i].orig = ++coord_index;
    1842           0 :     coords[coord_index]  = Coord2D(_jets[jet_i].rap(), _jets[jet_i].phi_02pi());
    1843           0 :     jetIDs[coord_index]  = jet_i;
    1844           0 :     minrap = min(coords[coord_index].x,minrap);
    1845           0 :     maxrap = max(coords[coord_index].x,maxrap);
    1846           0 :     Coord2D mirror_point(coords[coord_index]);
    1847           0 :     if (make_mirror(mirror_point, Dlim4mirror)) {
    1848           0 :       coordIDs[jet_i].mirror = ++coord_index;
    1849           0 :       coords[coord_index] = mirror_point;
    1850           0 :       jetIDs[coord_index] = jet_i;
    1851           0 :     } else {
    1852           0 :       coordIDs[jet_i].mirror = Invalid;
    1853             :     }
    1854           0 :   }
    1855           0 :   coords.resize(coord_index+1);
    1856           0 :   Coord2D left_edge(minrap-1.0, -3.15); // a security margin below  -pi
    1857           0 :   Coord2D right_edge(maxrap+1.0, 9.45); // a security margin above 3*pi
    1858           0 :   ClosestPair2D cp(coords, left_edge, right_edge);
    1859           0 :   vector<Coord2D> new_points(2);
    1860           0 :   vector<unsigned int> cIDs_to_remove(4);
    1861           0 :   vector<unsigned int> new_cIDs(2);
    1862             :   do {
    1863           0 :     unsigned int cID1, cID2;
    1864           0 :     double distance2;
    1865           0 :     cp.closest_pair(cID1,cID2,distance2);
    1866           0 :     if (distance2 > Dlim*Dlim) {break;}
    1867           0 :     distance2 *= _invR2;
    1868           0 :     int jet_i = jetIDs[cID1];
    1869           0 :     int jet_j = jetIDs[cID2];
    1870           0 :     assert (jet_i != jet_j); // to catch issue of recombining with mirror point
    1871           0 :     int newjet_k;
    1872           0 :     _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
    1873           0 :     if (--n_active == 1) {break;}
    1874           0 :     cIDs_to_remove.resize(0);
    1875           0 :     cIDs_to_remove.push_back(coordIDs[jet_i].orig);
    1876           0 :     cIDs_to_remove.push_back(coordIDs[jet_j].orig);
    1877           0 :     if (coordIDs[jet_i].mirror != Invalid)
    1878           0 :       cIDs_to_remove.push_back(coordIDs[jet_i].mirror);
    1879           0 :     if (coordIDs[jet_j].mirror != Invalid)
    1880           0 :       cIDs_to_remove.push_back(coordIDs[jet_j].mirror);
    1881           0 :     Coord2D new_point(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
    1882           0 :     new_points.resize(0);
    1883           0 :     new_points.push_back(new_point);
    1884           0 :     if (make_mirror(new_point, Dlim4mirror)) new_points.push_back(new_point);  //< same warning as before concerning the mirroring
    1885           0 :     cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
    1886           0 :     coordIDs[newjet_k].orig = new_cIDs[0];
    1887           0 :     jetIDs[new_cIDs[0]]       = newjet_k;
    1888           0 :     if (new_cIDs.size() == 2) {
    1889           0 :       coordIDs[newjet_k].mirror = new_cIDs[1];
    1890           0 :       jetIDs[new_cIDs[1]]         = newjet_k;
    1891           0 :     } else {coordIDs[newjet_k].mirror = Invalid;}
    1892           0 :   } while(true);
    1893           0 : }
    1894             : void ClusterSequence::_CP2DChan_cluster_2pi2R () {
    1895           0 :   if (_jet_algorithm != cambridge_algorithm) throw Error("CP2DChan clustering method called for a jet-finder that is not the cambridge algorithm");
    1896           0 :   _CP2DChan_limited_cluster(_Rparam);
    1897           0 :   _do_Cambridge_inclusive_jets();
    1898           0 : }
    1899             : void ClusterSequence::_CP2DChan_cluster_2piMultD () {
    1900           0 :   if (_Rparam >= 0.39) {
    1901           0 :     _CP2DChan_limited_cluster(min(_Rparam/2,0.3));
    1902           0 :   }
    1903           0 :   _CP2DChan_cluster_2pi2R ();
    1904           0 : }
    1905             : void ClusterSequence::_CP2DChan_cluster () {
    1906           0 :   if (_jet_algorithm != cambridge_algorithm) throw Error("_CP2DChan_cluster called for a jet-finder that is not the cambridge algorithm");
    1907           0 :   unsigned int n = _jets.size();
    1908           0 :   vector<MirrorInfo>   coordIDs(2*n);  // link from original to mirror indices
    1909           0 :   vector<int>          jetIDs(2*n);     // link from mirror to original indices
    1910           0 :   vector<Coord2D>      coords(2*n);   // our coordinates (and copies)
    1911           0 :   double minrap = numeric_limits<double>::max();
    1912           0 :   double maxrap = -minrap;
    1913             :   int coord_index = 0;
    1914           0 :   for (unsigned i = 0; i < n; i++) {
    1915           0 :     if (_jets[i].E() == abs(_jets[i].pz()) && _jets[i].perp2() == 0.0) {
    1916           0 :       coordIDs[i] = MirrorInfo(BeamJet,BeamJet);
    1917           0 :     } else {
    1918           0 :       coordIDs[i].orig   = coord_index;
    1919           0 :       coordIDs[i].mirror = coord_index+1;
    1920           0 :       coords[coord_index]   = Coord2D(_jets[i].rap(), _jets[i].phi_02pi());
    1921           0 :       coords[coord_index+1] = Coord2D(_jets[i].rap(), _jets[i].phi_02pi()+twopi);
    1922           0 :       jetIDs[coord_index]   = i;
    1923           0 :       jetIDs[coord_index+1] = i;
    1924           0 :       minrap = min(coords[coord_index].x,minrap);
    1925           0 :       maxrap = max(coords[coord_index].x,maxrap);
    1926           0 :       coord_index += 2;
    1927             :     }
    1928             :   }
    1929           0 :   for (unsigned i = n; i < 2*n; i++) {coordIDs[i].orig = Invalid;}
    1930           0 :   coords.resize(coord_index);
    1931           0 :   Coord2D left_edge(minrap-1.0, 0.0);
    1932           0 :   Coord2D right_edge(maxrap+1.0, 2*twopi);
    1933           0 :   ClosestPair2D cp(coords, left_edge, right_edge);
    1934           0 :   vector<Coord2D> new_points(2);
    1935           0 :   vector<unsigned int> cIDs_to_remove(4);
    1936           0 :   vector<unsigned int> new_cIDs(2);
    1937             :   do {
    1938           0 :     unsigned int cID1, cID2;
    1939           0 :     double distance2;
    1940           0 :     cp.closest_pair(cID1,cID2,distance2);
    1941           0 :     distance2 *= _invR2;
    1942           0 :     if (distance2 > 1.0) {break;}
    1943           0 :     int jet_i = jetIDs[cID1];
    1944           0 :     int jet_j = jetIDs[cID2];
    1945           0 :     assert (jet_i != jet_j); // to catch issue of recombining with mirror point
    1946           0 :     int newjet_k;
    1947           0 :     _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
    1948           0 :     cIDs_to_remove[0] = coordIDs[jet_i].orig;
    1949           0 :     cIDs_to_remove[1] = coordIDs[jet_i].mirror;
    1950           0 :     cIDs_to_remove[2] = coordIDs[jet_j].orig;
    1951           0 :     cIDs_to_remove[3] = coordIDs[jet_j].mirror;
    1952           0 :     new_points[0] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
    1953           0 :     new_points[1] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi()+twopi);
    1954           0 :     new_cIDs[0] = cp.replace(cIDs_to_remove[0], cIDs_to_remove[2], new_points[0]);
    1955           0 :     new_cIDs[1] = cp.replace(cIDs_to_remove[1], cIDs_to_remove[3], new_points[1]);
    1956           0 :     coordIDs[jet_i].orig = Invalid;
    1957           0 :     coordIDs[jet_j].orig = Invalid;
    1958           0 :     coordIDs[newjet_k] = MirrorInfo(new_cIDs[0], new_cIDs[1]);
    1959           0 :     jetIDs[new_cIDs[0]] = newjet_k;
    1960           0 :     jetIDs[new_cIDs[1]] = newjet_k;
    1961           0 :     n--;
    1962           0 :     if (n == 1) {break;}
    1963           0 :   } while(true);
    1964           0 :   _do_Cambridge_inclusive_jets();
    1965           0 : }
    1966             : void ClusterSequence::_do_Cambridge_inclusive_jets () {
    1967           0 :   unsigned int n = _history.size();
    1968           0 :   for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
    1969           0 :     if (_history[hist_i].child == Invalid) {
    1970           0 :       _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
    1971           0 :     }
    1972             :   }
    1973           0 : }
    1974             : FJCORE_END_NAMESPACE
    1975             : #include<iostream>
    1976             : #include<sstream>
    1977             : #include<cmath>
    1978             : #include <cstdlib>
    1979             : #include<cassert>
    1980             : #include<memory>
    1981             : #ifndef __FJCORE_DROP_CGAL // in case we do not have the code for CGAL
    1982             : #include "fastjet/internal/Dnn4piCylinder.hh"
    1983             : #include "fastjet/internal/Dnn3piCylinder.hh"
    1984             : #include "fastjet/internal/Dnn2piCylinder.hh"
    1985             : #endif //  __FJCORE_DROP_CGAL
    1986             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    1987             : using namespace std;
    1988             : void ClusterSequence::_delaunay_cluster () {
    1989           0 :   int n = _jets.size();
    1990           0 :   vector<EtaPhi> points(n); // recall EtaPhi is just a typedef'd pair<double>
    1991           0 :   for (int i = 0; i < n; i++) {
    1992           0 :     points[i] = EtaPhi(_jets[i].rap(),_jets[i].phi_02pi());
    1993           0 :     points[i].sanitize(); // make sure things are in the right range
    1994             :   }
    1995           0 :   auto_ptr<DynamicNearestNeighbours> DNN;
    1996             : #ifndef __FJCORE_DROP_CGAL // strategy = NlnN* are not supported if we drop CGAL...
    1997             :   bool verbose = false;
    1998             :   bool ignore_nearest_is_mirror = (_Rparam < twopi);
    1999             :   if (_strategy == NlnN4pi) {
    2000             :     DNN.reset(new Dnn4piCylinder(points,verbose));
    2001             :   } else if (_strategy == NlnN3pi) {
    2002             :     DNN.reset(new Dnn3piCylinder(points,ignore_nearest_is_mirror,verbose));
    2003             :   } else if (_strategy == NlnN) {
    2004             :     DNN.reset(new Dnn2piCylinder(points,ignore_nearest_is_mirror,verbose));
    2005             :   } else
    2006             : #else
    2007           0 :   if (_strategy == NlnN4pi || _strategy == NlnN3pi || _strategy == NlnN) {
    2008           0 :     ostringstream err;
    2009           0 :     err << "ERROR: Requested strategy "<<strategy_string()<<" but it is not"<<endl;
    2010           0 :     err << "       supported because FastJet was compiled without CGAL"<<endl;
    2011           0 :     throw Error(err.str());
    2012           0 :   }
    2013             : #endif // __FJCORE_DROP_CGAL
    2014             :   {
    2015           0 :     ostringstream err;
    2016           0 :     err << "ERROR: Unrecognized value for strategy: "<<_strategy<<endl;
    2017           0 :     assert(false);
    2018             :     throw Error(err.str());
    2019           0 :   }
    2020             :   DistMap DijMap;
    2021             :   for (int ii = 0; ii < n; ii++) {
    2022             :     _add_ktdistance_to_map(ii, DijMap, DNN.get());
    2023             :   }
    2024             :   for (int i=0;i<n;i++) {
    2025             :     TwoVertices SmallestDijPair;
    2026             :     int jet_i, jet_j;
    2027             :     double SmallestDij;
    2028             :     bool Valid2;
    2029             :     bool recombine_with_beam;
    2030             :     do {
    2031             :       SmallestDij = DijMap.begin()->first;
    2032             :       SmallestDijPair = DijMap.begin()->second;
    2033             :       jet_i = SmallestDijPair.first;
    2034             :       jet_j = SmallestDijPair.second;
    2035             :       DijMap.erase(DijMap.begin());
    2036             :       recombine_with_beam = (jet_j == BeamJet);
    2037             :       if (!recombine_with_beam) {Valid2 = DNN->Valid(jet_j);}
    2038             :       else {Valid2 = true;}
    2039             :     } while ( !DNN->Valid(jet_i) || !Valid2);
    2040             :     if (! recombine_with_beam) {
    2041             :       int nn; // will be index of new jet
    2042             :       _do_ij_recombination_step(jet_i, jet_j, SmallestDij, nn);
    2043             :       EtaPhi newpoint(_jets[nn].rap(), _jets[nn].phi_02pi());
    2044             :       newpoint.sanitize(); // make sure it is in correct range
    2045             :       points.push_back(newpoint);
    2046             :     } else {
    2047             :       _do_iB_recombination_step(jet_i, SmallestDij);
    2048             :     }
    2049             :     if (i == n-1) {break;}
    2050             :     vector<int> updated_neighbours;
    2051             :     if (! recombine_with_beam) {
    2052             :       int point3;
    2053             :       DNN->RemoveCombinedAddCombination(jet_i, jet_j,
    2054             :                                        points[points.size()-1], point3,
    2055             :                                        updated_neighbours);
    2056             :       if (static_cast<unsigned int> (point3) != points.size()-1) {
    2057             :         throw Error("INTERNAL ERROR: point3 != points.size()-1");}
    2058             :     } else {
    2059             :       DNN->RemovePoint(jet_i, updated_neighbours);
    2060             :     }
    2061             :     vector<int>::iterator it = updated_neighbours.begin();
    2062             :     for (; it != updated_neighbours.end(); ++it) {
    2063             :       int ii = *it;
    2064             :       _add_ktdistance_to_map(ii, DijMap, DNN.get());
    2065             :     }
    2066             :   } // end clustering loop
    2067           0 : }
    2068             : void ClusterSequence::_add_ktdistance_to_map(
    2069             :                           const int & ii,
    2070             :                           DistMap & DijMap,
    2071             :                           const DynamicNearestNeighbours * DNN) {
    2072           0 :   double yiB = jet_scale_for_algorithm(_jets[ii]);
    2073           0 :   if (yiB == 0.0) {
    2074           0 :     DijMap.insert(DijEntry(yiB,  TwoVertices(ii,-1)));
    2075           0 :   } else {
    2076           0 :     double DeltaR2 = DNN->NearestNeighbourDistance(ii) * _invR2;
    2077           0 :     if (DeltaR2 > 1.0) {
    2078           0 :       DijMap.insert(DijEntry(yiB,  TwoVertices(ii,-1)));
    2079           0 :     } else {
    2080           0 :       double kt2i = jet_scale_for_algorithm(_jets[ii]);
    2081           0 :       int jj = DNN->NearestNeighbourIndex(ii);
    2082           0 :       if (kt2i <= jet_scale_for_algorithm(_jets[jj])) {
    2083           0 :         double dij = DeltaR2 * kt2i;
    2084           0 :         DijMap.insert(DijEntry(dij, TwoVertices(ii,jj)));
    2085           0 :       }
    2086           0 :     }
    2087             :   }
    2088           0 : }
    2089             : FJCORE_END_NAMESPACE
    2090             : #include<iostream>
    2091             : #include<cmath>
    2092             : #include <cstdlib>
    2093             : #include<cassert>
    2094             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    2095             : using namespace std;
    2096             : void ClusterSequence::_really_dumb_cluster () {
    2097           0 :   vector<PseudoJet *> jetsp(_jets.size());
    2098           0 :   vector<int>         indices(_jets.size());
    2099           0 :   for (size_t i = 0; i<_jets.size(); i++) {
    2100           0 :     jetsp[i] = & _jets[i];
    2101           0 :     indices[i] = i;
    2102             :   }
    2103           0 :   for (int n = jetsp.size(); n > 0; n--) {
    2104             :     int ii, jj;
    2105           0 :     double ymin = jet_scale_for_algorithm(*(jetsp[0]));
    2106             :     ii = 0; jj = -2;
    2107           0 :     for (int i = 0; i < n; i++) {
    2108           0 :       double yiB = jet_scale_for_algorithm(*(jetsp[i]));
    2109           0 :       if (yiB < ymin) {
    2110           0 :         ymin = yiB; ii = i; jj = -2;}
    2111             :     }
    2112           0 :     for (int i = 0; i < n-1; i++) {
    2113           0 :       for (int j = i+1; j < n; j++) {
    2114             :         //double y = jetsp[i]->kt_distance(*jetsp[j])*_invR2;
    2115           0 :         double y = min(jet_scale_for_algorithm(*(jetsp[i])),
    2116           0 :                        jet_scale_for_algorithm(*(jetsp[j])))
    2117           0 :                     * jetsp[i]->plain_distance(*jetsp[j])*_invR2;
    2118           0 :         if (y < ymin) {ymin = y; ii = i; jj = j;}
    2119             :       }
    2120             :     }
    2121           0 :     int newn = 2*jetsp.size() - n;
    2122           0 :     if (jj >= 0) {
    2123           0 :       int nn; // new jet index
    2124           0 :       _do_ij_recombination_step(jetsp[ii]-&_jets[0],
    2125           0 :                                 jetsp[jj]-&_jets[0], ymin, nn);
    2126           0 :       jetsp[ii] = &_jets[nn];
    2127           0 :       jetsp[jj] = jetsp[n-1];
    2128           0 :       indices[ii] = newn;
    2129           0 :       indices[jj] = indices[n-1];
    2130           0 :     } else {
    2131           0 :       _do_iB_recombination_step(jetsp[ii]-&_jets[0], ymin);
    2132           0 :       jetsp[ii] = jetsp[n-1];
    2133           0 :       indices[ii] = indices[n-1];
    2134             :     }
    2135           0 :   }
    2136           0 : }
    2137             : FJCORE_END_NAMESPACE
    2138             : #include<iostream>
    2139             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    2140             : using namespace std;
    2141             : template<> inline void ClusterSequence::_bj_set_jetinfo(
    2142             :                            EEBriefJet * const jetA, const int _jets_index) const {
    2143           0 :   double E = _jets[_jets_index].E();
    2144           0 :   double scale = E*E; // the default energy scale for the kt alg
    2145           0 :   double p  = jet_def().extra_param(); // in case we're ee_genkt
    2146           0 :   switch (_jet_algorithm) {
    2147             :   case ee_kt_algorithm:
    2148           0 :     assert(_Rparam > 2.0); // force this to be true! [not best place, but works]
    2149             :     break;
    2150             :   case ee_genkt_algorithm:
    2151           0 :     if (p <= 0 && scale < 1e-300) scale = 1e-300; // same dodgy safety as genkt
    2152           0 :     scale = pow(scale,p);
    2153           0 :     break;
    2154             :   default:
    2155           0 :     throw Error("Unrecognised jet algorithm");
    2156             :   }
    2157           0 :   jetA->kt2  = scale; // "kt2" might one day be renamed as "scale" or some such
    2158           0 :   double norm = _jets[_jets_index].modp2();
    2159           0 :   if (norm > 0) {
    2160           0 :     norm = 1.0/sqrt(norm);
    2161           0 :     jetA->nx = norm * _jets[_jets_index].px();
    2162           0 :     jetA->ny = norm * _jets[_jets_index].py();
    2163           0 :     jetA->nz = norm * _jets[_jets_index].pz();
    2164           0 :   } else {
    2165           0 :     jetA->nx = 0.0;
    2166           0 :     jetA->ny = 0.0;
    2167           0 :     jetA->nz = 1.0;
    2168             :   }
    2169           0 :   jetA->_jets_index = _jets_index;
    2170           0 :   jetA->NN_dist = _R2;
    2171           0 :   jetA->NN      = NULL;
    2172           0 : }
    2173             : template<> double ClusterSequence::_bj_dist(
    2174             :                 const EEBriefJet * const jeta,
    2175             :                 const EEBriefJet * const jetb) const {
    2176             :   double dist = 1.0
    2177           0 :     - jeta->nx*jetb->nx
    2178           0 :     - jeta->ny*jetb->ny
    2179           0 :     - jeta->nz*jetb->nz;
    2180           0 :   dist *= 2; // distance is _2_*min(Ei^2,Ej^2)*(1-cos theta)
    2181           0 :   return dist;
    2182             : }
    2183             : void ClusterSequence::_simple_N2_cluster_BriefJet() {
    2184           0 :   _simple_N2_cluster<BriefJet>();
    2185           0 : }
    2186             : void ClusterSequence::_simple_N2_cluster_EEBriefJet() {
    2187           0 :   _simple_N2_cluster<EEBriefJet>();
    2188           0 : }
    2189             : FJCORE_END_NAMESPACE
    2190             : #include <iostream>
    2191             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    2192             : using namespace std;
    2193           0 : ClusterSequenceStructure::~ClusterSequenceStructure(){
    2194           0 :   if (_associated_cs != NULL
    2195           0 :       && _associated_cs->will_delete_self_when_unused()) {
    2196           0 :     _associated_cs->signal_imminent_self_deletion();
    2197           0 :     delete _associated_cs;
    2198             :   }
    2199           0 : }
    2200             : bool ClusterSequenceStructure::has_valid_cluster_sequence() const{
    2201           0 :   return (_associated_cs != NULL);
    2202             : }
    2203             : const ClusterSequence* ClusterSequenceStructure::associated_cluster_sequence() const{
    2204           0 :   return _associated_cs;
    2205             : }
    2206             : const ClusterSequence * ClusterSequenceStructure::validated_cs() const {
    2207           0 :   if (!_associated_cs)
    2208           0 :     throw Error("you requested information about the internal structure of a jet, but its associated ClusterSequence has gone out of scope.");
    2209           0 :   return _associated_cs;
    2210           0 : }
    2211             : bool ClusterSequenceStructure::has_partner(const PseudoJet &reference, PseudoJet &partner) const{
    2212           0 :   return validated_cs()->has_partner(reference, partner);
    2213             : }
    2214             : bool ClusterSequenceStructure::has_child(const PseudoJet &reference, PseudoJet &child) const{
    2215           0 :   return validated_cs()->has_child(reference, child);
    2216             : }
    2217             : bool ClusterSequenceStructure::has_parents(const PseudoJet &reference, PseudoJet &parent1, PseudoJet &parent2) const{
    2218           0 :   return validated_cs()->has_parents(reference, parent1, parent2);
    2219             : }
    2220             : bool ClusterSequenceStructure::object_in_jet(const PseudoJet &reference, const PseudoJet &jet) const{
    2221           0 :   if ((!has_associated_cluster_sequence()) || (!jet.has_associated_cluster_sequence()))
    2222           0 :     throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
    2223           0 :   if (reference.associated_cluster_sequence() != jet.associated_cluster_sequence()) return false;
    2224           0 :   return validated_cs()->object_in_jet(reference, jet);
    2225           0 : }
    2226             : bool ClusterSequenceStructure::has_constituents() const{
    2227           0 :   if (!has_associated_cluster_sequence())
    2228           0 :     throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
    2229           0 :   return true;
    2230           0 : }
    2231             : vector<PseudoJet> ClusterSequenceStructure::constituents(const PseudoJet &reference) const{
    2232           0 :   return validated_cs()->constituents(reference);
    2233             : }
    2234             : bool ClusterSequenceStructure::has_exclusive_subjets() const{
    2235           0 :   if (!has_associated_cluster_sequence())
    2236           0 :     throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
    2237           0 :   return true;
    2238           0 : }
    2239             : std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets (const PseudoJet &reference, const double & dcut) const {
    2240           0 :   return validated_cs()->exclusive_subjets(reference, dcut);
    2241             : }
    2242             : int ClusterSequenceStructure::n_exclusive_subjets(const PseudoJet &reference, const double & dcut) const {
    2243           0 :   return validated_cs()->n_exclusive_subjets(reference, dcut);
    2244             : }
    2245             : std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets_up_to (const PseudoJet &reference, int nsub) const {
    2246           0 :   return validated_cs()->exclusive_subjets_up_to(reference, nsub);
    2247             : }
    2248             : double ClusterSequenceStructure::exclusive_subdmerge(const PseudoJet &reference, int nsub) const {
    2249           0 :   return validated_cs()->exclusive_subdmerge(reference, nsub);
    2250             : }
    2251             : double ClusterSequenceStructure::exclusive_subdmerge_max(const PseudoJet &reference, int nsub) const {
    2252           0 :   return validated_cs()->exclusive_subdmerge_max(reference, nsub);
    2253             : }
    2254             : bool ClusterSequenceStructure::has_pieces(const PseudoJet &reference) const{
    2255           0 :   PseudoJet dummy1, dummy2;
    2256           0 :   return has_parents(reference, dummy1, dummy2);
    2257           0 : }
    2258             : vector<PseudoJet> ClusterSequenceStructure::pieces(const PseudoJet &reference) const{
    2259           0 :   PseudoJet j1, j2;
    2260           0 :   vector<PseudoJet> res;
    2261           0 :   if (has_parents(reference, j1, j2)){
    2262           0 :     res.push_back(j1);
    2263           0 :     res.push_back(j2);
    2264             :   }
    2265             :   return res;
    2266           0 : }
    2267             : FJCORE_END_NAMESPACE
    2268             : #include<iostream>
    2269             : #include<vector>
    2270             : #include<cmath>
    2271             : #include<algorithm>
    2272             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    2273             : using namespace std;
    2274             : void ClusterSequence::_bj_remove_from_tiles(TiledJet * const jet) {
    2275           0 :   Tile * tile = & _tiles[jet->tile_index];
    2276           0 :   if (jet->previous == NULL) {
    2277           0 :     tile->head = jet->next;
    2278           0 :   } else {
    2279           0 :     jet->previous->next = jet->next;
    2280             :   }
    2281           0 :   if (jet->next != NULL) {
    2282           0 :     jet->next->previous = jet->previous;
    2283           0 :   }
    2284           0 : }
    2285             : void ClusterSequence::_initialise_tiles() {
    2286           0 :   double default_size = max(0.1,_Rparam);
    2287           0 :   _tile_size_eta = default_size;
    2288           0 :   _n_tiles_phi   = max(3,int(floor(twopi/default_size)));
    2289           0 :   _tile_size_phi = twopi / _n_tiles_phi; // >= _Rparam and fits in 2pi
    2290           0 :   _tiles_eta_min = 0.0;
    2291           0 :   _tiles_eta_max = 0.0;
    2292             :   const double maxrap = 7.0;
    2293           0 :   for(unsigned int i = 0; i < _jets.size(); i++) {
    2294           0 :     double eta = _jets[i].rap();
    2295           0 :     if (abs(eta) < maxrap) {
    2296           0 :       if (eta < _tiles_eta_min) {_tiles_eta_min = eta;}
    2297           0 :       if (eta > _tiles_eta_max) {_tiles_eta_max = eta;}
    2298             :     }
    2299             :   }
    2300           0 :   _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
    2301           0 :   _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
    2302           0 :   _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
    2303           0 :   _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
    2304           0 :   _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
    2305           0 :   for (int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
    2306           0 :     for (int iphi = 0; iphi < _n_tiles_phi; iphi++) {
    2307           0 :       Tile * tile = & _tiles[_tile_index(ieta,iphi)];
    2308           0 :       tile->head = NULL; // first element of tiles points to itself
    2309           0 :       tile->begin_tiles[0] =  tile;
    2310             :       Tile ** pptile = & (tile->begin_tiles[0]);
    2311           0 :       pptile++;
    2312           0 :       tile->surrounding_tiles = pptile;
    2313           0 :       if (ieta > _tiles_ieta_min) {
    2314             :         // with the itile subroutine, we can safely run tiles from
    2315             :         // idphi=-1 to idphi=+1, because it takes care of
    2316             :         // negative and positive boundaries
    2317           0 :         for (int idphi = -1; idphi <=+1; idphi++) {
    2318           0 :           *pptile = & _tiles[_tile_index(ieta-1,iphi+idphi)];
    2319           0 :           pptile++;
    2320             :         }
    2321           0 :       }
    2322           0 :       *pptile = & _tiles[_tile_index(ieta,iphi-1)];
    2323           0 :       pptile++;
    2324           0 :       tile->RH_tiles = pptile;
    2325           0 :       *pptile = & _tiles[_tile_index(ieta,iphi+1)];
    2326           0 :       pptile++;
    2327           0 :       if (ieta < _tiles_ieta_max) {
    2328           0 :         for (int idphi = -1; idphi <= +1; idphi++) {
    2329           0 :           *pptile = & _tiles[_tile_index(ieta+1,iphi+idphi)];
    2330           0 :           pptile++;
    2331             :         }
    2332           0 :       }
    2333           0 :       tile->end_tiles = pptile;
    2334           0 :       tile->tagged = false;
    2335             :     }
    2336             :   }
    2337           0 : }
    2338             : int ClusterSequence::_tile_index(const double & eta, const double & phi) const {
    2339             :   int ieta, iphi;
    2340           0 :   if      (eta <= _tiles_eta_min) {ieta = 0;}
    2341           0 :   else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
    2342             :   else {
    2343           0 :     ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
    2344           0 :     if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
    2345           0 :       ieta = _tiles_ieta_max-_tiles_ieta_min;}
    2346             :   }
    2347           0 :   iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
    2348           0 :   return (iphi + ieta * _n_tiles_phi);
    2349             : }
    2350             : inline void ClusterSequence::_tj_set_jetinfo( TiledJet * const jet,
    2351             :                                               const int _jets_index) {
    2352           0 :   _bj_set_jetinfo<>(jet, _jets_index);
    2353           0 :   jet->tile_index = _tile_index(jet->eta, jet->phi);
    2354           0 :   Tile * tile = &_tiles[jet->tile_index];
    2355           0 :   jet->previous   = NULL;
    2356           0 :   jet->next       = tile->head;
    2357           0 :   if (jet->next != NULL) {jet->next->previous = jet;}
    2358           0 :   tile->head      = jet;
    2359           0 : }
    2360             : void ClusterSequence::_print_tiles(TiledJet * briefjets ) const {
    2361           0 :   for (vector<Tile>::const_iterator tile = _tiles.begin();
    2362           0 :        tile < _tiles.end(); tile++) {
    2363           0 :     cout << "Tile " << tile - _tiles.begin()<<" = ";
    2364           0 :     vector<int> list;
    2365           0 :     for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
    2366           0 :       list.push_back(jetI-briefjets);
    2367             :     }
    2368           0 :     sort(list.begin(),list.end());
    2369           0 :     for (unsigned int i = 0; i < list.size(); i++) {cout <<" "<<list[i];}
    2370           0 :     cout <<"\n";
    2371           0 :   }
    2372           0 : }
    2373             : void ClusterSequence::_add_neighbours_to_tile_union(const int tile_index,
    2374             :                vector<int> & tile_union, int & n_near_tiles) const {
    2375           0 :   for (Tile * const * near_tile = _tiles[tile_index].begin_tiles;
    2376           0 :        near_tile != _tiles[tile_index].end_tiles; near_tile++){
    2377           0 :     tile_union[n_near_tiles] = *near_tile - & _tiles[0];
    2378           0 :     n_near_tiles++;
    2379             :   }
    2380           0 : }
    2381             : inline void ClusterSequence::_add_untagged_neighbours_to_tile_union(
    2382             :                const int tile_index,
    2383             :                vector<int> & tile_union, int & n_near_tiles)  {
    2384           0 :   for (Tile ** near_tile = _tiles[tile_index].begin_tiles;
    2385           0 :        near_tile != _tiles[tile_index].end_tiles; near_tile++){
    2386           0 :     if (! (*near_tile)->tagged) {
    2387           0 :       (*near_tile)->tagged = true;
    2388           0 :       tile_union[n_near_tiles] = *near_tile - & _tiles[0];
    2389           0 :       n_near_tiles++;
    2390           0 :     }
    2391             :   }
    2392           0 : }
    2393             : void ClusterSequence::_tiled_N2_cluster() {
    2394           0 :   _initialise_tiles();
    2395           0 :   int n = _jets.size();
    2396           0 :   TiledJet * briefjets = new TiledJet[n];
    2397           0 :   TiledJet * jetA = briefjets, * jetB;
    2398           0 :   TiledJet oldB;
    2399             :   oldB.tile_index=0; // prevents a gcc warning
    2400           0 :   vector<int> tile_union(3*n_tile_neighbours);
    2401           0 :   for (int i = 0; i< n; i++) {
    2402           0 :     _tj_set_jetinfo(jetA, i);
    2403           0 :     jetA++; // move on to next entry of briefjets
    2404             :   }
    2405           0 :   TiledJet * tail = jetA; // a semaphore for the end of briefjets
    2406             :   TiledJet * head = briefjets; // a nicer way of naming start
    2407           0 :   vector<Tile>::const_iterator tile;
    2408           0 :   for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
    2409           0 :     for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
    2410           0 :       for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
    2411           0 :         double dist = _bj_dist(jetA,jetB);
    2412           0 :         if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
    2413           0 :         if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
    2414             :       }
    2415             :     }
    2416           0 :     for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
    2417           0 :       for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
    2418           0 :         for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
    2419           0 :           double dist = _bj_dist(jetA,jetB);
    2420           0 :           if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
    2421           0 :           if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
    2422             :         }
    2423             :       }
    2424             :     }
    2425             :   }
    2426           0 :   double * diJ = new double[n];
    2427           0 :   jetA = head;
    2428           0 :   for (int i = 0; i < n; i++) {
    2429           0 :     diJ[i] = _bj_diJ(jetA);
    2430           0 :     jetA++; // have jetA follow i
    2431             :   }
    2432           0 :   int history_location = n-1;
    2433           0 :   while (tail != head) {
    2434           0 :     double diJ_min = diJ[0];
    2435             :     int diJ_min_jet = 0;
    2436           0 :     for (int i = 1; i < n; i++) {
    2437           0 :       if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min  = diJ[i];}
    2438             :     }
    2439           0 :     history_location++;
    2440           0 :     jetA = & briefjets[diJ_min_jet];
    2441           0 :     jetB = jetA->NN;
    2442           0 :     diJ_min *= _invR2;
    2443           0 :     if (jetB != NULL) {
    2444           0 :       if (jetA < jetB) {std::swap(jetA,jetB);}
    2445           0 :       int nn; // new jet index
    2446           0 :       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
    2447           0 :       _bj_remove_from_tiles(jetA);
    2448           0 :       oldB = * jetB;  // take a copy because we will need it...
    2449           0 :       _bj_remove_from_tiles(jetB);
    2450           0 :       _tj_set_jetinfo(jetB, nn); // also registers the jet in the tiling
    2451           0 :     } else {
    2452           0 :       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
    2453           0 :       _bj_remove_from_tiles(jetA);
    2454             :     }
    2455           0 :     int n_near_tiles = 0;
    2456           0 :     _add_neighbours_to_tile_union(jetA->tile_index, tile_union, n_near_tiles);
    2457           0 :     if (jetB != NULL) {
    2458             :       bool sort_it = false;
    2459           0 :       if (jetB->tile_index != jetA->tile_index) {
    2460             :         sort_it = true;
    2461           0 :         _add_neighbours_to_tile_union(jetB->tile_index,tile_union,n_near_tiles);
    2462             :       }
    2463           0 :       if (oldB.tile_index != jetA->tile_index &&
    2464           0 :           oldB.tile_index != jetB->tile_index) {
    2465             :         sort_it = true;
    2466           0 :         _add_neighbours_to_tile_union(oldB.tile_index,tile_union,n_near_tiles);
    2467             :       }
    2468           0 :       if (sort_it) {
    2469             :         // sort the tiles before then compressing the list
    2470           0 :         sort(tile_union.begin(), tile_union.begin()+n_near_tiles);
    2471             :         // and now condense the list
    2472             :         int nnn = 1;
    2473           0 :         for (int i = 1; i < n_near_tiles; i++) {
    2474           0 :           if (tile_union[i] != tile_union[nnn-1]) {
    2475           0 :             tile_union[nnn] = tile_union[i];
    2476           0 :             nnn++;
    2477           0 :           }
    2478             :         }
    2479           0 :         n_near_tiles = nnn;
    2480           0 :       }
    2481           0 :     }
    2482           0 :     tail--; n--;
    2483           0 :     if (jetA == tail) {
    2484             :     } else {
    2485           0 :       *jetA = *tail;
    2486           0 :       diJ[jetA - head] = diJ[tail-head];
    2487           0 :       if (jetA->previous == NULL) {
    2488           0 :         _tiles[jetA->tile_index].head = jetA;
    2489           0 :       } else {
    2490           0 :         jetA->previous->next = jetA;
    2491             :       }
    2492           0 :       if (jetA->next != NULL) {jetA->next->previous = jetA;}
    2493             :     }
    2494           0 :     for (int itile = 0; itile < n_near_tiles; itile++) {
    2495           0 :       Tile * tile_ptr = &_tiles[tile_union[itile]];
    2496           0 :       for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
    2497             :         // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
    2498           0 :         if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
    2499           0 :           jetI->NN_dist = _R2;
    2500           0 :           jetI->NN      = NULL;
    2501             :           // now go over tiles that are neighbours of I (include own tile)
    2502           0 :           for (Tile ** near_tile  = tile_ptr->begin_tiles;
    2503           0 :                        near_tile != tile_ptr->end_tiles; near_tile++) {
    2504             :             // and then over the contents of that tile
    2505           0 :             for (TiledJet * jetJ  = (*near_tile)->head;
    2506           0 :                             jetJ != NULL; jetJ = jetJ->next) {
    2507           0 :               double dist = _bj_dist(jetI,jetJ);
    2508           0 :               if (dist < jetI->NN_dist && jetJ != jetI) {
    2509           0 :                 jetI->NN_dist = dist; jetI->NN = jetJ;
    2510           0 :               }
    2511             :             }
    2512             :           }
    2513           0 :           diJ[jetI-head] = _bj_diJ(jetI); // update diJ
    2514           0 :         }
    2515             :         // check whether new jetB is closer than jetI's current NN and
    2516             :         // if need to update things
    2517           0 :         if (jetB != NULL) {
    2518           0 :           double dist = _bj_dist(jetI,jetB);
    2519           0 :           if (dist < jetI->NN_dist) {
    2520           0 :             if (jetI != jetB) {
    2521           0 :               jetI->NN_dist = dist;
    2522           0 :               jetI->NN = jetB;
    2523           0 :               diJ[jetI-head] = _bj_diJ(jetI); // update diJ...
    2524           0 :             }
    2525             :           }
    2526           0 :           if (dist < jetB->NN_dist) {
    2527           0 :             if (jetI != jetB) {
    2528           0 :               jetB->NN_dist = dist;
    2529           0 :               jetB->NN      = jetI;}
    2530             :           }
    2531           0 :         }
    2532             :       }
    2533             :     }
    2534           0 :     if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
    2535           0 :     for (Tile ** near_tile = _tiles[tail->tile_index].begin_tiles;
    2536           0 :                  near_tile!= _tiles[tail->tile_index].end_tiles; near_tile++){
    2537           0 :       for (TiledJet * jetJ = (*near_tile)->head;
    2538           0 :                      jetJ != NULL; jetJ = jetJ->next) {
    2539           0 :         if (jetJ->NN == tail) {jetJ->NN = jetA;}
    2540             :       }
    2541             :     }
    2542           0 :     if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
    2543           0 :   }
    2544           0 :   delete[] diJ;
    2545           0 :   delete[] briefjets;
    2546           0 : }
    2547             : void ClusterSequence::_faster_tiled_N2_cluster() {
    2548           0 :   _initialise_tiles();
    2549           0 :   int n = _jets.size();
    2550           0 :   TiledJet * briefjets = new TiledJet[n];
    2551           0 :   TiledJet * jetA = briefjets, * jetB;
    2552           0 :   TiledJet oldB;
    2553             :   oldB.tile_index=0; // prevents a gcc warning
    2554           0 :   vector<int> tile_union(3*n_tile_neighbours);
    2555           0 :   for (int i = 0; i< n; i++) {
    2556           0 :     _tj_set_jetinfo(jetA, i);
    2557           0 :     jetA++; // move on to next entry of briefjets
    2558             :   }
    2559             :   TiledJet * head = briefjets; // a nicer way of naming start
    2560           0 :   vector<Tile>::const_iterator tile;
    2561           0 :   for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
    2562           0 :     for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
    2563           0 :       for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
    2564           0 :         double dist = _bj_dist(jetA,jetB);
    2565           0 :         if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
    2566           0 :         if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
    2567             :       }
    2568             :     }
    2569           0 :     for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
    2570           0 :       for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
    2571           0 :         for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
    2572           0 :           double dist = _bj_dist(jetA,jetB);
    2573           0 :           if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
    2574           0 :           if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
    2575             :         }
    2576             :       }
    2577             :     }
    2578             :   }
    2579             :   struct diJ_plus_link {
    2580             :     double     diJ; // the distance
    2581             :     TiledJet * jet; // the jet (i) for which we've found this distance
    2582             :   };
    2583           0 :   diJ_plus_link * diJ = new diJ_plus_link[n];
    2584           0 :   jetA = head;
    2585           0 :   for (int i = 0; i < n; i++) {
    2586           0 :     diJ[i].diJ = _bj_diJ(jetA); // kt distance * R^2
    2587           0 :     diJ[i].jet = jetA;  // our compact diJ table will not be in
    2588           0 :     jetA->diJ_posn = i; // one-to-one corresp. with non-compact jets,
    2589           0 :     jetA++; // have jetA follow i
    2590             :   }
    2591           0 :   int history_location = n-1;
    2592           0 :   while (n > 0) {
    2593             :     diJ_plus_link * best, *stop; // pointers a bit faster than indices
    2594           0 :     double diJ_min = diJ[0].diJ; // initialise the best one here.
    2595             :     best = diJ;                  // and here
    2596           0 :     stop = diJ+n;
    2597           0 :     for (diJ_plus_link * here = diJ+1; here != stop; here++) {
    2598           0 :       if (here->diJ < diJ_min) {best = here; diJ_min  = here->diJ;}
    2599             :     }
    2600           0 :     history_location++;
    2601           0 :     jetA = best->jet;
    2602           0 :     jetB = jetA->NN;
    2603           0 :     diJ_min *= _invR2;
    2604           0 :     if (jetB != NULL) {
    2605           0 :       if (jetA < jetB) {std::swap(jetA,jetB);}
    2606           0 :       int nn; // new jet index
    2607           0 :       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
    2608           0 :       _bj_remove_from_tiles(jetA);
    2609           0 :       oldB = * jetB;  // take a copy because we will need it...
    2610           0 :       _bj_remove_from_tiles(jetB);
    2611           0 :       _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
    2612           0 :     } else {
    2613           0 :       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
    2614           0 :       _bj_remove_from_tiles(jetA);
    2615             :     }
    2616           0 :     int n_near_tiles = 0;
    2617           0 :     _add_untagged_neighbours_to_tile_union(jetA->tile_index,
    2618             :                                            tile_union, n_near_tiles);
    2619           0 :     if (jetB != NULL) {
    2620           0 :       if (jetB->tile_index != jetA->tile_index) {
    2621           0 :         _add_untagged_neighbours_to_tile_union(jetB->tile_index,
    2622             :                                                tile_union,n_near_tiles);
    2623             :       }
    2624           0 :       if (oldB.tile_index != jetA->tile_index &&
    2625           0 :           oldB.tile_index != jetB->tile_index) {
    2626           0 :         _add_untagged_neighbours_to_tile_union(oldB.tile_index,
    2627             :                                                tile_union,n_near_tiles);
    2628             :       }
    2629             :     }
    2630           0 :     n--;
    2631           0 :     diJ[n].jet->diJ_posn = jetA->diJ_posn;
    2632           0 :     diJ[jetA->diJ_posn] = diJ[n];
    2633           0 :     for (int itile = 0; itile < n_near_tiles; itile++) {
    2634           0 :       Tile * tile_ptr = &_tiles[tile_union[itile]];
    2635           0 :       tile_ptr->tagged = false; // reset tag, since we're done with unions
    2636           0 :       for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
    2637             :         // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
    2638           0 :         if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
    2639           0 :           jetI->NN_dist = _R2;
    2640           0 :           jetI->NN      = NULL;
    2641             :           // now go over tiles that are neighbours of I (include own tile)
    2642           0 :           for (Tile ** near_tile  = tile_ptr->begin_tiles;
    2643           0 :                        near_tile != tile_ptr->end_tiles; near_tile++) {
    2644             :             // and then over the contents of that tile
    2645           0 :             for (TiledJet * jetJ  = (*near_tile)->head;
    2646           0 :                             jetJ != NULL; jetJ = jetJ->next) {
    2647           0 :               double dist = _bj_dist(jetI,jetJ);
    2648           0 :               if (dist < jetI->NN_dist && jetJ != jetI) {
    2649           0 :                 jetI->NN_dist = dist; jetI->NN = jetJ;
    2650           0 :               }
    2651             :             }
    2652             :           }
    2653           0 :           diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ kt-dist
    2654           0 :         }
    2655             :         // check whether new jetB is closer than jetI's current NN and
    2656             :         // if jetI is closer than jetB's current (evolving) nearest
    2657             :         // neighbour. Where relevant update things
    2658           0 :         if (jetB != NULL) {
    2659           0 :           double dist = _bj_dist(jetI,jetB);
    2660           0 :           if (dist < jetI->NN_dist) {
    2661           0 :             if (jetI != jetB) {
    2662           0 :               jetI->NN_dist = dist;
    2663           0 :               jetI->NN = jetB;
    2664           0 :               diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ...
    2665           0 :             }
    2666             :           }
    2667           0 :           if (dist < jetB->NN_dist) {
    2668           0 :             if (jetI != jetB) {
    2669           0 :               jetB->NN_dist = dist;
    2670           0 :               jetB->NN      = jetI;}
    2671             :           }
    2672           0 :         }
    2673             :       }
    2674             :     }
    2675           0 :     if (jetB != NULL) {diJ[jetB->diJ_posn].diJ = _bj_diJ(jetB);}
    2676           0 :   }
    2677           0 :   delete[] diJ;
    2678           0 :   delete[] briefjets;
    2679           0 : }
    2680             : void ClusterSequence::_minheap_faster_tiled_N2_cluster() {
    2681           0 :   _initialise_tiles();
    2682           0 :   int n = _jets.size();
    2683           0 :   TiledJet * briefjets = new TiledJet[n];
    2684           0 :   TiledJet * jetA = briefjets, * jetB;
    2685           0 :   TiledJet oldB;
    2686             :   oldB.tile_index=0; // prevents a gcc warning
    2687           0 :   vector<int> tile_union(3*n_tile_neighbours);
    2688           0 :   for (int i = 0; i< n; i++) {
    2689           0 :     _tj_set_jetinfo(jetA, i);
    2690           0 :     jetA++; // move on to next entry of briefjets
    2691             :   }
    2692             :   TiledJet * head = briefjets; // a nicer way of naming start
    2693           0 :   vector<Tile>::const_iterator tile;
    2694           0 :   for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
    2695           0 :     for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
    2696           0 :       for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
    2697           0 :         double dist = _bj_dist(jetA,jetB);
    2698           0 :         if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
    2699           0 :         if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
    2700             :       }
    2701             :     }
    2702           0 :     for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
    2703           0 :       for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
    2704           0 :         for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
    2705           0 :           double dist = _bj_dist(jetA,jetB);
    2706           0 :           if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
    2707           0 :           if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
    2708             :         }
    2709             :       }
    2710             :     }
    2711             :   }
    2712           0 :   vector<double> diJs(n);
    2713           0 :   for (int i = 0; i < n; i++) {
    2714           0 :     diJs[i] = _bj_diJ(&briefjets[i]);
    2715           0 :     briefjets[i].label_minheap_update_done();
    2716             :   }
    2717           0 :   MinHeap minheap(diJs);
    2718           0 :   vector<TiledJet *> jets_for_minheap;
    2719           0 :   jets_for_minheap.reserve(n);
    2720           0 :   int history_location = n-1;
    2721           0 :   while (n > 0) {
    2722           0 :     double diJ_min = minheap.minval() *_invR2;
    2723           0 :     jetA = head + minheap.minloc();
    2724           0 :     history_location++;
    2725           0 :     jetB = jetA->NN;
    2726           0 :     if (jetB != NULL) {
    2727           0 :       if (jetA < jetB) {std::swap(jetA,jetB);}
    2728           0 :       int nn; // new jet index
    2729           0 :       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
    2730           0 :       _bj_remove_from_tiles(jetA);
    2731           0 :       oldB = * jetB;  // take a copy because we will need it...
    2732           0 :       _bj_remove_from_tiles(jetB);
    2733           0 :       _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
    2734           0 :     } else {
    2735           0 :       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
    2736           0 :       _bj_remove_from_tiles(jetA);
    2737             :     }
    2738           0 :     minheap.remove(jetA-head);
    2739           0 :     int n_near_tiles = 0;
    2740           0 :     _add_untagged_neighbours_to_tile_union(jetA->tile_index,
    2741             :                                            tile_union, n_near_tiles);
    2742           0 :     if (jetB != NULL) {
    2743           0 :       if (jetB->tile_index != jetA->tile_index) {
    2744           0 :         _add_untagged_neighbours_to_tile_union(jetB->tile_index,
    2745             :                                                tile_union,n_near_tiles);
    2746             :       }
    2747           0 :       if (oldB.tile_index != jetA->tile_index &&
    2748           0 :           oldB.tile_index != jetB->tile_index) {
    2749             :         // GS: the line below generates a warning that oldB.tile_index
    2750             :         // may be used uninitialised. However, to reach this point, we
    2751             :         // ned jetB != NULL (see test a few lines above) and is jetB
    2752             :         // !=NULL, one would have gone through "oldB = *jetB before
    2753             :         // (see piece of code ~20 line above), so the index is
    2754             :         // initialised. We do not do anything to avoid the warning to
    2755             :         // avoid any potential speed impact.
    2756           0 :         _add_untagged_neighbours_to_tile_union(oldB.tile_index,
    2757             :                                                tile_union,n_near_tiles);
    2758             :       }
    2759           0 :       jetB->label_minheap_update_needed();
    2760           0 :       jets_for_minheap.push_back(jetB);
    2761             :     }
    2762           0 :     for (int itile = 0; itile < n_near_tiles; itile++) {
    2763           0 :       Tile * tile_ptr = &_tiles[tile_union[itile]];
    2764           0 :       tile_ptr->tagged = false; // reset tag, since we're done with unions
    2765           0 :       for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
    2766             :         // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
    2767           0 :         if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
    2768           0 :           jetI->NN_dist = _R2;
    2769           0 :           jetI->NN      = NULL;
    2770             :           // label jetI as needing heap action...
    2771           0 :           if (!jetI->minheap_update_needed()) {
    2772           0 :             jetI->label_minheap_update_needed();
    2773           0 :             jets_for_minheap.push_back(jetI);}
    2774             :           // now go over tiles that are neighbours of I (include own tile)
    2775           0 :           for (Tile ** near_tile  = tile_ptr->begin_tiles;
    2776           0 :                        near_tile != tile_ptr->end_tiles; near_tile++) {
    2777             :             // and then over the contents of that tile
    2778           0 :             for (TiledJet * jetJ  = (*near_tile)->head;
    2779           0 :                             jetJ != NULL; jetJ = jetJ->next) {
    2780           0 :               double dist = _bj_dist(jetI,jetJ);
    2781           0 :               if (dist < jetI->NN_dist && jetJ != jetI) {
    2782           0 :                 jetI->NN_dist = dist; jetI->NN = jetJ;
    2783           0 :               }
    2784             :             }
    2785             :           }
    2786           0 :         }
    2787             :         // check whether new jetB is closer than jetI's current NN and
    2788             :         // if jetI is closer than jetB's current (evolving) nearest
    2789             :         // neighbour. Where relevant update things
    2790           0 :         if (jetB != NULL) {
    2791           0 :           double dist = _bj_dist(jetI,jetB);
    2792           0 :           if (dist < jetI->NN_dist) {
    2793           0 :             if (jetI != jetB) {
    2794           0 :               jetI->NN_dist = dist;
    2795           0 :               jetI->NN = jetB;
    2796             :               // label jetI as needing heap action...
    2797           0 :               if (!jetI->minheap_update_needed()) {
    2798           0 :                 jetI->label_minheap_update_needed();
    2799           0 :                 jets_for_minheap.push_back(jetI);}
    2800             :             }
    2801             :           }
    2802           0 :           if (dist < jetB->NN_dist) {
    2803           0 :             if (jetI != jetB) {
    2804           0 :               jetB->NN_dist = dist;
    2805           0 :               jetB->NN      = jetI;}
    2806             :           }
    2807           0 :         }
    2808             :       }
    2809             :     }
    2810           0 :     while (jets_for_minheap.size() > 0) {
    2811           0 :       TiledJet * jetI = jets_for_minheap.back();
    2812           0 :       jets_for_minheap.pop_back();
    2813           0 :       minheap.update(jetI-head, _bj_diJ(jetI));
    2814           0 :       jetI->label_minheap_update_done();
    2815             :     }
    2816           0 :     n--;
    2817           0 :   }
    2818           0 :   delete[] briefjets;
    2819           0 : }
    2820             : FJCORE_END_NAMESPACE
    2821             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    2822             : using namespace std;
    2823           0 : CompositeJetStructure::CompositeJetStructure(const std::vector<PseudoJet> & initial_pieces,
    2824             :                                              const JetDefinition::Recombiner * recombiner)
    2825           0 :   : _pieces(initial_pieces){
    2826             :   if (recombiner){};  // ugly trick to prevent a gcc warning
    2827           0 :   _area_4vector_ptr = 0;
    2828           0 : }
    2829             : std::string CompositeJetStructure::description() const{
    2830           0 :   string str = "Composite PseudoJet";
    2831             :   return str;
    2832           0 : }
    2833             : bool CompositeJetStructure::has_constituents() const{
    2834           0 :   return _pieces.size()!=0;
    2835             : }
    2836             : std::vector<PseudoJet> CompositeJetStructure::constituents(const PseudoJet & /*jet*/) const{
    2837           0 :   vector<PseudoJet> all_constituents;
    2838           0 :   for (unsigned i = 0; i < _pieces.size(); i++) {
    2839           0 :     if (_pieces[i].has_constituents()){
    2840           0 :       vector<PseudoJet> constits = _pieces[i].constituents();
    2841           0 :       copy(constits.begin(), constits.end(), back_inserter(all_constituents));
    2842           0 :     } else {
    2843           0 :       all_constituents.push_back(_pieces[i]);
    2844             :     }
    2845             :   }
    2846             :   return all_constituents;
    2847           0 : }
    2848             : std::vector<PseudoJet> CompositeJetStructure::pieces(const PseudoJet & /*jet*/) const{
    2849           0 :   return _pieces;
    2850             : }
    2851             : FJCORE_END_NAMESPACE      // defined in fastjet/internal/base.hh
    2852             : #include <sstream>
    2853             : #ifdef FJCORE_HAVE_EXECINFO_H
    2854             : #include <execinfo.h>
    2855             : #include <cstdlib>
    2856             : #endif
    2857             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    2858             : using namespace std;
    2859             : bool Error::_print_errors = true;
    2860             : bool Error::_print_backtrace = false;
    2861             : ostream * Error::_default_ostr = & cerr;
    2862           0 : Error::Error(const std::string & message_in) {
    2863           0 :   _message = message_in;
    2864           0 :   if (_print_errors && _default_ostr){
    2865           0 :     ostringstream oss;
    2866           0 :     oss << "fjcore::Error:  "<< message_in << endl;
    2867             : #ifdef FJCORE_HAVE_EXECINFO_H
    2868           0 :     if (_print_backtrace){
    2869           0 :       void * array[10];
    2870             :       char ** messages;
    2871           0 :       int size = backtrace(array, 10);
    2872           0 :       messages = backtrace_symbols(array, size);
    2873           0 :       oss << "stack:" << endl;
    2874           0 :       for (int i = 1; i < size && messages != NULL; ++i){
    2875           0 :         oss << "  #" << i << ": " << messages[i] << endl;
    2876             :       }
    2877           0 :       free(messages);
    2878           0 :     }
    2879             : #endif
    2880           0 :     *_default_ostr << oss.str();
    2881           0 :     _default_ostr->flush();
    2882           0 :   }
    2883           0 : }
    2884             : FJCORE_END_NAMESPACE
    2885             : #include <string>
    2886             : #include <sstream>
    2887             : using namespace std;
    2888             : FJCORE_BEGIN_NAMESPACE
    2889             : FJCORE_END_NAMESPACE
    2890             : #include<sstream>
    2891             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    2892             : using namespace std;
    2893             : const double JetDefinition::max_allowable_R = 1000.0;
    2894           0 : JetDefinition::JetDefinition(JetAlgorithm jet_algorithm_in,
    2895             :                              double R_in,
    2896             :                              Strategy strategy_in,
    2897             :                              RecombinationScheme recomb_scheme_in,
    2898             :                              int nparameters) :
    2899           0 :   _jet_algorithm(jet_algorithm_in), _Rparam(R_in), _strategy(strategy_in) {
    2900           0 :   if (_jet_algorithm == ee_kt_algorithm) {
    2901           0 :     _Rparam = 4.0; // introduce a fictional R that ensures that
    2902           0 :   } else {
    2903           0 :     if (R_in > max_allowable_R) {
    2904           0 :       ostringstream oss;
    2905           0 :       oss << "Requested R = " << R_in << " for jet definition is larger than max_allowable_R = " << max_allowable_R;
    2906           0 :       throw Error(oss.str());
    2907           0 :     }
    2908             :   }
    2909           0 :   switch (jet_algorithm_in) {
    2910             :   case ee_kt_algorithm:
    2911           0 :     if (nparameters != 0) {
    2912           0 :       ostringstream oss;
    2913           0 :       oss << "ee_kt_algorithm should be constructed with 0 parameters but was called with "
    2914           0 :           << nparameters << " parameter(s)\n";
    2915           0 :       throw Error(oss.str());
    2916           0 :     }
    2917             :     break;
    2918             :   case genkt_algorithm:
    2919             :   case ee_genkt_algorithm:
    2920           0 :     if (nparameters != 2) {
    2921           0 :       ostringstream oss;
    2922           0 :       oss << "(ee_)genkt_algorithm should be constructed with 2 parameters but was called with "
    2923           0 :           << nparameters << " parameter(s)\n";
    2924           0 :       throw Error(oss.str());
    2925           0 :     }
    2926             :     break;
    2927             :   default:
    2928           0 :     if (nparameters != 1) {
    2929           0 :       ostringstream oss;
    2930           0 :       oss << "The jet algorithm you requested ("
    2931           0 :           << jet_algorithm_in << ") should be constructed with 1 parameter but was called with "
    2932           0 :           << nparameters << " parameter(s)\n";
    2933           0 :       throw Error(oss.str());
    2934           0 :     }
    2935             :   }
    2936           0 :   assert (_strategy  != plugin_strategy);
    2937           0 :   _plugin = NULL;
    2938           0 :   set_recombination_scheme(recomb_scheme_in);
    2939           0 :   set_extra_param(0.0); // make sure it's defined
    2940           0 : }
    2941             : string JetDefinition::description() const {
    2942           0 :   ostringstream name;
    2943           0 :   if (jet_algorithm() == plugin_algorithm) {
    2944           0 :     return plugin()->description();
    2945           0 :   } else if (jet_algorithm() == kt_algorithm) {
    2946           0 :     name << "Longitudinally invariant kt algorithm with R = " << R();
    2947           0 :     name << " and " << recombiner()->description();
    2948           0 :   } else if (jet_algorithm() == cambridge_algorithm) {
    2949           0 :     name << "Longitudinally invariant Cambridge/Aachen algorithm with R = "
    2950           0 :          << R() ;
    2951           0 :     name << " and " << recombiner()->description();
    2952           0 :   } else if (jet_algorithm() == antikt_algorithm) {
    2953           0 :     name << "Longitudinally invariant anti-kt algorithm with R = "
    2954           0 :          << R() ;
    2955           0 :     name << " and " << recombiner()->description();
    2956           0 :   } else if (jet_algorithm() == genkt_algorithm) {
    2957           0 :     name << "Longitudinally invariant generalised kt algorithm with R = "
    2958           0 :          << R() << ", p = " << extra_param();
    2959           0 :     name << " and " << recombiner()->description();
    2960           0 :   } else if (jet_algorithm() == cambridge_for_passive_algorithm) {
    2961           0 :     name << "Longitudinally invariant Cambridge/Aachen algorithm with R = "
    2962           0 :          << R() << "and a special hack whereby particles with kt < "
    2963           0 :          << extra_param() << "are treated as passive ghosts";
    2964           0 :   } else if (jet_algorithm() == ee_kt_algorithm) {
    2965           0 :     name << "e+e- kt (Durham) algorithm (NB: no R)";
    2966           0 :     name << " with " << recombiner()->description();
    2967           0 :   } else if (jet_algorithm() == ee_genkt_algorithm) {
    2968           0 :     name << "e+e- generalised kt algorithm with R = "
    2969           0 :          << R() << ", p = " << extra_param();
    2970           0 :     name << " and " << recombiner()->description();
    2971           0 :   } else if (jet_algorithm() == undefined_jet_algorithm) {
    2972           0 :     name << "uninitialised JetDefinition (jet_algorithm=undefined_jet_algorithm)" ;
    2973             :   } else {
    2974           0 :     throw Error("JetDefinition::description(): unrecognized jet_algorithm");
    2975             :   }
    2976           0 :   return name.str();
    2977           0 : }
    2978             : void JetDefinition::set_recombination_scheme(
    2979             :                                RecombinationScheme recomb_scheme) {
    2980           0 :   _default_recombiner = JetDefinition::DefaultRecombiner(recomb_scheme);
    2981           0 :   if (_recombiner_shared()) _recombiner_shared.reset();
    2982           0 :   _recombiner = 0;
    2983           0 : }
    2984             : bool JetDefinition::has_same_recombiner(const JetDefinition &other_jd) const{
    2985           0 :   const RecombinationScheme & scheme = recombination_scheme();
    2986           0 :   if (other_jd.recombination_scheme() != scheme) return false;
    2987           0 :   return (scheme != external_scheme)
    2988           0 :     || (recombiner() == other_jd.recombiner());
    2989           0 : }
    2990             : void JetDefinition::delete_recombiner_when_unused(){
    2991           0 :   if (_recombiner == 0){
    2992           0 :     throw Error("tried to call JetDefinition::delete_recombiner_when_unused() for a JetDefinition without a user-defined recombination scheme");
    2993             :   }
    2994           0 :   _recombiner_shared.reset(_recombiner);
    2995           0 : }
    2996             : void JetDefinition::delete_plugin_when_unused(){
    2997           0 :   if (_plugin == 0){
    2998           0 :     throw Error("tried to call JetDefinition::delete_plugin_when_unused() for a JetDefinition without a plugin");
    2999             :   }
    3000           0 :   _plugin_shared.reset(_plugin);
    3001           0 : }
    3002             : string JetDefinition::DefaultRecombiner::description() const {
    3003           0 :   switch(_recomb_scheme) {
    3004             :   case E_scheme:
    3005           0 :     return "E scheme recombination";
    3006             :   case pt_scheme:
    3007           0 :     return "pt scheme recombination";
    3008             :   case pt2_scheme:
    3009           0 :     return "pt2 scheme recombination";
    3010             :   case Et_scheme:
    3011           0 :     return "Et scheme recombination";
    3012             :   case Et2_scheme:
    3013           0 :     return "Et2 scheme recombination";
    3014             :   case BIpt_scheme:
    3015           0 :     return "boost-invariant pt scheme recombination";
    3016             :   case BIpt2_scheme:
    3017           0 :     return "boost-invariant pt2 scheme recombination";
    3018             :   default:
    3019           0 :     ostringstream err;
    3020           0 :     err << "DefaultRecombiner: unrecognized recombination scheme "
    3021           0 :         << _recomb_scheme;
    3022           0 :     throw Error(err.str());
    3023           0 :   }
    3024           0 : }
    3025             : void JetDefinition::DefaultRecombiner::recombine(
    3026             :            const PseudoJet & pa, const PseudoJet & pb,
    3027             :            PseudoJet & pab) const {
    3028             :   double weighta, weightb;
    3029           0 :   switch(_recomb_scheme) {
    3030             :   case E_scheme:
    3031           0 :     pab.reset(pa.px()+pb.px(),
    3032           0 :               pa.py()+pb.py(),
    3033           0 :               pa.pz()+pb.pz(),
    3034           0 :               pa.E ()+pb.E ());
    3035           0 :     return;
    3036             :   case pt_scheme:
    3037             :   case Et_scheme:
    3038             :   case BIpt_scheme:
    3039           0 :     weighta = pa.perp();
    3040           0 :     weightb = pb.perp();
    3041           0 :     break;
    3042             :   case pt2_scheme:
    3043             :   case Et2_scheme:
    3044             :   case BIpt2_scheme:
    3045           0 :     weighta = pa.perp2();
    3046           0 :     weightb = pb.perp2();
    3047           0 :     break;
    3048             :   default:
    3049           0 :     ostringstream err;
    3050           0 :     err << "DefaultRecombiner: unrecognized recombination scheme "
    3051           0 :         << _recomb_scheme;
    3052           0 :     throw Error(err.str());
    3053           0 :   }
    3054           0 :   double perp_ab = pa.perp() + pb.perp();
    3055           0 :   if (perp_ab != 0.0) { // weights also non-zero...
    3056           0 :     double y_ab    = (weighta * pa.rap() + weightb * pb.rap())/(weighta+weightb);
    3057           0 :     double phi_a = pa.phi(), phi_b = pb.phi();
    3058           0 :     if (phi_a - phi_b > pi)  phi_b += twopi;
    3059           0 :     if (phi_a - phi_b < -pi) phi_b -= twopi;
    3060           0 :     double phi_ab = (weighta * phi_a + weightb * phi_b)/(weighta+weightb);
    3061           0 :     pab.reset_PtYPhiM(perp_ab,y_ab,phi_ab);
    3062           0 :   } else { // weights are zero
    3063           0 :     pab.reset(0.0, 0.0, 0.0, 0.0);
    3064             :   }
    3065           0 : }
    3066             : void JetDefinition::DefaultRecombiner::preprocess(PseudoJet & p) const {
    3067           0 :   switch(_recomb_scheme) {
    3068             :   case E_scheme:
    3069             :   case BIpt_scheme:
    3070             :   case BIpt2_scheme:
    3071             :     break;
    3072             :   case pt_scheme:
    3073             :   case pt2_scheme:
    3074             :     {
    3075           0 :       double newE = sqrt(p.perp2()+p.pz()*p.pz());
    3076           0 :       p.reset_momentum(p.px(), p.py(), p.pz(), newE);
    3077             :     }
    3078           0 :     break;
    3079             :   case Et_scheme:
    3080             :   case Et2_scheme:
    3081             :     {
    3082           0 :       double rescale = p.E()/sqrt(p.perp2()+p.pz()*p.pz());
    3083           0 :       p.reset_momentum(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E());
    3084             :     }
    3085           0 :     break;
    3086             :   default:
    3087           0 :     ostringstream err;
    3088           0 :     err << "DefaultRecombiner: unrecognized recombination scheme "
    3089           0 :         << _recomb_scheme;
    3090           0 :     throw Error(err.str());
    3091           0 :   }
    3092           0 : }
    3093             : void JetDefinition::Plugin::set_ghost_separation_scale(double /*scale*/) const {
    3094           0 :   throw Error("set_ghost_separation_scale not supported");
    3095           0 : }
    3096             : PseudoJet join(const vector<PseudoJet> & pieces, const JetDefinition::Recombiner & recombiner){
    3097           0 :   PseudoJet result;  // automatically initialised to 0
    3098           0 :   if (pieces.size()>0){
    3099           0 :     result = pieces[0];
    3100           0 :     for (unsigned int i=1; i<pieces.size(); i++)
    3101           0 :       recombiner.plus_equal(result, pieces[i]);
    3102           0 :   }
    3103           0 :   CompositeJetStructure *cj_struct = new CompositeJetStructure(pieces, &recombiner);
    3104           0 :   result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
    3105             :   return result;
    3106           0 : }
    3107             : PseudoJet join(const PseudoJet & j1,
    3108             :                const JetDefinition::Recombiner & recombiner){
    3109           0 :   return join(vector<PseudoJet>(1,j1), recombiner);
    3110           0 : }
    3111             : PseudoJet join(const PseudoJet & j1, const PseudoJet & j2,
    3112             :                const JetDefinition::Recombiner & recombiner){
    3113           0 :   vector<PseudoJet> pieces;
    3114           0 :   pieces.push_back(j1);
    3115           0 :   pieces.push_back(j2);
    3116           0 :   return join(pieces, recombiner);
    3117           0 : }
    3118             : PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3,
    3119             :                const JetDefinition::Recombiner & recombiner){
    3120           0 :   vector<PseudoJet> pieces;
    3121           0 :   pieces.push_back(j1);
    3122           0 :   pieces.push_back(j2);
    3123           0 :   pieces.push_back(j3);
    3124           0 :   return join(pieces, recombiner);
    3125           0 : }
    3126             : PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4,
    3127             :                const JetDefinition::Recombiner & recombiner){
    3128           0 :   vector<PseudoJet> pieces;
    3129           0 :   pieces.push_back(j1);
    3130           0 :   pieces.push_back(j2);
    3131           0 :   pieces.push_back(j3);
    3132           0 :   pieces.push_back(j4);
    3133           0 :   return join(pieces, recombiner);
    3134           0 : }
    3135             : FJCORE_END_NAMESPACE
    3136             : #include <sstream>
    3137             : #include <limits>
    3138             : using namespace std;
    3139             : FJCORE_BEGIN_NAMESPACE
    3140             : ostream * LimitedWarning::_default_ostr = &cerr;
    3141           6 : std::list< LimitedWarning::Summary > LimitedWarning::_global_warnings_summary;
    3142             : int LimitedWarning::_max_warn_default = 5;
    3143             : void LimitedWarning::warn(const std::string & warning) {
    3144           0 :   warn(warning, _default_ostr);
    3145           0 : }
    3146             : void LimitedWarning::warn(const std::string & warning, std::ostream * ostr) {
    3147           0 :   if (_this_warning_summary == 0) {
    3148           0 :     _global_warnings_summary.push_back(Summary(warning, 0));
    3149           0 :     _this_warning_summary = & (_global_warnings_summary.back());
    3150           0 :   }
    3151           0 :   if (_n_warn_so_far < _max_warn) {
    3152           0 :     ostringstream warnstr;
    3153           0 :     warnstr << "WARNING: ";
    3154           0 :     warnstr << warning;
    3155           0 :     _n_warn_so_far++;
    3156           0 :     if (_n_warn_so_far == _max_warn) warnstr << " (LAST SUCH WARNING)";
    3157           0 :     warnstr << std::endl;
    3158           0 :     if (ostr) {
    3159           0 :       (*ostr) << warnstr.str();
    3160           0 :       ostr->flush(); // get something written to file even if the program aborts
    3161             :     }
    3162           0 :   }
    3163           0 :   if (_this_warning_summary->second < numeric_limits<unsigned>::max()) {
    3164           0 :     _this_warning_summary->second++;
    3165           0 :   }
    3166           0 : }
    3167             : string LimitedWarning::summary() {
    3168           0 :   ostringstream str;
    3169           0 :   for (list<Summary>::const_iterator it = _global_warnings_summary.begin();
    3170           0 :        it != _global_warnings_summary.end(); it++) {
    3171           0 :     str << it->second << " times: " << it->first << endl;
    3172             :   }
    3173           0 :   return str.str();
    3174           0 : }
    3175             : FJCORE_END_NAMESPACE
    3176             : #include<iostream>
    3177             : #include<cmath>
    3178             : #include<limits>
    3179             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    3180             : using namespace std;
    3181             : void MinHeap::_initialise(const std::vector<double> & values){
    3182           0 :   for (unsigned i = values.size(); i < _heap.size(); i++) {
    3183           0 :     _heap[i].value = std::numeric_limits<double>::max();
    3184           0 :     _heap[i].minloc = &(_heap[i]);
    3185             :   }
    3186           0 :   for (unsigned i = 0; i < values.size(); i++) {
    3187           0 :     _heap[i].value = values[i];
    3188           0 :     _heap[i].minloc = &(_heap[i]);
    3189             :   }
    3190           0 :   for (unsigned i = _heap.size()-1; i > 0; i--) {
    3191           0 :     ValueLoc * parent = &(_heap[(i-1)/2]);
    3192           0 :     ValueLoc * here   = &(_heap[i]);
    3193           0 :     if (here->minloc->value < parent->minloc->value) {
    3194           0 :       parent->minloc = here->minloc;
    3195           0 :     }
    3196             :   }
    3197           0 : }
    3198             : void MinHeap::update(unsigned int loc, double new_value) {
    3199           0 :   assert(loc < _heap.size());
    3200           0 :   ValueLoc * start = &(_heap[loc]);
    3201           0 :   if (start->minloc != start && !(new_value < start->minloc->value)) {
    3202           0 :     start->value = new_value;
    3203           0 :     return;
    3204             :   }
    3205           0 :   start->value = new_value;
    3206           0 :   start->minloc = start;
    3207             :   bool change_made = true;
    3208           0 :   ValueLoc * heap_end = (&(_heap[0])) + _heap.size();
    3209           0 :   while(change_made) {
    3210           0 :     ValueLoc * here = &(_heap[loc]);
    3211             :     change_made     = false;
    3212           0 :     if (here->minloc == start) {
    3213           0 :       here->minloc = here; change_made = true;
    3214           0 :     }
    3215           0 :     ValueLoc * child = &(_heap[2*loc+1]);
    3216           0 :     if (child < heap_end && child->minloc->value < here->minloc->value ) {
    3217           0 :       here->minloc = child->minloc;
    3218           0 :       change_made = true;}
    3219           0 :     child++;
    3220           0 :     if (child < heap_end && child->minloc->value < here->minloc->value ) {
    3221           0 :       here->minloc = child->minloc;
    3222           0 :       change_made = true;}
    3223           0 :     if (loc == 0) {break;}
    3224           0 :     loc = (loc-1)/2;
    3225           0 :   }
    3226           0 : }
    3227             : FJCORE_END_NAMESPACE
    3228             : #include<valarray>
    3229             : #include<iostream>
    3230             : #include<sstream>
    3231             : #include<cmath>
    3232             : #include<algorithm>
    3233             : #include <cstdarg>
    3234             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    3235             : using namespace std;
    3236           0 : PseudoJet::PseudoJet(const double px_in, const double py_in, const double pz_in, const double E_in) {
    3237           0 :   _E  = E_in ;
    3238           0 :   _px = px_in;
    3239           0 :   _py = py_in;
    3240           0 :   _pz = pz_in;
    3241           0 :   this->_finish_init();
    3242           0 :   _reset_indices();
    3243           0 : }
    3244             : void PseudoJet::_finish_init () {
    3245           0 :   _kt2 = this->px()*this->px() + this->py()*this->py();
    3246           0 :   _phi = pseudojet_invalid_phi;
    3247           0 :   _rap = pseudojet_invalid_rap;
    3248           0 : }
    3249             : void PseudoJet::_set_rap_phi() const {
    3250           0 :   if (_kt2 == 0.0) {
    3251           0 :     _phi = 0.0; }
    3252             :   else {
    3253           0 :     _phi = atan2(this->py(),this->px());
    3254             :   }
    3255           0 :   if (_phi < 0.0) {_phi += twopi;}
    3256           0 :   if (_phi >= twopi) {_phi -= twopi;} // can happen if phi=-|eps<1e-15|?
    3257           0 :   if (this->E() == abs(this->pz()) && _kt2 == 0) {
    3258           0 :     double MaxRapHere = MaxRap + abs(this->pz());
    3259           0 :     if (this->pz() >= 0.0) {_rap = MaxRapHere;} else {_rap = -MaxRapHere;}
    3260           0 :   } else {
    3261           0 :     double effective_m2 = max(0.0,m2()); // force non tachyonic mass
    3262           0 :     double E_plus_pz    = _E + abs(_pz); // the safer of p+, p-
    3263           0 :     _rap = 0.5*log((_kt2 + effective_m2)/(E_plus_pz*E_plus_pz));
    3264           0 :     if (_pz > 0) {_rap = - _rap;}
    3265             :   }
    3266           0 : }
    3267             : valarray<double> PseudoJet::four_mom() const {
    3268           0 :   valarray<double> mom(4);
    3269           0 :   mom[0] = _px;
    3270           0 :   mom[1] = _py;
    3271           0 :   mom[2] = _pz;
    3272           0 :   mom[3] = _E ;
    3273             :   return mom;
    3274           0 : }
    3275             : double PseudoJet::operator () (int i) const {
    3276           0 :   switch(i) {
    3277             :   case X:
    3278           0 :     return px();
    3279             :   case Y:
    3280           0 :     return py();
    3281             :   case Z:
    3282           0 :     return pz();
    3283             :   case T:
    3284           0 :     return e();
    3285             :   default:
    3286           0 :     ostringstream err;
    3287           0 :     err << "PseudoJet subscripting: bad index (" << i << ")";
    3288           0 :     throw Error(err.str());
    3289           0 :   }
    3290             :   return 0.;
    3291           0 : }
    3292             : double PseudoJet::pseudorapidity() const {
    3293           0 :   if (px() == 0.0 && py() ==0.0) return MaxRap;
    3294           0 :   if (pz() == 0.0) return 0.0;
    3295           0 :   double theta = atan(perp()/pz());
    3296           0 :   if (theta < 0) theta += pi;
    3297           0 :   return -log(tan(theta/2));
    3298           0 : }
    3299             : PseudoJet operator+ (const PseudoJet & jet1, const PseudoJet & jet2) {
    3300           0 :   return PseudoJet(jet1.px()+jet2.px(),
    3301           0 :                    jet1.py()+jet2.py(),
    3302           0 :                    jet1.pz()+jet2.pz(),
    3303           0 :                    jet1.E() +jet2.E()  );
    3304             : }
    3305             : PseudoJet operator- (const PseudoJet & jet1, const PseudoJet & jet2) {
    3306           0 :   return PseudoJet(jet1.px()-jet2.px(),
    3307           0 :                    jet1.py()-jet2.py(),
    3308           0 :                    jet1.pz()-jet2.pz(),
    3309           0 :                    jet1.E() -jet2.E()  );
    3310             : }
    3311             : PseudoJet operator* (double coeff, const PseudoJet & jet) {
    3312           0 :   PseudoJet coeff_times_jet(jet);
    3313           0 :   coeff_times_jet *= coeff;
    3314             :   return coeff_times_jet;
    3315           0 : }
    3316             : PseudoJet operator* (const PseudoJet & jet, double coeff) {
    3317           0 :   return coeff*jet;
    3318             : }
    3319             : PseudoJet operator/ (const PseudoJet & jet, double coeff) {
    3320           0 :   return (1.0/coeff)*jet;
    3321             : }
    3322             : void PseudoJet::operator*=(double coeff) {
    3323           0 :   _px *= coeff;
    3324           0 :   _py *= coeff;
    3325           0 :   _pz *= coeff;
    3326           0 :   _E  *= coeff;
    3327           0 :   _kt2*= coeff*coeff;
    3328           0 : }
    3329             : void PseudoJet::operator/=(double coeff) {
    3330           0 :   (*this) *= 1.0/coeff;
    3331           0 : }
    3332             : void PseudoJet::operator+=(const PseudoJet & other_jet) {
    3333           0 :   _px += other_jet._px;
    3334           0 :   _py += other_jet._py;
    3335           0 :   _pz += other_jet._pz;
    3336           0 :   _E  += other_jet._E ;
    3337           0 :   _finish_init(); // we need to recalculate phi,rap,kt2
    3338           0 : }
    3339             : void PseudoJet::operator-=(const PseudoJet & other_jet) {
    3340           0 :   _px -= other_jet._px;
    3341           0 :   _py -= other_jet._py;
    3342           0 :   _pz -= other_jet._pz;
    3343           0 :   _E  -= other_jet._E ;
    3344           0 :   _finish_init(); // we need to recalculate phi,rap,kt2
    3345           0 : }
    3346             : bool operator==(const PseudoJet & a, const PseudoJet & b) {
    3347           0 :   if (a.px() != b.px()) return false;
    3348           0 :   if (a.py() != b.py()) return false;
    3349           0 :   if (a.pz() != b.pz()) return false;
    3350           0 :   if (a.E () != b.E ()) return false;
    3351           0 :   if (a.user_index()    != b.user_index()) return false;
    3352           0 :   if (a.cluster_hist_index() != b.cluster_hist_index()) return false;
    3353           0 :   if (a.user_info_ptr() != b.user_info_ptr()) return false;
    3354           0 :   if (a.structure_ptr() != b.structure_ptr()) return false;
    3355           0 :   return true;
    3356           0 : }
    3357             : bool operator==(const PseudoJet & jet, const double val) {
    3358           0 :   if (val != 0)
    3359           0 :     throw Error("comparing a PseudoJet with a non-zero constant (double) is not allowed.");
    3360           0 :   return (jet.px() == 0 && jet.py() == 0 &&
    3361           0 :           jet.pz() == 0 && jet.E() == 0);
    3362           0 : }
    3363             : PseudoJet & PseudoJet::boost(const PseudoJet & prest) {
    3364           0 :   if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0)
    3365           0 :     return *this;
    3366           0 :   double m_local = prest.m();
    3367           0 :   assert(m_local != 0);
    3368           0 :   double pf4  = (  px()*prest.px() + py()*prest.py()
    3369           0 :                  + pz()*prest.pz() + E()*prest.E() )/m_local;
    3370           0 :   double fn   = (pf4 + E()) / (prest.E() + m_local);
    3371           0 :   _px +=  fn*prest.px();
    3372           0 :   _py +=  fn*prest.py();
    3373           0 :   _pz +=  fn*prest.pz();
    3374           0 :   _E = pf4;
    3375           0 :   _finish_init(); // we need to recalculate phi,rap,kt2
    3376             :   return *this;
    3377           0 : }
    3378             : PseudoJet & PseudoJet::unboost(const PseudoJet & prest) {
    3379           0 :   if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0)
    3380           0 :     return *this;
    3381           0 :   double m_local = prest.m();
    3382           0 :   assert(m_local != 0);
    3383           0 :   double pf4  = ( -px()*prest.px() - py()*prest.py()
    3384           0 :                  - pz()*prest.pz() + E()*prest.E() )/m_local;
    3385           0 :   double fn   = (pf4 + E()) / (prest.E() + m_local);
    3386           0 :   _px -=  fn*prest.px();
    3387           0 :   _py -=  fn*prest.py();
    3388           0 :   _pz -=  fn*prest.pz();
    3389           0 :   _E = pf4;
    3390           0 :   _finish_init(); // we need to recalculate phi,rap,kt2
    3391             :   return *this;
    3392           0 : }
    3393             : bool have_same_momentum(const PseudoJet & jeta, const PseudoJet & jetb) {
    3394           0 :   return jeta.px() == jetb.px()
    3395           0 :     &&   jeta.py() == jetb.py()
    3396           0 :     &&   jeta.pz() == jetb.pz()
    3397           0 :     &&   jeta.E()  == jetb.E();
    3398             : }
    3399             : void PseudoJet::set_cached_rap_phi(double rap_in, double phi_in) {
    3400           0 :   _rap = rap_in; _phi = phi_in;
    3401           0 :   if (_phi >= twopi) _phi -= twopi;
    3402           0 :   if (_phi < 0)      _phi += twopi;
    3403           0 : }
    3404             : void PseudoJet::reset_momentum_PtYPhiM(double pt_in, double y_in, double phi_in, double m_in) {
    3405           0 :   assert(phi_in < 2*twopi && phi_in > -twopi);
    3406           0 :   double ptm = (m_in == 0) ? pt_in : sqrt(pt_in*pt_in+m_in*m_in);
    3407           0 :   double exprap = exp(y_in);
    3408           0 :   double pminus = ptm/exprap;
    3409           0 :   double pplus  = ptm*exprap;
    3410           0 :   double px_local = pt_in*cos(phi_in);
    3411           0 :   double py_local = pt_in*sin(phi_in);
    3412           0 :   reset_momentum(px_local,py_local,0.5*(pplus-pminus),0.5*(pplus+pminus));
    3413           0 :   set_cached_rap_phi(y_in,phi_in);
    3414           0 : }
    3415             : PseudoJet PtYPhiM(double pt, double y, double phi, double m) {
    3416           0 :   assert(phi < 2*twopi && phi > -twopi);
    3417           0 :   double ptm = (m == 0) ? pt : sqrt(pt*pt+m*m);
    3418           0 :   double exprap = exp(y);
    3419           0 :   double pminus = ptm/exprap;
    3420           0 :   double pplus  = ptm*exprap;
    3421           0 :   double px = pt*cos(phi);
    3422           0 :   double py = pt*sin(phi);
    3423           0 :   PseudoJet mom(px,py,0.5*(pplus-pminus),0.5*(pplus+pminus));
    3424           0 :   mom.set_cached_rap_phi(y,phi);
    3425             :   return mom;
    3426           0 : }
    3427             : double PseudoJet::kt_distance(const PseudoJet & other) const {
    3428           0 :   double distance = min(_kt2, other._kt2);
    3429           0 :   double dphi = abs(phi() - other.phi());
    3430           0 :   if (dphi > pi) {dphi = twopi - dphi;}
    3431           0 :   double drap = rap() - other.rap();
    3432           0 :   distance = distance * (dphi*dphi + drap*drap);
    3433           0 :   return distance;
    3434             : }
    3435             : double PseudoJet::plain_distance(const PseudoJet & other) const {
    3436           0 :   double dphi = abs(phi() - other.phi());
    3437           0 :   if (dphi > pi) {dphi = twopi - dphi;}
    3438           0 :   double drap = rap() - other.rap();
    3439           0 :   return (dphi*dphi + drap*drap);
    3440             : }
    3441             : double PseudoJet::delta_phi_to(const PseudoJet & other) const {
    3442           0 :   double dphi = other.phi() - phi();
    3443           0 :   if (dphi >  pi) dphi -= twopi;
    3444           0 :   if (dphi < -pi) dphi += twopi;
    3445           0 :   return dphi;
    3446             : }
    3447             : string PseudoJet::description() const{
    3448           0 :   if (!_structure())
    3449           0 :     return "standard PseudoJet (with no associated clustering information)";
    3450           0 :   return _structure()->description();
    3451           0 : }
    3452             : bool PseudoJet::has_associated_cluster_sequence() const{
    3453           0 :   return (_structure()) && (_structure->has_associated_cluster_sequence());
    3454             : }
    3455             : const ClusterSequence* PseudoJet::associated_cluster_sequence() const{
    3456           0 :   if (! has_associated_cluster_sequence()) return NULL;
    3457           0 :   return _structure->associated_cluster_sequence();
    3458           0 : }
    3459             : bool PseudoJet::has_valid_cluster_sequence() const{
    3460           0 :   return (_structure()) && (_structure->has_valid_cluster_sequence());
    3461             : }
    3462             : const ClusterSequence * PseudoJet::validated_cs() const {
    3463           0 :   return validated_structure_ptr()->validated_cs();
    3464             : }
    3465             : void PseudoJet::set_structure_shared_ptr(const SharedPtr<PseudoJetStructureBase> &structure_in){
    3466           0 :   _structure = structure_in;
    3467           0 : }
    3468             : bool PseudoJet::has_structure() const{
    3469           0 :   return _structure();
    3470             : }
    3471             : const PseudoJetStructureBase* PseudoJet::structure_ptr() const {
    3472           0 :   if (!_structure()) return NULL;
    3473           0 :   return _structure();
    3474           0 : }
    3475             : PseudoJetStructureBase* PseudoJet::structure_non_const_ptr(){
    3476           0 :   if (!_structure()) return NULL;
    3477           0 :   return _structure();
    3478           0 : }
    3479             : const PseudoJetStructureBase* PseudoJet::validated_structure_ptr() const {
    3480           0 :   if (!_structure())
    3481           0 :     throw Error("Trying to access the structure of a PseudoJet which has no associated structure");
    3482           0 :   return _structure();
    3483           0 : }
    3484             : const SharedPtr<PseudoJetStructureBase> & PseudoJet::structure_shared_ptr() const {
    3485           0 :   return _structure;
    3486             : }
    3487             : bool PseudoJet::has_partner(PseudoJet &partner) const{
    3488           0 :   return validated_structure_ptr()->has_partner(*this, partner);
    3489             : }
    3490             : bool PseudoJet::has_child(PseudoJet &child) const{
    3491           0 :   return validated_structure_ptr()->has_child(*this, child);
    3492             : }
    3493             : bool PseudoJet::has_parents(PseudoJet &parent1, PseudoJet &parent2) const{
    3494           0 :   return validated_structure_ptr()->has_parents(*this, parent1, parent2);
    3495             : }
    3496             : bool PseudoJet::contains(const PseudoJet &constituent) const{
    3497           0 :   return validated_structure_ptr()->object_in_jet(constituent, *this);
    3498             : }
    3499             : bool PseudoJet::is_inside(const PseudoJet &jet) const{
    3500           0 :   return validated_structure_ptr()->object_in_jet(*this, jet);
    3501             : }
    3502             : bool PseudoJet::has_constituents() const{
    3503           0 :   return (_structure()) && (_structure->has_constituents());
    3504             : }
    3505             : vector<PseudoJet> PseudoJet::constituents() const{
    3506           0 :   return validated_structure_ptr()->constituents(*this);
    3507             : }
    3508             : bool PseudoJet::has_exclusive_subjets() const{
    3509           0 :   return (_structure()) && (_structure->has_exclusive_subjets());
    3510             : }
    3511             : std::vector<PseudoJet> PseudoJet::exclusive_subjets (const double & dcut) const {
    3512           0 :   return validated_structure_ptr()->exclusive_subjets(*this, dcut);
    3513             : }
    3514             : int PseudoJet::n_exclusive_subjets(const double & dcut) const {
    3515           0 :   return validated_structure_ptr()->n_exclusive_subjets(*this, dcut);
    3516             : }
    3517             : std::vector<PseudoJet> PseudoJet::exclusive_subjets_up_to (int nsub) const {
    3518           0 :   return validated_structure_ptr()->exclusive_subjets_up_to(*this, nsub);
    3519             : }
    3520             : std::vector<PseudoJet> PseudoJet::exclusive_subjets (int nsub) const {
    3521           0 :   vector<PseudoJet> subjets = exclusive_subjets_up_to(nsub);
    3522           0 :   if (int(subjets.size()) < nsub) {
    3523           0 :     ostringstream err;
    3524           0 :     err << "Requested " << nsub << " exclusive subjets, but there were only "
    3525           0 :         << subjets.size() << " particles in the jet";
    3526           0 :     throw Error(err.str());
    3527           0 :   }
    3528             :   return subjets;
    3529           0 : }
    3530             : double PseudoJet::exclusive_subdmerge(int nsub) const {
    3531           0 :   return validated_structure_ptr()->exclusive_subdmerge(*this, nsub);
    3532             : }
    3533             : double PseudoJet::exclusive_subdmerge_max(int nsub) const {
    3534           0 :   return validated_structure_ptr()->exclusive_subdmerge_max(*this, nsub);
    3535             : }
    3536             : bool PseudoJet::has_pieces() const{
    3537           0 :   return ((_structure()) && (_structure->has_pieces(*this)));
    3538             : }
    3539             : std::vector<PseudoJet> PseudoJet::pieces() const{
    3540           0 :   return validated_structure_ptr()->pieces(*this);
    3541             : }
    3542           0 : PseudoJet::InexistentUserInfo::InexistentUserInfo() : Error("you attempted to perform a dynamic cast of a PseudoJet's extra info, but the extra info pointer was null")
    3543           0 : {}
    3544             : void sort_indices(vector<int> & indices,
    3545             :                          const vector<double> & values) {
    3546           0 :   IndexedSortHelper index_sort_helper(&values);
    3547           0 :   sort(indices.begin(), indices.end(), index_sort_helper);
    3548           0 : }
    3549             : template<class T> vector<T>  objects_sorted_by_values(
    3550             :                        const vector<T> & objects,
    3551             :                        const vector<double> & values) {
    3552           0 :   assert(objects.size() == values.size());
    3553           0 :   vector<int> indices(values.size());
    3554           0 :   for (size_t i = 0; i < indices.size(); i++) {indices[i] = i;}
    3555           0 :   sort_indices(indices, values);
    3556           0 :   vector<T> objects_sorted(objects.size());
    3557           0 :   for (size_t i = 0; i < indices.size(); i++) {
    3558           0 :     objects_sorted[i] = objects[indices[i]];
    3559             :   }
    3560             :   return objects_sorted;
    3561           0 : }
    3562             : vector<PseudoJet> sorted_by_pt(const vector<PseudoJet> & jets) {
    3563           0 :   vector<double> minus_kt2(jets.size());
    3564           0 :   for (size_t i = 0; i < jets.size(); i++) {minus_kt2[i] = -jets[i].kt2();}
    3565           0 :   return objects_sorted_by_values(jets, minus_kt2);
    3566           0 : }
    3567             : vector<PseudoJet> sorted_by_rapidity(const vector<PseudoJet> & jets) {
    3568           0 :   vector<double> rapidities(jets.size());
    3569           0 :   for (size_t i = 0; i < jets.size(); i++) {rapidities[i] = jets[i].rap();}
    3570           0 :   return objects_sorted_by_values(jets, rapidities);
    3571           0 : }
    3572             : vector<PseudoJet> sorted_by_E(const vector<PseudoJet> & jets) {
    3573           0 :   vector<double> energies(jets.size());
    3574           0 :   for (size_t i = 0; i < jets.size(); i++) {energies[i] = -jets[i].E();}
    3575           0 :   return objects_sorted_by_values(jets, energies);
    3576           0 : }
    3577             : vector<PseudoJet> sorted_by_pz(const vector<PseudoJet> & jets) {
    3578           0 :   vector<double> pz(jets.size());
    3579           0 :   for (size_t i = 0; i < jets.size(); i++) {pz[i] = jets[i].pz();}
    3580           0 :   return objects_sorted_by_values(jets, pz);
    3581           0 : }
    3582             : PseudoJet join(const vector<PseudoJet> & pieces){
    3583           0 :   PseudoJet result;  // automatically initialised to 0
    3584           0 :   for (unsigned int i=0; i<pieces.size(); i++)
    3585           0 :     result += pieces[i];
    3586           0 :   CompositeJetStructure *cj_struct = new CompositeJetStructure(pieces);
    3587           0 :   result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
    3588             :   return result;
    3589           0 : }
    3590             : PseudoJet join(const PseudoJet & j1){
    3591           0 :   return join(vector<PseudoJet>(1,j1));
    3592           0 : }
    3593             : PseudoJet join(const PseudoJet & j1, const PseudoJet & j2){
    3594           0 :   vector<PseudoJet> pieces;
    3595           0 :   pieces.push_back(j1);
    3596           0 :   pieces.push_back(j2);
    3597           0 :   return join(pieces);
    3598           0 : }
    3599             : PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3){
    3600           0 :   vector<PseudoJet> pieces;
    3601           0 :   pieces.push_back(j1);
    3602           0 :   pieces.push_back(j2);
    3603           0 :   pieces.push_back(j3);
    3604           0 :   return join(pieces);
    3605           0 : }
    3606             : PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4){
    3607           0 :   vector<PseudoJet> pieces;
    3608           0 :   pieces.push_back(j1);
    3609           0 :   pieces.push_back(j2);
    3610           0 :   pieces.push_back(j3);
    3611           0 :   pieces.push_back(j4);
    3612           0 :   return join(pieces);
    3613           0 : }
    3614             : FJCORE_END_NAMESPACE
    3615             : using namespace std;
    3616             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    3617             : const ClusterSequence* PseudoJetStructureBase::associated_cluster_sequence() const{
    3618           0 :   return NULL;
    3619             : }
    3620             : const ClusterSequence * PseudoJetStructureBase::validated_cs() const{
    3621           0 :   throw Error("This PseudoJet structure is not associated with a valid ClusterSequence");
    3622           0 : }
    3623             : bool PseudoJetStructureBase::has_partner(const PseudoJet & /*reference */, PseudoJet & /*partner*/) const{
    3624           0 :   throw Error("This PseudoJet structure has no implementation for has_partner");
    3625           0 : }
    3626             : bool PseudoJetStructureBase::has_child(const PseudoJet & /*reference*/, PseudoJet & /*child*/) const{
    3627           0 :   throw Error("This PseudoJet structure has no implementation for has_child");
    3628           0 : }
    3629             : bool PseudoJetStructureBase::has_parents(const PseudoJet & /*reference*/, PseudoJet &/*parent1*/, PseudoJet &/*parent2*/) const{
    3630           0 :   throw Error("This PseudoJet structure has no implementation for has_parents");
    3631           0 : }
    3632             : bool PseudoJetStructureBase::object_in_jet(const PseudoJet & /*reference*/, const PseudoJet & /*jet*/) const{
    3633           0 :   throw Error("This PseudoJet structure has no implementation for is_inside");
    3634           0 : }
    3635             : vector<PseudoJet> PseudoJetStructureBase::constituents(const PseudoJet &/*reference*/) const{
    3636           0 :   throw Error("This PseudoJet structure has no implementation for constituents");
    3637           0 : }
    3638             : vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets (const PseudoJet & /*reference*/, const double & /*dcut*/) const{
    3639           0 :   throw Error("This PseudoJet structure has no implementation for exclusive_subjets");
    3640           0 : }
    3641             : int PseudoJetStructureBase::n_exclusive_subjets(const PseudoJet & /*reference*/, const double & /*dcut*/) const{
    3642           0 :   throw Error("This PseudoJet structure has no implementation for n_exclusive_subjets");
    3643           0 : }
    3644             : vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets_up_to (const PseudoJet & /*reference*/, int /*nsub*/) const{
    3645           0 :   throw Error("This PseudoJet structure has no implementation for exclusive_subjets");
    3646           0 : }
    3647             : double PseudoJetStructureBase::exclusive_subdmerge(const PseudoJet & /*reference*/, int /*nsub*/) const{
    3648           0 :   throw Error("This PseudoJet structure has no implementation for exclusive_submerge");
    3649           0 : }
    3650             : double PseudoJetStructureBase::exclusive_subdmerge_max(const PseudoJet & /*reference*/, int /*nsub*/) const{
    3651           0 :   throw Error("This PseudoJet structure has no implementation for exclusive_submerge_max");
    3652           0 : }
    3653             : std::vector<PseudoJet> PseudoJetStructureBase::pieces(const PseudoJet & /*reference*/) const{
    3654           0 :   throw Error("This PseudoJet structure has no implementation for pieces");
    3655           0 : }
    3656             : FJCORE_END_NAMESPACE
    3657             : #include <sstream>
    3658             : #include <algorithm>
    3659             : using namespace std;
    3660             : FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
    3661             : std::vector<PseudoJet> Selector::operator()(const std::vector<PseudoJet> & jets) const {
    3662           0 :   std::vector<PseudoJet> result;
    3663           0 :   const SelectorWorker * worker_local = validated_worker();
    3664           0 :   if (worker_local->applies_jet_by_jet()) {
    3665           0 :     for (std::vector<PseudoJet>::const_iterator jet = jets.begin();
    3666           0 :          jet != jets.end(); jet++) {
    3667           0 :       if (worker_local->pass(*jet)) result.push_back(*jet);
    3668             :     }
    3669           0 :   } else {
    3670           0 :     std::vector<const PseudoJet *> jetptrs(jets.size());
    3671           0 :     for (unsigned i = 0; i < jets.size(); i++) {
    3672           0 :       jetptrs[i] = & jets[i];
    3673             :     }
    3674           0 :     worker_local->terminator(jetptrs);
    3675           0 :     for (unsigned i = 0; i < jetptrs.size(); i++) {
    3676           0 :       if (jetptrs[i]) result.push_back(jets[i]);
    3677             :     }
    3678           0 :   }
    3679             :   return result;
    3680           0 : }
    3681             : unsigned int Selector::count(const std::vector<PseudoJet> & jets) const {
    3682             :   unsigned n = 0;
    3683           0 :   const SelectorWorker * worker_local = validated_worker();
    3684           0 :   if (worker_local->applies_jet_by_jet()) {
    3685           0 :     for (unsigned i = 0; i < jets.size(); i++) {
    3686           0 :       if (worker_local->pass(jets[i])) n++;
    3687             :     }
    3688           0 :   } else {
    3689           0 :     std::vector<const PseudoJet *> jetptrs(jets.size());
    3690           0 :     for (unsigned i = 0; i < jets.size(); i++) {
    3691           0 :       jetptrs[i] = & jets[i];
    3692             :     }
    3693           0 :     worker_local->terminator(jetptrs);
    3694           0 :     for (unsigned i = 0; i < jetptrs.size(); i++) {
    3695           0 :       if (jetptrs[i]) n++;
    3696             :     }
    3697           0 :   }
    3698           0 :   return n;
    3699           0 : }
    3700             : void Selector::sift(const std::vector<PseudoJet> & jets,
    3701             :                     std::vector<PseudoJet> & jets_that_pass,
    3702             :                     std::vector<PseudoJet> & jets_that_fail
    3703             :                     ) const {
    3704           0 :   const SelectorWorker * worker_local = validated_worker();
    3705           0 :   jets_that_pass.clear();
    3706           0 :   jets_that_fail.clear();
    3707           0 :   if (worker_local->applies_jet_by_jet()) {
    3708           0 :     for (unsigned i = 0; i < jets.size(); i++) {
    3709           0 :       if (worker_local->pass(jets[i])) {
    3710           0 :         jets_that_pass.push_back(jets[i]);
    3711           0 :       } else {
    3712           0 :         jets_that_fail.push_back(jets[i]);
    3713             :       }
    3714             :     }
    3715           0 :   } else {
    3716           0 :     std::vector<const PseudoJet *> jetptrs(jets.size());
    3717           0 :     for (unsigned i = 0; i < jets.size(); i++) {
    3718           0 :       jetptrs[i] = & jets[i];
    3719             :     }
    3720           0 :     worker_local->terminator(jetptrs);
    3721           0 :     for (unsigned i = 0; i < jetptrs.size(); i++) {
    3722           0 :       if (jetptrs[i]) {
    3723           0 :         jets_that_pass.push_back(jets[i]);
    3724             :       } else {
    3725           0 :         jets_that_fail.push_back(jets[i]);
    3726             :       }
    3727             :     }
    3728           0 :   }
    3729           0 : }
    3730             : bool SelectorWorker::has_finite_area() const {
    3731           0 :   if (! is_geometric()) return false;
    3732           0 :   double rapmin, rapmax;
    3733           0 :   get_rapidity_extent(rapmin, rapmax);
    3734           0 :   return (rapmax != std::numeric_limits<double>::infinity())
    3735           0 :     &&  (-rapmin != std::numeric_limits<double>::infinity());
    3736           0 : }
    3737           0 : class SW_Identity : public SelectorWorker {
    3738             : public:
    3739           0 :   SW_Identity(){}
    3740             :   virtual bool pass(const PseudoJet &) const {
    3741           0 :     return true;
    3742             :   }
    3743             :   virtual void terminator(vector<const PseudoJet *> &) const {
    3744           0 :     return;
    3745             :   }
    3746           0 :   virtual string description() const { return "Identity";}
    3747           0 :   virtual bool is_geometric() const { return true;}
    3748             : };
    3749             : Selector SelectorIdentity() {
    3750           0 :   return Selector(new SW_Identity);
    3751           0 : }
    3752           0 : class SW_Not : public SelectorWorker {
    3753             : public:
    3754           0 :   SW_Not(const Selector & s) : _s(s) {}
    3755           0 :   virtual SelectorWorker* copy(){ return new SW_Not(*this);}
    3756             :   virtual bool pass(const PseudoJet & jet) const {
    3757           0 :     if (!applies_jet_by_jet())
    3758           0 :       throw Error("Cannot apply this selector worker to an individual jet");
    3759           0 :     return ! _s.pass(jet);
    3760           0 :   }
    3761           0 :   virtual bool applies_jet_by_jet() const {return _s.applies_jet_by_jet();}
    3762             :   virtual void terminator(vector<const PseudoJet *> & jets) const {
    3763           0 :     if (applies_jet_by_jet()){
    3764           0 :       SelectorWorker::terminator(jets);
    3765           0 :       return;
    3766             :     }
    3767           0 :     vector<const PseudoJet *> s_jets = jets;
    3768           0 :     _s.worker()->terminator(s_jets);
    3769           0 :     for (unsigned int i=0; i<s_jets.size(); i++){
    3770           0 :       if (s_jets[i]) jets[i] = NULL;
    3771             :     }
    3772           0 :   }
    3773             :   virtual string description() const {
    3774           0 :     ostringstream ostr;
    3775           0 :     ostr << "!(" << _s.description() << ")";
    3776           0 :     return ostr.str();
    3777           0 :   }
    3778           0 :   virtual bool is_geometric() const { return _s.is_geometric();}
    3779           0 :   virtual bool takes_reference() const { return _s.takes_reference();}
    3780           0 :   virtual void set_reference(const PseudoJet &ref) { _s.set_reference(ref);}
    3781             : protected:
    3782             :   Selector _s;
    3783             : };
    3784             : Selector operator!(const Selector & s) {
    3785           0 :   return Selector(new SW_Not(s));
    3786           0 : }
    3787           0 : class SW_BinaryOperator: public SelectorWorker {
    3788             : public:
    3789           0 :   SW_BinaryOperator(const Selector & s1, const Selector & s2) : _s1(s1), _s2(s2) {
    3790           0 :     _applies_jet_by_jet = _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
    3791           0 :     _takes_reference = _s1.takes_reference() || _s2.takes_reference();
    3792           0 :     _is_geometric = _s1.is_geometric() && _s2.is_geometric();
    3793           0 :   }
    3794           0 :   virtual bool applies_jet_by_jet() const {return _applies_jet_by_jet;}
    3795             :   virtual bool takes_reference() const{
    3796           0 :     return _takes_reference;
    3797             :   }
    3798             :   virtual void set_reference(const PseudoJet &centre){
    3799           0 :     _s1.set_reference(centre);
    3800           0 :     _s2.set_reference(centre);
    3801           0 :   }
    3802           0 :   virtual bool is_geometric() const { return _is_geometric;}
    3803             : protected:
    3804             :   Selector _s1, _s2;
    3805             :   bool _applies_jet_by_jet;
    3806             :   bool _takes_reference;
    3807             :   bool _is_geometric;
    3808             : };
    3809           0 : class SW_And: public SW_BinaryOperator {
    3810             : public:
    3811           0 :   SW_And(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2){}
    3812           0 :   virtual SelectorWorker* copy(){ return new SW_And(*this);}
    3813             :   virtual bool pass(const PseudoJet & jet) const {
    3814           0 :     if (!applies_jet_by_jet())
    3815           0 :       throw Error("Cannot apply this selector worker to an individual jet");
    3816           0 :     return _s1.pass(jet) && _s2.pass(jet);
    3817           0 :   }
    3818             :   virtual void terminator(vector<const PseudoJet *> & jets) const {
    3819           0 :     if (applies_jet_by_jet()){
    3820           0 :       SelectorWorker::terminator(jets);
    3821           0 :       return;
    3822             :     }
    3823           0 :     vector<const PseudoJet *> s1_jets = jets;
    3824           0 :     _s1.worker()->terminator(s1_jets);
    3825           0 :     _s2.worker()->terminator(jets);
    3826           0 :     for (unsigned int i=0; i<jets.size(); i++){
    3827           0 :       if (! s1_jets[i]) jets[i] = NULL;
    3828             :     }
    3829           0 :   }
    3830             :   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
    3831           0 :     double s1min, s1max, s2min, s2max;
    3832           0 :     _s1.get_rapidity_extent(s1min, s1max);
    3833           0 :     _s2.get_rapidity_extent(s2min, s2max);
    3834           0 :     rapmax = min(s1max, s2max);
    3835           0 :     rapmin = max(s1min, s2min);
    3836           0 :   }
    3837             :   virtual string description() const {
    3838           0 :     ostringstream ostr;
    3839           0 :     ostr << "(" << _s1.description() << " && " << _s2.description() << ")";
    3840           0 :     return ostr.str();
    3841           0 :   }
    3842             : };
    3843             : Selector operator&&(const Selector & s1, const Selector & s2) {
    3844           0 :   return Selector(new SW_And(s1,s2));
    3845           0 : }
    3846           0 : class SW_Or: public SW_BinaryOperator {
    3847             : public:
    3848           0 :   SW_Or(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2) {}
    3849           0 :   virtual SelectorWorker* copy(){ return new SW_Or(*this);}
    3850             :   virtual bool pass(const PseudoJet & jet) const {
    3851           0 :     if (!applies_jet_by_jet())
    3852           0 :       throw Error("Cannot apply this selector worker to an individual jet");
    3853           0 :     return _s1.pass(jet) || _s2.pass(jet);
    3854           0 :   }
    3855             :   virtual bool applies_jet_by_jet() const {
    3856           0 :     return _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
    3857             :   }
    3858             :   virtual void terminator(vector<const PseudoJet *> & jets) const {
    3859           0 :     if (applies_jet_by_jet()){
    3860           0 :       SelectorWorker::terminator(jets);
    3861           0 :       return;
    3862             :     }
    3863           0 :     vector<const PseudoJet *> s1_jets = jets;
    3864           0 :     _s1.worker()->terminator(s1_jets);
    3865           0 :     _s2.worker()->terminator(jets);
    3866           0 :     for (unsigned int i=0; i<jets.size(); i++){
    3867           0 :       if (s1_jets[i]) jets[i] = s1_jets[i];
    3868             :     }
    3869           0 :   }
    3870             :   virtual string description() const {
    3871           0 :     ostringstream ostr;
    3872           0 :     ostr << "(" << _s1.description() << " || " << _s2.description() << ")";
    3873           0 :     return ostr.str();
    3874           0 :   }
    3875             :   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
    3876           0 :     double s1min, s1max, s2min, s2max;
    3877           0 :     _s1.get_rapidity_extent(s1min, s1max);
    3878           0 :     _s2.get_rapidity_extent(s2min, s2max);
    3879           0 :     rapmax = max(s1max, s2max);
    3880           0 :     rapmin = min(s1min, s2min);
    3881           0 :   }
    3882             : };
    3883             : Selector operator ||(const Selector & s1, const Selector & s2) {
    3884           0 :   return Selector(new SW_Or(s1,s2));
    3885           0 : }
    3886           0 : class SW_Mult: public SW_And {
    3887             : public:
    3888           0 :   SW_Mult(const Selector & s1, const Selector & s2) : SW_And(s1,s2) {}
    3889           0 :   virtual SelectorWorker* copy(){ return new SW_Mult(*this);}
    3890             :   virtual void terminator(vector<const PseudoJet *> & jets) const {
    3891           0 :     if (applies_jet_by_jet()){
    3892           0 :       SelectorWorker::terminator(jets);
    3893           0 :       return;
    3894             :     }
    3895           0 :     _s2.worker()->terminator(jets);
    3896           0 :     _s1.worker()->terminator(jets);
    3897           0 :   }
    3898             :   virtual string description() const {
    3899           0 :     ostringstream ostr;
    3900           0 :     ostr << "(" << _s1.description() << " * " << _s2.description() << ")";
    3901           0 :     return ostr.str();
    3902           0 :   }
    3903             : };
    3904             : Selector operator*(const Selector & s1, const Selector & s2) {
    3905           0 :   return Selector(new SW_Mult(s1,s2));
    3906           0 : }
    3907             : class QuantityBase{
    3908             : public:
    3909           0 :   QuantityBase(double q) : _q(q){}
    3910           0 :   virtual ~QuantityBase(){}
    3911             :   virtual double operator()(const PseudoJet & jet ) const =0;
    3912             :   virtual string description() const =0;
    3913           0 :   virtual bool is_geometric() const { return false;}
    3914           0 :   virtual double comparison_value() const {return _q;}
    3915           0 :   virtual double description_value() const {return comparison_value();}
    3916             : protected:
    3917             :   double _q;
    3918             : };
    3919           0 : class QuantitySquareBase : public QuantityBase{
    3920             : public:
    3921           0 :   QuantitySquareBase(double sqrtq) : QuantityBase(sqrtq*sqrtq), _sqrtq(sqrtq){}
    3922           0 :   virtual double description_value() const {return _sqrtq;}
    3923             : protected:
    3924             :   double _sqrtq;
    3925             : };
    3926             : template<typename QuantityType>
    3927           0 : class SW_QuantityMin : public SelectorWorker{
    3928             : public:
    3929           0 :   SW_QuantityMin(double qmin) : _qmin(qmin) {}
    3930           0 :   virtual bool pass(const PseudoJet & jet) const {return _qmin(jet) >= _qmin.comparison_value();}
    3931             :   virtual string description() const {
    3932           0 :     ostringstream ostr;
    3933           0 :     ostr << _qmin.description() << " >= " << _qmin.description_value();
    3934           0 :     return ostr.str();
    3935           0 :   }
    3936           0 :   virtual bool is_geometric() const { return _qmin.is_geometric();}
    3937             : protected:
    3938             :   QuantityType _qmin;     ///< the cut
    3939             : };
    3940             : template<typename QuantityType>
    3941           0 : class SW_QuantityMax : public SelectorWorker {
    3942             : public:
    3943           0 :   SW_QuantityMax(double qmax) : _qmax(qmax) {}
    3944           0 :   virtual bool pass(const PseudoJet & jet) const {return _qmax(jet) <= _qmax.comparison_value();}
    3945             :   virtual string description() const {
    3946           0 :     ostringstream ostr;
    3947           0 :     ostr << _qmax.description() << " <= " << _qmax.description_value();
    3948           0 :     return ostr.str();
    3949           0 :   }
    3950           0 :   virtual bool is_geometric() const { return _qmax.is_geometric();}
    3951             : protected:
    3952             :   QuantityType _qmax;   ///< the cut
    3953             : };
    3954             : template<typename QuantityType>
    3955           0 : class SW_QuantityRange : public SelectorWorker {
    3956             : public:
    3957           0 :   SW_QuantityRange(double qmin, double qmax) : _qmin(qmin), _qmax(qmax) {}
    3958             :   virtual bool pass(const PseudoJet & jet) const {
    3959           0 :     double q = _qmin(jet); // we could identically use _qmax
    3960           0 :     return (q >= _qmin.comparison_value()) && (q <= _qmax.comparison_value());
    3961             :   }
    3962             :   virtual string description() const {
    3963           0 :     ostringstream ostr;
    3964           0 :     ostr << _qmin.description_value() << " <= " << _qmin.description() << " <= " << _qmax.description_value();
    3965           0 :     return ostr.str();
    3966           0 :   }
    3967           0 :   virtual bool is_geometric() const { return _qmin.is_geometric();}
    3968             : protected:
    3969             :   QuantityType _qmin;   // the lower cut
    3970             :   QuantityType _qmax;   // the upper cut
    3971             : };
    3972           0 : class QuantityPt2 : public QuantitySquareBase{
    3973             : public:
    3974           0 :   QuantityPt2(double pt) : QuantitySquareBase(pt){}
    3975           0 :   virtual double operator()(const PseudoJet & jet ) const { return jet.perp2();}
    3976           0 :   virtual string description() const {return "pt";}
    3977             : };
    3978             : Selector SelectorPtMin(double ptmin) {
    3979           0 :   return Selector(new SW_QuantityMin<QuantityPt2>(ptmin));
    3980           0 : }
    3981             : Selector SelectorPtMax(double ptmax) {
    3982           0 :   return Selector(new SW_QuantityMax<QuantityPt2>(ptmax));
    3983           0 : }
    3984             : Selector SelectorPtRange(double ptmin, double ptmax) {
    3985           0 :   return Selector(new SW_QuantityRange<QuantityPt2>(ptmin, ptmax));
    3986           0 : }
    3987           0 : class QuantityEt2 : public QuantitySquareBase{
    3988             : public:
    3989           0 :   QuantityEt2(double Et) : QuantitySquareBase(Et){}
    3990           0 :   virtual double operator()(const PseudoJet & jet ) const { return jet.Et2();}
    3991           0 :   virtual string description() const {return "Et";}
    3992             : };
    3993             : Selector SelectorEtMin(double Etmin) {
    3994           0 :   return Selector(new SW_QuantityMin<QuantityEt2>(Etmin));
    3995           0 : }
    3996             : Selector SelectorEtMax(double Etmax) {
    3997           0 :   return Selector(new SW_QuantityMax<QuantityEt2>(Etmax));
    3998           0 : }
    3999             : Selector SelectorEtRange(double Etmin, double Etmax) {
    4000           0 :   return Selector(new SW_QuantityRange<QuantityEt2>(Etmin, Etmax));
    4001           0 : }
    4002           0 : class QuantityE : public QuantityBase{
    4003             : public:
    4004           0 :   QuantityE(double E) : QuantityBase(E){}
    4005           0 :   virtual double operator()(const PseudoJet & jet ) const { return jet.E();}
    4006           0 :   virtual string description() const {return "E";}
    4007             : };
    4008             : Selector SelectorEMin(double Emin) {
    4009           0 :   return Selector(new SW_QuantityMin<QuantityE>(Emin));
    4010           0 : }
    4011             : Selector SelectorEMax(double Emax) {
    4012           0 :   return Selector(new SW_QuantityMax<QuantityE>(Emax));
    4013           0 : }
    4014             : Selector SelectorERange(double Emin, double Emax) {
    4015           0 :   return Selector(new SW_QuantityRange<QuantityE>(Emin, Emax));
    4016           0 : }
    4017           0 : class QuantityM2 : public QuantitySquareBase{
    4018             : public:
    4019           0 :   QuantityM2(double m) : QuantitySquareBase(m){}
    4020           0 :   virtual double operator()(const PseudoJet & jet ) const { return jet.m2();}
    4021           0 :   virtual string description() const {return "mass";}
    4022             : };
    4023             : Selector SelectorMassMin(double mmin) {
    4024           0 :   return Selector(new SW_QuantityMin<QuantityM2>(mmin));
    4025           0 : }
    4026             : Selector SelectorMassMax(double mmax) {
    4027           0 :   return Selector(new SW_QuantityMax<QuantityM2>(mmax));
    4028           0 : }
    4029             : Selector SelectorMassRange(double mmin, double mmax) {
    4030           0 :   return Selector(new SW_QuantityRange<QuantityM2>(mmin, mmax));
    4031           0 : }
    4032           0 : class QuantityRap : public QuantityBase{
    4033             : public:
    4034           0 :   QuantityRap(double rap) : QuantityBase(rap){}
    4035           0 :   virtual double operator()(const PseudoJet & jet ) const { return jet.rap();}
    4036           0 :   virtual string description() const {return "rap";}
    4037           0 :   virtual bool is_geometric() const { return true;}
    4038             : };
    4039           0 : class SW_RapMin : public SW_QuantityMin<QuantityRap>{
    4040             : public:
    4041           0 :   SW_RapMin(double rapmin) : SW_QuantityMin<QuantityRap>(rapmin){}
    4042             :   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
    4043           0 :     rapmax = std::numeric_limits<double>::max();
    4044           0 :     rapmin = _qmin.comparison_value();
    4045           0 :   }
    4046             : };
    4047           0 : class SW_RapMax : public SW_QuantityMax<QuantityRap>{
    4048             : public:
    4049           0 :   SW_RapMax(double rapmax) : SW_QuantityMax<QuantityRap>(rapmax){}
    4050             :   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
    4051           0 :     rapmax = _qmax.comparison_value();
    4052           0 :     rapmin = -std::numeric_limits<double>::max();
    4053           0 :   }
    4054             : };
    4055           0 : class SW_RapRange : public SW_QuantityRange<QuantityRap>{
    4056             : public:
    4057           0 :   SW_RapRange(double rapmin, double rapmax) : SW_QuantityRange<QuantityRap>(rapmin, rapmax){
    4058           0 :     assert(rapmin<=rapmax);
    4059           0 :   }
    4060             :   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
    4061           0 :     rapmax = _qmax.comparison_value();
    4062           0 :     rapmin = _qmin.comparison_value();
    4063           0 :   }
    4064           0 :   virtual bool has_known_area() const { return true;} ///< the area is analytically known
    4065             :   virtual double known_area() const {
    4066           0 :     return twopi * (_qmax.comparison_value()-_qmin.comparison_value());
    4067             :   }
    4068             : };
    4069             : Selector SelectorRapMin(double rapmin) {
    4070           0 :   return Selector(new SW_RapMin(rapmin));
    4071           0 : }
    4072             : Selector SelectorRapMax(double rapmax) {
    4073           0 :   return Selector(new SW_RapMax(rapmax));
    4074           0 : }
    4075             : Selector SelectorRapRange(double rapmin, double rapmax) {
    4076           0 :   return Selector(new SW_RapRange(rapmin, rapmax));
    4077           0 : }
    4078           0 : class QuantityAbsRap : public QuantityBase{
    4079             : public:
    4080           0 :   QuantityAbsRap(double absrap) : QuantityBase(absrap){}
    4081           0 :   virtual double operator()(const PseudoJet & jet ) const { return abs(jet.rap());}
    4082           0 :   virtual string description() const {return "|rap|";}
    4083           0 :   virtual bool is_geometric() const { return true;}
    4084             : };
    4085           0 : class SW_AbsRapMax : public SW_QuantityMax<QuantityAbsRap>{
    4086             : public:
    4087           0 :   SW_AbsRapMax(double absrapmax) : SW_QuantityMax<QuantityAbsRap>(absrapmax){}
    4088             :   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
    4089           0 :     rapmax =  _qmax.comparison_value();
    4090           0 :     rapmin = -_qmax.comparison_value();
    4091           0 :   }
    4092           0 :   virtual bool has_known_area() const { return true;}   ///< the area is analytically known
    4093             :   virtual double known_area() const {
    4094           0 :     return twopi * 2 * _qmax.comparison_value();
    4095             :   }
    4096             : };
    4097           0 : class SW_AbsRapRange : public SW_QuantityRange<QuantityAbsRap>{
    4098             : public:
    4099           0 :   SW_AbsRapRange(double absrapmin, double absrapmax) : SW_QuantityRange<QuantityAbsRap>(absrapmin, absrapmax){}
    4100             :   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
    4101           0 :     rapmax =  _qmax.comparison_value();
    4102           0 :     rapmin = -_qmax.comparison_value();
    4103           0 :   }
    4104           0 :   virtual bool has_known_area() const { return true;} ///< the area is analytically known
    4105             :   virtual double known_area() const {
    4106           0 :     return twopi * 2 * (_qmax.comparison_value()-max(_qmin.comparison_value(),0.0)); // this should handle properly absrapmin<0
    4107             :   }
    4108             : };
    4109             : Selector SelectorAbsRapMin(double absrapmin) {
    4110           0 :   return Selector(new SW_QuantityMin<QuantityAbsRap>(absrapmin));
    4111           0 : }
    4112             : Selector SelectorAbsRapMax(double absrapmax) {
    4113           0 :   return Selector(new SW_AbsRapMax(absrapmax));
    4114           0 : }
    4115             : Selector SelectorAbsRapRange(double rapmin, double rapmax) {
    4116           0 :   return Selector(new SW_AbsRapRange(rapmin, rapmax));
    4117           0 : }
    4118           0 : class QuantityEta : public QuantityBase{
    4119             : public:
    4120           0 :   QuantityEta(double eta) : QuantityBase(eta){}
    4121           0 :   virtual double operator()(const PseudoJet & jet ) const { return jet.eta();}
    4122           0 :   virtual string description() const {return "eta";}
    4123             : };
    4124             : Selector SelectorEtaMin(double etamin) {
    4125           0 :   return Selector(new SW_QuantityMin<QuantityEta>(etamin));
    4126           0 : }
    4127             : Selector SelectorEtaMax(double etamax) {
    4128           0 :   return Selector(new SW_QuantityMax<QuantityEta>(etamax));
    4129           0 : }
    4130             : Selector SelectorEtaRange(double etamin, double etamax) {
    4131           0 :   return Selector(new SW_QuantityRange<QuantityEta>(etamin, etamax));
    4132           0 : }
    4133           0 : class QuantityAbsEta : public QuantityBase{
    4134             : public:
    4135           0 :   QuantityAbsEta(double abseta) : QuantityBase(abseta){}
    4136           0 :   virtual double operator()(const PseudoJet & jet ) const { return abs(jet.eta());}
    4137           0 :   virtual string description() const {return "|eta|";}
    4138           0 :   virtual bool is_geometric() const { return true;}
    4139             : };
    4140             : Selector SelectorAbsEtaMin(double absetamin) {
    4141           0 :   return Selector(new SW_QuantityMin<QuantityAbsEta>(absetamin));
    4142           0 : }
    4143             : Selector SelectorAbsEtaMax(double absetamax) {
    4144           0 :   return Selector(new SW_QuantityMax<QuantityAbsEta>(absetamax));
    4145           0 : }
    4146             : Selector SelectorAbsEtaRange(double absetamin, double absetamax) {
    4147           0 :   return Selector(new SW_QuantityRange<QuantityAbsEta>(absetamin, absetamax));
    4148           0 : }
    4149           0 : class SW_PhiRange : public SelectorWorker {
    4150             : public:
    4151           0 :   SW_PhiRange(double phimin, double phimax) : _phimin(phimin), _phimax(phimax){
    4152           0 :     assert(_phimin<_phimax);
    4153           0 :     assert(_phimin>-twopi);
    4154           0 :     assert(_phimax<2*twopi);
    4155           0 :     _phispan = _phimax - _phimin;
    4156           0 :   }
    4157             :   virtual bool pass(const PseudoJet & jet) const {
    4158           0 :     double dphi=jet.phi()-_phimin;
    4159           0 :     if (dphi >= twopi) dphi -= twopi;
    4160           0 :     if (dphi < 0)      dphi += twopi;
    4161           0 :     return (dphi <= _phispan);
    4162             :   }
    4163             :   virtual string description() const {
    4164           0 :     ostringstream ostr;
    4165           0 :     ostr << _phimin << " <= phi <= " << _phimax;
    4166           0 :     return ostr.str();
    4167           0 :   }
    4168           0 :   virtual bool is_geometric() const { return true;}
    4169             : protected:
    4170             :   double _phimin;   // the lower cut
    4171             :   double _phimax;   // the upper cut
    4172             :   double _phispan;  // the span of the range
    4173             : };
    4174             : Selector SelectorPhiRange(double phimin, double phimax) {
    4175           0 :   return Selector(new SW_PhiRange(phimin, phimax));
    4176           0 : }
    4177           0 : class SW_RapPhiRange : public SW_And{
    4178             : public:
    4179             :   SW_RapPhiRange(double rapmin, double rapmax, double phimin, double phimax)
    4180           0 :     : SW_And(SelectorRapRange(rapmin, rapmax), SelectorPhiRange(phimin, phimax)){
    4181           0 :     _known_area = ((phimax-phimin > twopi) ? twopi : phimax-phimin) * (rapmax-rapmin);
    4182           0 :   }
    4183             :   virtual double known_area() const{
    4184           0 :     return _known_area;
    4185             :   }
    4186             : protected:
    4187             :   double _known_area;
    4188             : };
    4189             : Selector SelectorRapPhiRange(double rapmin, double rapmax, double phimin, double phimax) {
    4190           0 :   return Selector(new SW_RapPhiRange(rapmin, rapmax, phimin, phimax));
    4191           0 : }
    4192           0 : class SW_NHardest : public SelectorWorker {
    4193             : public:
    4194           0 :   SW_NHardest(unsigned int n) : _n(n) {};
    4195             :   virtual bool pass(const PseudoJet &) const {
    4196           0 :     if (!applies_jet_by_jet())
    4197           0 :       throw Error("Cannot apply this selector worker to an individual jet");
    4198           0 :     return false;
    4199           0 :   }
    4200             :   virtual void terminator(vector<const PseudoJet *> & jets) const {
    4201           0 :     if (jets.size() < _n) return;
    4202           0 :     vector<double> minus_pt2(jets.size());
    4203           0 :     vector<unsigned int> indices(jets.size());
    4204           0 :     for (unsigned int i=0; i<jets.size(); i++){
    4205           0 :       indices[i] = i;
    4206           0 :       minus_pt2[i] = jets[i] ? -jets[i]->perp2() : 0.0;
    4207             :     }
    4208           0 :     IndexedSortHelper sort_helper(& minus_pt2);
    4209           0 :     partial_sort(indices.begin(), indices.begin()+_n, indices.end(), sort_helper);
    4210           0 :     for (unsigned int i=_n; i<jets.size(); i++)
    4211           0 :       jets[indices[i]] = NULL;
    4212           0 :   }
    4213           0 :   virtual bool applies_jet_by_jet() const {return false;}
    4214             :   virtual string description() const {
    4215           0 :     ostringstream ostr;
    4216           0 :     ostr << _n << " hardest";
    4217           0 :     return ostr.str();
    4218           0 :   }
    4219             : protected:
    4220             :   unsigned int _n;
    4221             : };
    4222             : Selector SelectorNHardest(unsigned int n) {
    4223           0 :   return Selector(new SW_NHardest(n));
    4224           0 : }
    4225           0 : class SW_WithReference : public SelectorWorker{
    4226             : public:
    4227           0 :   SW_WithReference() : _is_initialised(false){};
    4228           0 :   virtual bool takes_reference() const { return true;}
    4229             :   virtual void set_reference(const PseudoJet &centre){
    4230           0 :     _is_initialised = true;
    4231           0 :     _reference = centre;
    4232           0 :   }
    4233             : protected:
    4234             :   PseudoJet _reference;
    4235             :   bool _is_initialised;
    4236             : };
    4237           0 : class SW_Circle : public SW_WithReference {
    4238             : public:
    4239           0 :   SW_Circle(const double &radius) : _radius2(radius*radius) {}
    4240           0 :   virtual SelectorWorker* copy(){ return new SW_Circle(*this);}
    4241             :   virtual bool pass(const PseudoJet & jet) const {
    4242           0 :     if (! _is_initialised)
    4243           0 :       throw Error("To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
    4244           0 :     return jet.squared_distance(_reference) <= _radius2;
    4245           0 :   }
    4246             :   virtual string description() const {
    4247           0 :     ostringstream ostr;
    4248           0 :     ostr << "distance from the centre <= " << sqrt(_radius2);
    4249           0 :     return ostr.str();
    4250           0 :   }
    4251             :   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
    4252           0 :     if (! _is_initialised)
    4253           0 :       throw Error("To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
    4254           0 :     rapmax = _reference.rap()+sqrt(_radius2);
    4255           0 :     rapmin = _reference.rap()-sqrt(_radius2);
    4256           0 :   }
    4257           0 :   virtual bool is_geometric() const { return true;}    ///< implies a finite area
    4258           0 :   virtual bool has_finite_area() const { return true;} ///< regardless of the reference
    4259           0 :   virtual bool has_known_area() const { return true;}  ///< the area is analytically known
    4260             :   virtual double known_area() const {
    4261           0 :     return pi * _radius2;
    4262             :   }
    4263             : protected:
    4264             :   double _radius2;
    4265             : };
    4266             : Selector SelectorCircle(const double & radius) {
    4267           0 :   return Selector(new SW_Circle(radius));
    4268           0 : }
    4269           0 : class SW_Doughnut : public SW_WithReference {
    4270             : public:
    4271           0 :   SW_Doughnut(const double &radius_in, const double &radius_out)
    4272           0 :     : _radius_in2(radius_in*radius_in), _radius_out2(radius_out*radius_out) {}
    4273           0 :   virtual SelectorWorker* copy(){ return new SW_Doughnut(*this);}
    4274             :   virtual bool pass(const PseudoJet & jet) const {
    4275           0 :     if (! _is_initialised)
    4276           0 :       throw Error("To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
    4277           0 :     double distance2 = jet.squared_distance(_reference);
    4278           0 :     return (distance2 <= _radius_out2) && (distance2 >= _radius_in2);
    4279           0 :   }
    4280             :   virtual string description() const {
    4281           0 :     ostringstream ostr;
    4282           0 :     ostr << sqrt(_radius_in2) << " <= distance from the centre <= " << sqrt(_radius_out2);
    4283           0 :     return ostr.str();
    4284           0 :   }
    4285             :   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
    4286           0 :     if (! _is_initialised)
    4287           0 :       throw Error("To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
    4288           0 :     rapmax = _reference.rap()+sqrt(_radius_out2);
    4289           0 :     rapmin = _reference.rap()-sqrt(_radius_out2);
    4290           0 :   }
    4291           0 :   virtual bool is_geometric() const { return true;}    ///< implies a finite area
    4292           0 :   virtual bool has_finite_area() const { return true;} ///< regardless of the reference
    4293           0 :   virtual bool has_known_area() const { return true;}  ///< the area is analytically known
    4294             :   virtual double known_area() const {
    4295           0 :     return pi * (_radius_out2-_radius_in2);
    4296             :   }
    4297             : protected:
    4298             :   double _radius_in2, _radius_out2;
    4299             : };
    4300             : Selector SelectorDoughnut(const double & radius_in, const double & radius_out) {
    4301           0 :   return Selector(new SW_Doughnut(radius_in, radius_out));
    4302           0 : }
    4303           0 : class SW_Strip : public SW_WithReference {
    4304             : public:
    4305           0 :   SW_Strip(const double &delta) : _delta(delta) {}
    4306           0 :   virtual SelectorWorker* copy(){ return new SW_Strip(*this);}
    4307             :   virtual bool pass(const PseudoJet & jet) const {
    4308           0 :     if (! _is_initialised)
    4309           0 :       throw Error("To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
    4310           0 :     return abs(jet.rap()-_reference.rap()) <= _delta;
    4311           0 :   }
    4312             :   virtual string description() const {
    4313           0 :     ostringstream ostr;
    4314           0 :     ostr << "|rap - rap_reference| <= " << _delta;
    4315           0 :     return ostr.str();
    4316           0 :   }
    4317             :   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
    4318           0 :     if (! _is_initialised)
    4319           0 :       throw Error("To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
    4320           0 :     rapmax = _reference.rap()+_delta;
    4321           0 :     rapmin = _reference.rap()-_delta;
    4322           0 :   }
    4323           0 :   virtual bool is_geometric() const { return true;}    ///< implies a finite area
    4324           0 :   virtual bool has_finite_area() const { return true;} ///< regardless of the reference
    4325           0 :   virtual bool has_known_area() const { return true;}  ///< the area is analytically known
    4326             :   virtual double known_area() const {
    4327           0 :     return twopi * 2 * _delta;
    4328             :   }
    4329             : protected:
    4330             :   double _delta;
    4331             : };
    4332             : Selector SelectorStrip(const double & half_width) {
    4333           0 :   return Selector(new SW_Strip(half_width));
    4334           0 : }
    4335           0 : class SW_Rectangle : public SW_WithReference {
    4336             : public:
    4337           0 :   SW_Rectangle(const double &delta_rap, const double &delta_phi)
    4338           0 :     : _delta_rap(delta_rap),  _delta_phi(delta_phi) {}
    4339           0 :   virtual SelectorWorker* copy(){ return new SW_Rectangle(*this);}
    4340             :   virtual bool pass(const PseudoJet & jet) const {
    4341           0 :     if (! _is_initialised)
    4342           0 :       throw Error("To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
    4343           0 :     return (abs(jet.rap()-_reference.rap()) <= _delta_rap) && (abs(jet.delta_phi_to(_reference)) <= _delta_phi);
    4344           0 :   }
    4345             :   virtual string description() const {
    4346           0 :     ostringstream ostr;
    4347           0 :     ostr << "|rap - rap_reference| <= " << _delta_rap << " && |phi - phi_reference| <= " << _delta_phi ;
    4348           0 :     return ostr.str();
    4349           0 :   }
    4350             :   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
    4351           0 :     if (! _is_initialised)
    4352           0 :       throw Error("To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
    4353           0 :     rapmax = _reference.rap()+_delta_rap;
    4354           0 :     rapmin = _reference.rap()-_delta_rap;
    4355           0 :   }
    4356           0 :   virtual bool is_geometric() const { return true;}    ///< implies a finite area
    4357           0 :   virtual bool has_finite_area() const { return true;} ///< regardless of the reference
    4358           0 :   virtual bool has_known_area() const { return true;}  ///< the area is analytically known
    4359             :   virtual double known_area() const {
    4360           0 :     return 4 * _delta_rap * _delta_phi;
    4361             :   }
    4362             : protected:
    4363             :   double _delta_rap, _delta_phi;
    4364             : };
    4365             : Selector SelectorRectangle(const double & half_rap_width, const double & half_phi_width) {
    4366           0 :   return Selector(new SW_Rectangle(half_rap_width, half_phi_width));
    4367           0 : }
    4368           0 : class SW_PtFractionMin : public SW_WithReference {
    4369             : public:
    4370           0 :   SW_PtFractionMin(double fraction) : _fraction2(fraction*fraction){}
    4371           0 :   virtual SelectorWorker* copy(){ return new SW_PtFractionMin(*this);}
    4372             :   virtual bool pass(const PseudoJet & jet) const {
    4373           0 :     if (! _is_initialised)
    4374           0 :       throw Error("To use a SelectorPtFractionMin (or any selector that requires a reference), you first have to call set_reference(...)");
    4375           0 :     return (jet.perp2() >= _fraction2*_reference.perp2());
    4376           0 :   }
    4377             :   virtual string description() const {
    4378           0 :     ostringstream ostr;
    4379           0 :     ostr << "pt >= " << sqrt(_fraction2) << "* pt_ref";
    4380           0 :     return ostr.str();
    4381           0 :   }
    4382             : protected:
    4383             :   double _fraction2;
    4384             : };
    4385             : Selector SelectorPtFractionMin(double fraction){
    4386           0 :   return Selector(new SW_PtFractionMin(fraction));
    4387           0 : }
    4388           0 : class SW_IsZero : public SelectorWorker {
    4389             : public:
    4390           0 :   SW_IsZero(){}
    4391             :   virtual bool pass(const PseudoJet & jet) const {
    4392           0 :     return jet==0;
    4393             :   }
    4394           0 :   virtual string description() const { return "zero";}
    4395             : };
    4396             : Selector SelectorIsZero(){
    4397           0 :   return Selector(new SW_IsZero());
    4398           0 : }
    4399             : Selector & Selector::operator &=(const Selector & b){
    4400           0 :   _worker.reset(new SW_And(*this, b));
    4401           0 :   return *this;
    4402           0 : }
    4403             : Selector & Selector::operator |=(const Selector & b){
    4404           0 :   _worker.reset(new SW_Or(*this, b));
    4405           0 :   return *this;
    4406           0 : }
    4407             : FJCORE_END_NAMESPACE      // defined in fastjet/internal/base.hh

Generated by: LCOV version 1.11