Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:48:40

0001 // fjcore -- extracted from FastJet v3.5.1 (https://fastjet.fr)
0002 //
0003 // fjcore constitutes a digest of the main FastJet functionality.
0004 // The files fjcore.hh and fjcore.cc are meant to provide easy access to these 
0005 // core functions, in the form of single files and without the need of a full 
0006 // FastJet installation:
0007 //
0008 //     g++ main.cc fjcore.cc
0009 // 
0010 // with main.cc including fjcore.hh.
0011 //
0012 // A fortran interface, fjcorefortran.cc, is also provided. See the example 
0013 // and the Makefile for instructions.
0014 //
0015 // The results are expected to be identical to those obtained by linking to
0016 // the full FastJet distribution.
0017 //
0018 // NOTE THAT, IN ORDER TO MAKE IT POSSIBLE FOR FJCORE AND THE FULL FASTJET
0019 // TO COEXIST, THE FORMER USES THE "fjcore" NAMESPACE INSTEAD OF "fastjet". 
0020 //
0021 // In particular, fjcore provides:
0022 //
0023 //   - access to all native pp and ee algorithms, kt, anti-kt, C/A.
0024 //     For C/A, the NlnN method is available, while anti-kt and kt
0025 //     are limited to the N^2 one (still the fastest for N < 100k particles)
0026 //   - access to selectors, for implementing cuts and selections
0027 //   - access to all functionalities related to pseudojets (e.g. a jet's
0028 //     structure or user-defined information)
0029 //
0030 // Instead, it does NOT provide:
0031 //
0032 //   - jet areas functionality
0033 //   - background estimation
0034 //   - access to other algorithms via plugins
0035 //   - interface to CGAL
0036 //   - fastjet tools, e.g. filters, taggers
0037 //
0038 // If these functionalities are needed, the full FastJet installation must be
0039 // used. The code will be fully compatible, with the sole replacement of the
0040 // header files and of the fjcore namespace with the fastjet one.
0041 //
0042 // fjcore.hh and fjcore.cc are not meant to be human-readable.
0043 // For documentation, see the full FastJet manual and doxygen at https://fastjet.fr
0044 //
0045 // Like FastJet, fjcore is released under the terms of the GNU General Public
0046 // License version 2 (GPLv2) or later. If you use this code as part of work towards a
0047 // scientific publication, whether directly or contained within another program
0048 // (e.g. Pythia, MadGraph, Sherpa, POWHEGBox, Rivet, LHC collaboration software frameworks, 
0049 // etc.), you should include a citation to
0050 // 
0051 //   EPJC72(2012)1896 [arXiv:1111.6097] (FastJet User Manual)
0052 //   and, optionally, Phys.Lett.B641 (2006) 57 [arXiv:hep-ph/0512210]
0053 //
0054 //FJSTARTHEADER
0055 // $Id$
0056 //
0057 // Copyright (c) 2005-2025, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
0058 //
0059 //----------------------------------------------------------------------
0060 // This file is part of FastJet (fjcore).
0061 //
0062 //  FastJet is free software; you can redistribute it and/or modify
0063 //  it under the terms of the GNU General Public License as published by
0064 //  the Free Software Foundation; either version 2 of the License, or
0065 //  (at your option) any later version.
0066 //
0067 //  The algorithms that underlie FastJet have required considerable
0068 //  development. They are described in the original FastJet paper,
0069 //  hep-ph/0512210 and in the manual, arXiv:1111.6097. If you use
0070 //  FastJet as part of work towards a scientific publication, please
0071 //  quote the version you use and include a citation to the manual and
0072 //  optionally also to hep-ph/0512210.
0073 //
0074 //  FastJet is distributed in the hope that it will be useful,
0075 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
0076 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0077 //  GNU General Public License for more details.
0078 //
0079 //  You should have received a copy of the GNU General Public License
0080 //  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
0081 //----------------------------------------------------------------------
0082 //FJENDHEADER
0083 #ifndef __FJCORE_HH__
0084 #define __FJCORE_HH__
0085 #define __FJCORE_ONLY_CORE__  // remove all the non-core code (a safekeeper)
0086 #define __FJCORE_DROP_CGAL    // disable CGAL support
0087 #undef FJCORE_PACKAGE
0088 #undef FJCORE_PACKAGE_BUGREPORT
0089 #define FJCORE_PACKAGE_NAME "FastJet"
0090 #undef FJCORE_PACKAGE_STRING
0091 #undef FJCORE_PACKAGE_TARNAME
0092 #undef FJCORE_PACKAGE_URL
0093 #define FJCORE_PACKAGE_VERSION "3.5.1"
0094 #define FJCORE_VERSION "3.5.1"
0095 #define FJCORE_VERSION_MAJOR 3
0096 #define FJCORE_VERSION_MINOR 5
0097 #define FJCORE_VERSION_PATCHLEVEL 1
0098 #define FJCORE_VERSION_PRERELEASE 
0099 #define FJCORE_VERSION_NUMBER 30501
0100 #define FJCORE_ENABLE_PLUGIN_CDFCONES
0101 #define FJCORE_ENABLE_PLUGIN_EECAMBRIDGE
0102 #define FJCORE_ENABLE_PLUGIN_GRIDJET
0103 #define FJCORE_ENABLE_PLUGIN_JADE
0104 #define FJCORE_ENABLE_PLUGIN_NESTEDDEFS
0105 #define FJCORE_ENABLE_PLUGIN_SISCONE
0106 #ifndef FJCORE_ENABLE_CGAL
0107 #define __FJCORE_DROP_CGAL
0108 #endif
0109 #define FJCORE_ENABLE_DEBUG
0110 #ifndef __FJCORE_CONFIG_H__
0111 #define __FJCORE_CONFIG_H__
0112 #ifdef _WIN32
0113     #if defined(fjcore_EXPORTS)
0114         #define FJCORE_WINDLL __declspec(dllexport) // Export when building the DLL
0115     #else
0116         #define FJCORE_WINDLL __declspec(dllimport) // Import when using the DLL
0117     #endif
0118     #if defined(fjcore_EXPORTS)
0119         #define FJCORE_TOOLS_WINDLL __declspec(dllexport) // Export when building the DLL
0120     #else
0121         #define FJCORE_TOOLS_WINDLL __declspec(dllimport) // Import when using the DLL
0122     #endif
0123     #if defined(fjcore_EXPORTS)
0124         #define FJCORE_PLUGINS_WINDLL __declspec(dllexport) // Export when building the DLL
0125     #else
0126         #define FJCORE_PLUGINS_WINDLL __declspec(dllimport) // Import when using the DLL
0127     #endif
0128 #else
0129     #define FJCORE_WINDLL
0130     #define FJCORE_TOOLS_WINDLL
0131     #define FJCORE_PLUGINS_WINDLL
0132 #endif
0133 #endif // __FJCORE_CONFIG_H__
0134 #ifndef __FJCORE_FASTJET_BASE_HH__
0135 #define __FJCORE_FASTJET_BASE_HH__
0136 #define FJCORE_BEGIN_NAMESPACE namespace fjcore {
0137 #define FJCORE_END_NAMESPACE   }
0138 #ifdef FJCORE_HAVE_OVERRIDE
0139 #define FJCORE_OVERRIDE  override
0140 #else
0141 #define FJCORE_OVERRIDE  
0142 #endif
0143 #endif // __FJCORE_FASTJET_BASE_HH__
0144 #ifndef __FJCORE_THREAD_SAFETY_HELPERS_HH__
0145 #define __FJCORE_THREAD_SAFETY_HELPERS_HH__
0146 #include <limits>
0147 #ifdef FJCORE_HAVE_LIMITED_THREAD_SAFETY
0148 #include <atomic>
0149 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0150 namespace thread_safety_helpers{
0151   template<typename T>
0152   class AtomicCounter{
0153   public:
0154     AtomicCounter() : _count{0}{}
0155     AtomicCounter(const T &count) : _count{count}{}
0156     AtomicCounter(const AtomicCounter &other) : _count{other._count.load()}{}
0157     operator T() const{ return _count.load();}
0158     T get() const{ return _count.load();}
0159     void set(const T new_value){
0160       _count.store(new_value);
0161     }
0162     T step(){
0163       T count = _count;
0164       while (_count < std::numeric_limits<T>::max()
0165              && !(_count.compare_exchange_strong(count, count+1)));
0166       return count;
0167     }
0168     inline T operator++(){
0169       return step()+1;
0170     }
0171     inline T operator++(int){
0172       return step();
0173     }
0174   private:
0175     std::atomic<T> _count;  ///< the actual count
0176   };
0177   class FirstTimeTrue{
0178   public:
0179     FirstTimeTrue(): _first_time{true}{}
0180     FirstTimeTrue(const FirstTimeTrue &other) : _first_time{other._first_time.load()}{}
0181     bool operator()(){
0182       bool expected = true;
0183       return _first_time.compare_exchange_strong(expected, false,
0184                                                  std::memory_order_seq_cst,
0185                                                  std::memory_order_relaxed);
0186     }
0187   private:
0188     std::atomic<bool> _first_time;
0189   };
0190 } // namespace thread_safety_helpers
0191 FJCORE_END_NAMESPACE
0192 #else  // FJ wo thread-safety features
0193 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0194 namespace thread_safety_helpers{
0195   template<typename T>
0196   class AtomicCounter{
0197   public:
0198     AtomicCounter() : _count(0){}
0199     AtomicCounter(const T &count) : _count(count){}
0200     AtomicCounter(const AtomicCounter &other) : _count(other._count){}
0201     operator T() const{ return _count;}
0202     T get() const{ return _count;}
0203     void set(const T new_value){
0204       _count = new_value;
0205     }
0206     T step(){
0207       unsigned int count = _count;
0208       if (_count < std::numeric_limits<T>::max()){ _count++; }
0209       return count;
0210     }
0211     inline T operator++(){
0212       return step()+1;
0213     }
0214     inline T operator++(int){
0215       return step();
0216     }
0217   private:
0218     T _count;  ///< the actual value
0219   };
0220   class FirstTimeTrue{
0221   public:
0222     FirstTimeTrue(): _first_time(true){}
0223     bool operator()(){
0224       if (!_first_time) {return false;}
0225       _first_time = false;
0226       return true;
0227     }
0228   private:
0229     bool _first_time;
0230   };
0231 } // namespace thread_safety_helpers
0232 FJCORE_END_NAMESPACE
0233 #endif // FJCORE_HAVE_LIMITED_THREAD_SAFETY
0234 #endif // __FJCORE_THREAD_SAFETY_HELPERS_HH__
0235 #ifndef __FJCORE_NUMCONSTS__
0236 #define __FJCORE_NUMCONSTS__
0237 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0238 const double pi = 3.141592653589793238462643383279502884197;
0239 const double twopi = 6.283185307179586476925286766559005768394;
0240 const double pisq  = 9.869604401089358618834490999876151135314;
0241 const double zeta2 = 1.644934066848226436472415166646025189219;
0242 const double zeta3 = 1.202056903159594285399738161511449990765;
0243 const double eulergamma = 0.577215664901532860606512090082402431042;
0244 const double ln2   = 0.693147180559945309417232121458176568076;
0245 FJCORE_END_NAMESPACE
0246 #endif // __FJCORE_NUMCONSTS__
0247 #ifndef __FJCORE_INTERNAL_IS_BASE_HH__
0248 #define __FJCORE_INTERNAL_IS_BASE_HH__
0249 FJCORE_BEGIN_NAMESPACE
0250 template<typename T, T _t>
0251 struct integral_type{
0252   FJCORE_WINDLL static const T value = _t;         ///< the value (only member carrying info)
0253   typedef T value_type;          ///< a typedef for the type T
0254   typedef integral_type<T,_t> type;  ///< a typedef for the whole structure
0255 };
0256 template<typename T, T _t>
0257 const T integral_type<T, _t>::value;
0258 typedef integral_type<bool, true>  true_type;  ///< the bool 'true'  value promoted to a type
0259 typedef integral_type<bool, false> false_type; ///< the bool 'false' value promoted to a type
0260 typedef char (&__yes_type)[1]; //< the yes type
0261 typedef char (&__no_type) [2]; //< the no type
0262 template<typename B, typename D>
0263 struct __inheritance_helper{
0264 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310))   // MSVC 7.1
0265   template <typename T>
0266   static __yes_type check_sig(D const volatile *, T);
0267 #else
0268   static __yes_type check_sig(D const volatile *, long);
0269 #endif
0270   static __no_type  check_sig(B const volatile *, int);
0271 };
0272 template<typename B, typename D>
0273 struct IsBaseAndDerived{
0274 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000))
0275 #pragma warning(push)
0276 #pragma warning(disable:6334)
0277 #endif
0278   struct Host{
0279 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310))
0280     operator B const volatile *() const;
0281 #else
0282     operator B const volatile * const&() const;
0283 #endif
0284     operator D const volatile *();
0285   };
0286   static const bool value = ((sizeof(B)!=0) && 
0287                  (sizeof(D)!=0) && 
0288                  (sizeof(__inheritance_helper<B,D>::check_sig(Host(), 0)) == sizeof(__yes_type)));
0289 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000))
0290 #pragma warning(pop)
0291 #endif
0292 };
0293 template<class B, class D>
0294 B* cast_if_derived(D* d){
0295   return IsBaseAndDerived<B,D>::value ? (B*)(d) : 0;
0296 }
0297 FJCORE_END_NAMESPACE
0298 #endif  // __IS_BASE_OF_HH__
0299 #ifndef __FJCORE_FJCORE_DEPRECATED_HH__
0300 #define __FJCORE_FJCORE_DEPRECATED_HH__
0301 #ifndef SWIG
0302 #if defined(FJCORE_HAVE_CXX14_DEPRECATED) && (!defined(__FJCORE_ONLY_CORE__))
0303 #define FJCORE_DEPRECATED(func)              [[deprecated]] func
0304 #define FJCORE_DEPRECATED_MSG(message,func)  [[deprecated(message)]] func
0305 #elif defined(FJCORE_HAVE_GNUCXX_DEPRECATED)
0306 #define FJCORE_DEPRECATED(func)              func __attribute__((__deprecated__))
0307 #define FJCORE_DEPRECATED_MSG(message,func)  func __attribute__((__deprecated__))
0308 #else
0309 #define FJCORE_DEPRECATED(func)              func
0310 #define FJCORE_DEPRECATED_MSG(message,func)  func
0311 #endif
0312 #else  // SWIG
0313 #define FJCORE_DEPRECATED(func)              func
0314 #define FJCORE_DEPRECATED_MSG(message,func)  func
0315 #endif // SWIG
0316 #endif // __FJCORE_FJCORE_DEPRECATED_HH__
0317  #ifndef __FJCORE_SHARED_PTR_HH__
0318 #define __FJCORE_SHARED_PTR_HH__
0319 #include <cstdlib>  // for NULL!!!
0320 #ifdef FJCORE_HAVE_THREAD_SAFETY
0321 #include <atomic>
0322 #endif // FJCORE_HAVE_THREAD_SAFETY
0323 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0324 #ifdef FJCORE_HAVE_THREAD_SAFETY
0325 template<class T>
0326 class SharedPtr{
0327 public:
0328   class __SharedCountingPtr;
0329   SharedPtr() : _ptr(NULL){}
0330   template<class Y> explicit SharedPtr(Y* ptr){
0331     _ptr = new __SharedCountingPtr(ptr);
0332   }
0333   SharedPtr(SharedPtr const & share) : _ptr(share._get_container()){
0334     if (_ptr!=NULL) (*_ptr)++;
0335   }
0336   ~SharedPtr(){
0337     if (_ptr==NULL) return;
0338     _decrease_count();
0339   }
0340   void reset(){
0341     SharedPtr().swap(*this);
0342   }
0343   template<class Y> void reset(Y * ptr){
0344     SharedPtr(ptr).swap(*this);
0345   }
0346   template<class Y> void reset(SharedPtr<Y> const & share){
0347     if (_ptr!=NULL){
0348       if (_ptr == share._get_container()) return;
0349       _decrease_count();
0350     }
0351     _ptr = share._get_container();  // Note: automatically set it to NULL if share is empty
0352     if (_ptr!=NULL) (*_ptr)++;
0353   }
0354   SharedPtr& operator=(SharedPtr const & share){
0355     reset(share);
0356     return *this;
0357   }
0358   template<class Y> SharedPtr& operator=(SharedPtr<Y> const & share){
0359     reset(share);
0360     return *this;
0361   }
0362   inline T& operator*() const{
0363     return *(_ptr->get());
0364   }
0365   inline T* operator->() const{
0366     if (_ptr==NULL) return NULL;
0367     return _ptr->get();
0368   }  
0369   inline T* get() const{
0370     if (_ptr==NULL) return NULL;
0371     return _ptr->get();
0372   }
0373   T* operator ()() const{
0374     if (_ptr==NULL) return NULL;
0375     return _ptr->get(); // automatically returns NULL when out-of-scope
0376   }
0377   inline bool unique() const{
0378     return (use_count()==1);
0379   }
0380   inline long use_count() const{
0381     if (_ptr==NULL) return 0;
0382     return _ptr->use_count(); // automatically returns NULL when out-of-scope
0383   }
0384   inline operator bool() const{
0385     return (get()!=NULL);
0386   }
0387   inline void swap(SharedPtr & share){
0388     __SharedCountingPtr* share_container = share._ptr;
0389     share._ptr = _ptr;
0390     _ptr = share_container;
0391   }
0392   void set_count(const long & count){
0393     if (_ptr==NULL) return;
0394     _ptr->set_count(count);
0395   }
0396   class __SharedCountingPtr : public std::atomic<long>{
0397   public:
0398     __SharedCountingPtr() : std::atomic<long>(0), _ptr(NULL){} 
0399     template<class Y> explicit __SharedCountingPtr(Y* ptr)
0400       : std::atomic<long>(1), _ptr(ptr){}
0401     ~__SharedCountingPtr(){ 
0402       if (_ptr!=NULL){ delete _ptr;}
0403     }
0404     inline T* get() const {return _ptr;}
0405     inline long use_count() const {return (long)(*this);}
0406     inline void set_count(const long & count){ store(count);}
0407   private:
0408     T *_ptr;               ///< the pointer we're counting the references to
0409   };
0410 private:
0411   inline __SharedCountingPtr* _get_container() const{
0412     return _ptr;
0413   }
0414   void _decrease_count(){
0415     if (((*_ptr)--) == 1)
0416       delete _ptr;
0417   }
0418   __SharedCountingPtr *_ptr;
0419 };
0420 template<class T,class U>
0421 inline bool operator==(SharedPtr<T> const & t, SharedPtr<U> const & u){
0422   return t.get() == u.get();
0423 }
0424 template<class T,class U>
0425 inline bool operator!=(SharedPtr<T> const & t, SharedPtr<U> const & u){
0426   return t.get() != u.get();
0427 }
0428 template<class T,class U>
0429 inline bool operator<(SharedPtr<T> const & t, SharedPtr<U> const & u){
0430   return t.get() < u.get();
0431 }
0432 template<class T>
0433 inline void swap(SharedPtr<T> & a, SharedPtr<T> & b){
0434   return a.swap(b);
0435 }
0436 template<class T>
0437 inline T* get_pointer(SharedPtr<T> const & t){
0438   return t.get();
0439 }
0440 #else  // FJCORE_HAVE_THREAD_SAFETY
0441 template<class T>
0442 class SharedPtr{
0443 public:
0444   class __SharedCountingPtr;
0445   SharedPtr() : _ptr(NULL){}
0446   template<class Y> explicit SharedPtr(Y* ptr){
0447     _ptr = new __SharedCountingPtr(ptr);
0448   }
0449   SharedPtr(SharedPtr const & share) : _ptr(share._get_container()){
0450     if (_ptr!=NULL) ++(*_ptr);
0451   }
0452   ~SharedPtr(){
0453     if (_ptr==NULL) return;
0454     _decrease_count();
0455   }
0456   void reset(){
0457     SharedPtr().swap(*this);
0458   }
0459   template<class Y> void reset(Y * ptr){
0460     SharedPtr(ptr).swap(*this);
0461   }
0462   template<class Y> void reset(SharedPtr<Y> const & share){
0463     if (_ptr!=NULL){
0464       if (_ptr == share._get_container()) return;
0465       _decrease_count();
0466     }
0467     _ptr = share._get_container();  // Note: automatically set it to NULL if share is empty
0468     if (_ptr!=NULL) ++(*_ptr);
0469   }
0470   SharedPtr& operator=(SharedPtr const & share){
0471     reset(share);
0472     return *this;
0473   }
0474   template<class Y> SharedPtr& operator=(SharedPtr<Y> const & share){
0475     reset(share);
0476     return *this;
0477   }
0478   FJCORE_DEPRECATED_MSG("Use SharedPtr<T>::get() instead",
0479   T* operator ()() const){
0480     if (_ptr==NULL) return NULL;
0481     return _ptr->get(); // automatically returns NULL when out-of-scope
0482   }
0483   inline T& operator*() const{
0484     return *(_ptr->get());
0485   }
0486   inline T* operator->() const{
0487     if (_ptr==NULL) return NULL;
0488     return _ptr->get();
0489   }  
0490   inline T* get() const{
0491     if (_ptr==NULL) return NULL;
0492     return _ptr->get();
0493   }
0494   inline bool unique() const{
0495     return (use_count()==1);
0496   }
0497   inline long use_count() const{
0498     if (_ptr==NULL) return 0;
0499     return _ptr->use_count(); // automatically returns NULL when out-of-scope
0500   }
0501   #ifdef FJCORE_HAVE_EXPLICIT_FOR_OPERATORS
0502   explicit
0503   #endif
0504   inline operator bool() const{
0505     return (get()!=NULL);
0506   }
0507   inline void swap(SharedPtr & share){
0508     __SharedCountingPtr* share_container = share._ptr;
0509     share._ptr = _ptr;
0510     _ptr = share_container;
0511   }
0512   void set_count(const long & count){
0513     if (_ptr==NULL) return;
0514     _ptr->set_count(count);
0515   }
0516   class __SharedCountingPtr{
0517   public:
0518     __SharedCountingPtr() : _ptr(NULL), _count(0){}
0519     template<class Y> explicit __SharedCountingPtr(Y* ptr) : _ptr(ptr), _count(1){}
0520     ~__SharedCountingPtr(){ 
0521       if (_ptr!=NULL){ delete _ptr;}
0522     }
0523     inline T* get() const {return _ptr;}
0524     inline long use_count() const {return _count;}
0525     inline long operator++(){return ++_count;}
0526     inline long operator--(){return --_count;}
0527     inline long operator++(int){return _count++;}
0528     inline long operator--(int){return _count--;}
0529     void set_count(const long & count){
0530       _count = count;
0531     }
0532   private:
0533     T *_ptr;      ///< the pointer we're counting the references to
0534     long _count;  ///< the number of references
0535   };
0536 private:
0537   inline __SharedCountingPtr* _get_container() const{
0538     return _ptr;
0539   }
0540   void _decrease_count(){
0541     (*_ptr)--;
0542     if (_ptr->use_count()==0)
0543       delete _ptr; // that automatically deletes the object itself
0544   }
0545   __SharedCountingPtr *_ptr;
0546 };
0547 template<class T,class U>
0548 inline bool operator==(SharedPtr<T> const & t, SharedPtr<U> const & u){
0549   return t.get() == u.get();
0550 }
0551 template<class T,class U>
0552 inline bool operator!=(SharedPtr<T> const & t, SharedPtr<U> const & u){
0553   return t.get() != u.get();
0554 }
0555 template<class T,class U>
0556 inline bool operator<(SharedPtr<T> const & t, SharedPtr<U> const & u){
0557   return t.get() < u.get();
0558 }
0559 template<class T>
0560 inline void swap(SharedPtr<T> & a, SharedPtr<T> & b){
0561   return a.swap(b);
0562 }
0563 template<class T>
0564 inline T* get_pointer(SharedPtr<T> const & t){
0565   return t.get();
0566 }
0567 #endif // FJCORE_HAVE_THREAD_SAFETY
0568 FJCORE_END_NAMESPACE      // defined in fastjet/internal/base.hh
0569 #endif   // __FJCORE_SHARED_PTR_HH__
0570 #ifndef __FJCORE_LIMITEDWARNING_HH__
0571 #define __FJCORE_LIMITEDWARNING_HH__
0572 #include <iostream>
0573 #include <string>
0574 #include <list>
0575 #ifdef FJCORE_HAVE_LIMITED_THREAD_SAFETY
0576 #include <atomic>
0577 #include <mutex>
0578 #endif // FJCORE_HAVE_LIMITED_THREAD_SAFETY
0579 FJCORE_BEGIN_NAMESPACE
0580 class LimitedWarning {
0581 public:
0582   LimitedWarning() : _max_warn(_max_warn_default),_this_warning_summary(0) {}
0583   LimitedWarning(int max_warn_in) : _max_warn(max_warn_in), _this_warning_summary(0) {}  
0584 #ifdef FJCORE_HAVE_LIMITED_THREAD_SAFETY
0585   LimitedWarning(const LimitedWarning &other)
0586     : _max_warn(other._max_warn), _this_warning_summary{other._this_warning_summary.load()} {}  
0587 #endif
0588   void warn(const char * warning) {warn(warning, _default_ostr);}
0589   void warn(const std::string & warning) {warn(warning.c_str(), _default_ostr);}
0590   void warn(const char * warning, std::ostream * ostr);
0591   void warn(const std::string & warning, std::ostream * ostr) {warn(warning.c_str(), ostr);}
0592   static void set_default_stream(std::ostream * ostr) {
0593     _default_ostr = ostr;
0594   }
0595 #ifdef FJCORE_HAVE_LIMITED_THREAD_SAFETY
0596   static void set_default_stream_and_mutex(std::ostream * ostr,
0597                                            std::mutex * warnings_mutex) {
0598     _default_ostr  = ostr;
0599     _stream_mutex = warnings_mutex;
0600   }
0601 #endif // FJCORE_HAVE_LIMITED_THREAD_SAFETY
0602   static void set_default_max_warn(int max_warn) {
0603     _max_warn_default = max_warn;
0604   }
0605   int max_warn() const {return _max_warn;}
0606   int n_warn_so_far() const;
0607   static std::string summary();
0608 private:
0609   const int _max_warn;
0610   typedef std::pair<std::string, thread_safety_helpers::AtomicCounter<unsigned int> > Summary;
0611 #ifdef FJCORE_HAVE_LIMITED_THREAD_SAFETY
0612   FJCORE_WINDLL static std::atomic<int> _max_warn_default;
0613   FJCORE_WINDLL static std::atomic<std::ostream *> _default_ostr;
0614   FJCORE_WINDLL static std::atomic<std::mutex *> _stream_mutex;
0615   FJCORE_WINDLL static std::mutex _global_warnings_summary_mutex;
0616   std::atomic<Summary*> _this_warning_summary;
0617 #else
0618   FJCORE_WINDLL static int _max_warn_default;
0619   FJCORE_WINDLL static std::ostream * _default_ostr;
0620   Summary* _this_warning_summary;
0621 #endif // FJCORE_HAVE_LIMITED_THREAD_SAFETY
0622   FJCORE_WINDLL static std::list< Summary > _global_warnings_summary;
0623 };
0624 FJCORE_END_NAMESPACE
0625 #endif // __FJCORE_LIMITEDWARNING_HH__
0626 #ifndef __FJCORE_ERROR_HH__
0627 #define __FJCORE_ERROR_HH__
0628 #include<iostream>
0629 #include<string>
0630 #if (!defined(FJCORE_HAVE_EXECINFO_H)) || defined(__FJCORE_ONLY_CORE__)
0631 #endif
0632 #ifdef FJCORE_HAVE_LIMITED_THREAD_SAFETY
0633 #include <atomic>
0634 #include <mutex>
0635 #endif // FJCORE_HAVE_LIMITED_THREAD_SAFETY
0636 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0637 class Error{
0638 public:
0639   Error() {}
0640   Error(const std::string & message);
0641   virtual ~Error() {}
0642   std::string message() const {return _message;}
0643   std::string description() const {return message();}
0644   static void set_print_errors(bool print_errors) {_print_errors = print_errors;}
0645   static void set_print_backtrace(bool enabled);
0646   static void set_default_stream(std::ostream * ostr) {
0647     _default_ostr = ostr;
0648   }
0649 #ifdef FJCORE_HAVE_LIMITED_THREAD_SAFETY
0650   static void set_default_stream_and_mutex(std::ostream * ostr, std::mutex * stream_mutex) {
0651     _default_ostr = ostr;
0652     _stream_mutex = stream_mutex;
0653   }
0654 #endif // FJCORE_HAVE_LIMITED_THREAD_SAFETY
0655 private:
0656   std::string _message;                ///< error message
0657 #ifdef FJCORE_HAVE_LIMITED_THREAD_SAFETY
0658   FJCORE_WINDLL static std::atomic<bool> _print_errors;           ///< do we print anything?
0659   FJCORE_WINDLL static std::atomic<bool> _print_backtrace;        ///< do we print the backtrace?
0660   FJCORE_WINDLL static std::atomic<std::ostream *> _default_ostr; ///< the output stream (cerr if not set)
0661   FJCORE_WINDLL static std::atomic<std::mutex *> _stream_mutex; ///< the mutex for the output stream (nullptr if not set)
0662 #else
0663   FJCORE_WINDLL static bool _print_errors;           ///< do we print anything?
0664   FJCORE_WINDLL static bool _print_backtrace;        ///< do we print the backtrace?
0665   FJCORE_WINDLL static std::ostream * _default_ostr; ///< the output stream (cerr if not set)
0666 #endif // FJCORE_HAVE_LIMITED_THREAD_SAFETY
0667 #if (!defined(FJCORE_HAVE_EXECINFO_H)) || defined(__FJCORE_ONLY_CORE__)
0668   FJCORE_WINDLL static LimitedWarning _execinfo_undefined;
0669 #endif
0670 };
0671 class InternalError : public Error{
0672 public:
0673   InternalError(const std::string & message_in) : Error(std::string("*** CRITICAL INTERNAL FASTJET ERROR *** CONTACT THE AUTHORS *** ") + message_in){ }
0674 };
0675 FJCORE_END_NAMESPACE
0676 #endif // __FJCORE_ERROR_HH__
0677 #ifndef __FJCORE_PSEUDOJET_STRUCTURE_BASE_HH__
0678 #define __FJCORE_PSEUDOJET_STRUCTURE_BASE_HH__
0679 #include <vector>
0680 #include <string>
0681 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0682 class PseudoJet;
0683 class ClusterSequence;
0684 class PseudoJetStructureBase{
0685 public:
0686   PseudoJetStructureBase(){};
0687   virtual ~PseudoJetStructureBase(){};
0688   virtual std::string description() const{ return "PseudoJet with an unknown structure"; }
0689   virtual bool has_associated_cluster_sequence() const { return false;}
0690   virtual const ClusterSequence* associated_cluster_sequence() const;
0691   virtual bool has_valid_cluster_sequence() const {return false;}
0692   virtual const ClusterSequence * validated_cs() const;
0693   virtual bool has_partner(const PseudoJet &reference, PseudoJet &partner) const;
0694   virtual bool has_child(const PseudoJet &reference, PseudoJet &child) const;
0695   virtual bool has_parents(const PseudoJet &reference, PseudoJet &parent1, PseudoJet &parent2) const;
0696   virtual bool object_in_jet(const PseudoJet &reference, const PseudoJet &jet) const;
0697   virtual bool has_constituents() const {return false;}
0698   virtual std::vector<PseudoJet> constituents(const PseudoJet &reference) const;
0699   virtual bool has_exclusive_subjets() const {return false;}
0700   virtual std::vector<PseudoJet> exclusive_subjets(const PseudoJet &reference, const double & dcut) const;
0701   virtual int n_exclusive_subjets(const PseudoJet &reference, const double & dcut) const;
0702   virtual std::vector<PseudoJet> exclusive_subjets_up_to (const PseudoJet &reference, int nsub) const;
0703   virtual double exclusive_subdmerge(const PseudoJet &reference, int nsub) const;
0704   virtual double exclusive_subdmerge_max(const PseudoJet &reference, int nsub) const;
0705   virtual bool has_pieces(const PseudoJet & /* reference */) const {
0706     return false;}
0707   virtual std::vector<PseudoJet> pieces(const PseudoJet & /* reference */
0708                                         ) const;
0709 };
0710 FJCORE_END_NAMESPACE
0711 #endif  //  __FJCORE_PSEUDOJET_STRUCTURE_BASE_HH__
0712 #ifndef __FJCORE_PSEUDOJET_HH__
0713 #define __FJCORE_PSEUDOJET_HH__
0714 #include<valarray>
0715 #include<vector>
0716 #include<cassert>
0717 #include<cmath>
0718 #include<iostream>
0719 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0720 const double MaxRap = 1e5;
0721 const double pseudojet_invalid_phi = -100.0;
0722 const double pseudojet_invalid_rap = -1e200;
0723 class PseudoJet {
0724  public:
0725   PseudoJet() : _px(0), _py(0), _pz(0), _E(0) {_finish_init(); _reset_indices();}
0726   PseudoJet(const double px, const double py, const double pz, const double E);
0727   #ifndef SWIG
0728   template <class L> PseudoJet(const L & some_four_vector);
0729   #endif
0730   PseudoJet(bool /* dummy */) {}
0731 #ifdef FJCORE_HAVE_THREAD_SAFETY
0732   PseudoJet(const PseudoJet &other){ (*this)=other; }
0733   PseudoJet& operator=(const PseudoJet& other);
0734 #endif
0735   virtual ~PseudoJet(){}
0736   inline double E()   const {return _E;}
0737   inline double e()   const {return _E;} // like CLHEP
0738   inline double px()  const {return _px;}
0739   inline double py()  const {return _py;}
0740   inline double pz()  const {return _pz;}
0741   inline double phi() const {return phi_02pi();}
0742   inline double phi_std()  const {
0743     _ensure_valid_rap_phi();
0744     return _phi > pi ? _phi-twopi : _phi;}
0745   inline double phi_02pi() const {
0746     _ensure_valid_rap_phi();
0747     return _phi;
0748   }
0749   inline double rap() const {
0750     _ensure_valid_rap_phi();
0751     return _rap;
0752   }
0753   inline double rapidity() const {return rap();} // like CLHEP
0754   double pseudorapidity() const;
0755   double eta() const {return pseudorapidity();}
0756   inline double pt2() const {return _kt2;}
0757   inline double  pt() const {return sqrt(_kt2);} 
0758   inline double perp2() const {return _kt2;}  // like CLHEP
0759   inline double  perp() const {return sqrt(_kt2);}    // like CLHEP
0760   inline double kt2() const {return _kt2;} // for bkwds compatibility
0761   inline double  m2() const {return (_E+_pz)*(_E-_pz)-_kt2;}    
0762   inline double  m() const;    
0763   inline double mperp2() const {return (_E+_pz)*(_E-_pz);}
0764   inline double mperp() const {return sqrt(std::abs(mperp2()));}
0765   inline double mt2() const {return (_E+_pz)*(_E-_pz);}
0766   inline double mt() const {return sqrt(std::abs(mperp2()));}
0767   inline double modp2() const {return _kt2+_pz*_pz;}
0768   inline double modp() const {return sqrt(_kt2+_pz*_pz);}
0769   inline double Et() const {return (_kt2==0) ? 0.0 : _E/sqrt(1.0+_pz*_pz/_kt2);}
0770   inline double Et2() const {return (_kt2==0) ? 0.0 : _E*_E/(1.0+_pz*_pz/_kt2);}
0771   inline double cos_theta() const {
0772     return std::min(1.0, std::max(-1.0, _pz/sqrt(modp2())));
0773   }
0774   inline double theta() const { return acos(cos_theta()); }
0775   double operator () (int i) const ; 
0776   inline double operator [] (int i) const { return (*this)(i); }; // this too
0777   double kt_distance(const PseudoJet & other) const;
0778   double plain_distance(const PseudoJet & other) const;
0779   inline double squared_distance(const PseudoJet & other) const {
0780     return plain_distance(other);}
0781   inline double delta_R(const PseudoJet & other) const {
0782     return sqrt(squared_distance(other));
0783   }
0784   double delta_phi_to(const PseudoJet & other) const;
0785   inline double beam_distance() const {return _kt2;}
0786   std::valarray<double> four_mom() const;
0787   enum { X=0, Y=1, Z=2, T=3, NUM_COORDINATES=4, SIZE=NUM_COORDINATES };
0788   PseudoJet & boost(const PseudoJet & prest);
0789   PseudoJet & unboost(const PseudoJet & prest);
0790   PseudoJet & operator*=(double);
0791   PseudoJet & operator/=(double);
0792   PseudoJet & operator+=(const PseudoJet &);
0793   PseudoJet & operator-=(const PseudoJet &);
0794   inline void reset(double px, double py, double pz, double E);
0795   inline void reset(const PseudoJet & psjet) {
0796     (*this) = psjet;
0797   }
0798 #ifndef SWIG
0799   template <class L> inline void reset(const L & some_four_vector) {
0800     const PseudoJet * pj = fjcore::cast_if_derived<const PseudoJet>(&some_four_vector);
0801     if (pj){
0802       (*this) = *pj;
0803     } else {
0804       reset(some_four_vector[0], some_four_vector[1],
0805         some_four_vector[2], some_four_vector[3]);
0806     }
0807   }
0808 #endif // SWIG
0809   inline void reset_PtYPhiM(double pt_in, double y_in, double phi_in, double m_in=0.0) {
0810     reset_momentum_PtYPhiM(pt_in, y_in, phi_in, m_in);
0811     _reset_indices();
0812   }
0813   inline void reset_momentum(double px, double py, double pz, double E);
0814   inline void reset_momentum(const PseudoJet & pj);
0815   void reset_momentum_PtYPhiM(double pt, double y, double phi, double m=0.0);
0816   template <class L> inline void reset_momentum(const L & some_four_vector) {
0817     reset_momentum(some_four_vector[0], some_four_vector[1],
0818            some_four_vector[2], some_four_vector[3]);
0819   }
0820   void set_cached_rap_phi(double rap, double phi);
0821   inline int user_index() const {return _user_index;}
0822   inline void set_user_index(const int index) {_user_index = index;}
0823   class UserInfoBase{
0824   public:
0825     UserInfoBase(){};
0826     virtual ~UserInfoBase(){}; 
0827   };
0828   class InexistentUserInfo : public Error {
0829   public:
0830     InexistentUserInfo();
0831   };
0832   void set_user_info(UserInfoBase * user_info_in) {
0833     _user_info.reset(user_info_in);
0834   }
0835   template<class L>
0836   const L & user_info() const{
0837     if (_user_info.get() == 0) throw InexistentUserInfo();
0838     return dynamic_cast<const L &>(* _user_info.get());
0839   }
0840   bool has_user_info() const{
0841     return _user_info.get();
0842   }
0843   template<class L>
0844   bool has_user_info() const{
0845     return _user_info.get() && dynamic_cast<const L *>(_user_info.get());
0846   }
0847   const UserInfoBase * user_info_ptr() const{
0848     return _user_info.get();
0849   }
0850   const SharedPtr<UserInfoBase> & user_info_shared_ptr() const{
0851     return _user_info;
0852   }
0853   SharedPtr<UserInfoBase> & user_info_shared_ptr(){
0854     return _user_info;
0855   }
0856   void set_user_info_shared_ptr(const SharedPtr<UserInfoBase> & user_info_in) {
0857     _user_info = user_info_in;
0858   }
0859   std::string description() const;
0860   bool has_associated_cluster_sequence() const;
0861   bool has_associated_cs() const {return has_associated_cluster_sequence();}
0862   bool has_valid_cluster_sequence() const;
0863   bool has_valid_cs() const {return has_valid_cluster_sequence();}
0864   const ClusterSequence* associated_cluster_sequence() const;
0865   const ClusterSequence* associated_cs() const {return associated_cluster_sequence();}
0866   inline const ClusterSequence * validated_cluster_sequence() const {
0867     return validated_cs();
0868   }
0869   const ClusterSequence * validated_cs() const;
0870   void set_structure_shared_ptr(const SharedPtr<PseudoJetStructureBase> &structure_in);
0871   bool has_structure() const;
0872   const PseudoJetStructureBase* structure_ptr() const;
0873   PseudoJetStructureBase* structure_non_const_ptr();
0874   const PseudoJetStructureBase* validated_structure_ptr() const;
0875   const SharedPtr<PseudoJetStructureBase> & structure_shared_ptr() const;
0876   template<typename StructureType>
0877   const StructureType & structure() const;
0878   template<typename TransformerType>
0879   bool has_structure_of() const;
0880   template<typename TransformerType>
0881   const typename TransformerType::StructureType & structure_of() const;
0882   virtual bool has_partner(PseudoJet &partner) const;
0883   virtual bool has_child(PseudoJet &child) const;
0884   virtual bool has_parents(PseudoJet &parent1, PseudoJet &parent2) const;
0885   virtual bool contains(const PseudoJet &constituent) const;
0886   virtual bool is_inside(const PseudoJet &jet) const;
0887   virtual bool has_constituents() const;
0888   virtual std::vector<PseudoJet> constituents() const;
0889   virtual bool has_exclusive_subjets() const;
0890   std::vector<PseudoJet> exclusive_subjets (const double dcut) const;
0891   int n_exclusive_subjets(const double dcut) const;
0892   std::vector<PseudoJet> exclusive_subjets (int nsub) const;
0893   std::vector<PseudoJet> exclusive_subjets_up_to (int nsub) const;
0894   double exclusive_subdmerge(int nsub) const;
0895   double exclusive_subdmerge_max(int nsub) const;
0896   virtual bool has_pieces() const;
0897   virtual std::vector<PseudoJet> pieces() const;
0898   inline int cluster_hist_index() const {return _cluster_hist_index;}
0899   inline void set_cluster_hist_index(const int index) {_cluster_hist_index = index;}
0900   inline int cluster_sequence_history_index() const {
0901     return cluster_hist_index();}
0902   inline void set_cluster_sequence_history_index(const int index) {
0903     set_cluster_hist_index(index);}
0904  protected:  
0905   SharedPtr<PseudoJetStructureBase> _structure;
0906   SharedPtr<UserInfoBase> _user_info;
0907  private: 
0908   double _px,_py,_pz,_E;
0909   mutable double _phi, _rap;
0910   double _kt2; 
0911   int    _cluster_hist_index, _user_index;
0912 #ifdef FJCORE_HAVE_THREAD_SAFETY
0913   enum {
0914     Init_Done=1,
0915     Init_NotDone=0,
0916     Init_InProgress=-1
0917   };
0918   mutable std::atomic<int> _init_status;
0919 #endif
0920   void _finish_init();
0921   void _reset_indices();
0922 #ifdef FJCORE_HAVE_THREAD_SAFETY
0923   void _ensure_valid_rap_phi() const;
0924 #else
0925   inline void _ensure_valid_rap_phi() const{
0926     if (_phi == pseudojet_invalid_phi) _set_rap_phi();
0927   }
0928 #endif
0929   void _set_rap_phi() const;
0930   friend PseudoJet operator*(double, const PseudoJet &);
0931 };
0932 PseudoJet operator+(const PseudoJet &, const PseudoJet &);
0933 PseudoJet operator-(const PseudoJet &, const PseudoJet &);
0934 PseudoJet operator*(double, const PseudoJet &);
0935 PseudoJet operator*(const PseudoJet &, double);
0936 PseudoJet operator/(const PseudoJet &, double);
0937 bool operator==(const PseudoJet &, const PseudoJet &);
0938 inline bool operator!=(const PseudoJet & a, const PseudoJet & b) {return !(a==b);}
0939 bool operator==(const PseudoJet & jet, const double val);
0940 inline bool operator==(const double val, const PseudoJet & jet) {return jet == val;}
0941 inline bool operator!=(const PseudoJet & a, const double val)  {return !(a==val);}
0942 inline bool operator!=( const double val, const PseudoJet & a) {return !(a==val);}
0943 inline double dot_product(const PseudoJet & a, const PseudoJet & b) {
0944   return a.E()*b.E() - a.px()*b.px() - a.py()*b.py() - a.pz()*b.pz();
0945 }
0946 inline double cos_theta(const PseudoJet & a, const PseudoJet & b) {
0947   double dot_3d = a.px()*b.px() + a.py()*b.py() + a.pz()*b.pz();
0948   return std::min(1.0, std::max(-1.0, dot_3d/sqrt(a.modp2()*b.modp2())));
0949 }
0950 inline double theta(const PseudoJet & a, const PseudoJet & b) {
0951   return acos(cos_theta(a,b));
0952 }
0953 bool have_same_momentum(const PseudoJet &, const PseudoJet &);
0954 PseudoJet PtYPhiM(double pt, double y, double phi, double m = 0.0);
0955 std::vector<PseudoJet> sorted_by_pt(const std::vector<PseudoJet> & jets);
0956 std::vector<PseudoJet> sorted_by_rapidity(const std::vector<PseudoJet> & jets);
0957 std::vector<PseudoJet> sorted_by_E(const std::vector<PseudoJet> & jets);
0958 std::vector<PseudoJet> sorted_by_pz(const std::vector<PseudoJet> & jets);
0959 void sort_indices(std::vector<int> & indices, 
0960           const std::vector<double> & values);
0961 template<class T> std::vector<T> objects_sorted_by_values(const std::vector<T> & objects, 
0962                           const std::vector<double> & values) {
0963   if (objects.size() != values.size()){
0964     throw Error("fjcore::objects_sorted_by_values(...): the size of the 'objects' vector must match the size of the 'values' vector");
0965   }
0966   std::vector<int> indices(values.size());
0967   for (size_t i = 0; i < indices.size(); i++) {indices[i] = i;}
0968   sort_indices(indices, values);
0969   std::vector<T> objects_sorted(objects.size());
0970   for (size_t i = 0; i < indices.size(); i++) {
0971     objects_sorted[i] = objects[indices[i]];
0972   }
0973   return objects_sorted;
0974 }
0975 class IndexedSortHelper {
0976 public:
0977   inline IndexedSortHelper (const std::vector<double> * reference_values) {
0978     _ref_values = reference_values;
0979   };
0980   inline int operator() (const int i1, const int i2) const {
0981     return  (*_ref_values)[i1] < (*_ref_values)[i2];
0982   };
0983 private:
0984   const std::vector<double> * _ref_values;
0985 };
0986 #ifndef SWIG
0987 template <class L> inline  PseudoJet::PseudoJet(const L & some_four_vector) {
0988   reset(some_four_vector);
0989 }
0990 #endif
0991 inline void PseudoJet::_reset_indices() { 
0992   set_cluster_hist_index(-1);
0993   set_user_index(-1);
0994   _structure.reset();
0995   _user_info.reset();
0996 }
0997 inline double PseudoJet::m() const {
0998   double mm = m2();
0999   return mm < 0.0 ? -std::sqrt(-mm) : std::sqrt(mm);
1000 }
1001 inline void PseudoJet::reset(double px_in, double py_in, double pz_in, double E_in) {
1002   _px = px_in;
1003   _py = py_in;
1004   _pz = pz_in;
1005   _E  = E_in;
1006   _finish_init();
1007   _reset_indices();
1008 }
1009 inline void PseudoJet::reset_momentum(double px_in, double py_in, double pz_in, double E_in) {
1010   _px = px_in;
1011   _py = py_in;
1012   _pz = pz_in;
1013   _E  = E_in;
1014   _finish_init();
1015 }
1016 inline void PseudoJet::reset_momentum(const PseudoJet & pj) {
1017   _px  = pj._px ;
1018   _py  = pj._py ;
1019   _pz  = pj._pz ;
1020   _E   = pj._E  ;
1021 #ifdef FJCORE_HAVE_THREAD_SAFETY
1022   int expected = Init_Done;
1023   if (pj._init_status.compare_exchange_weak(expected, Init_Done)) {
1024     _init_status = Init_Done;
1025     _phi = pj._phi;
1026     _rap = pj._rap;
1027     _kt2 = pj._kt2;
1028   } else {
1029     _finish_init();
1030   }
1031 #else 
1032   _phi = pj._phi;
1033   _rap = pj._rap;
1034   _kt2 = pj._kt2;
1035 #endif
1036 }
1037 template<typename StructureType>
1038 const StructureType & PseudoJet::structure() const{
1039   return dynamic_cast<const StructureType &>(* validated_structure_ptr());
1040 }
1041 template<typename TransformerType>
1042 bool PseudoJet::has_structure_of() const{
1043   if (!_structure) return false;
1044   return dynamic_cast<const typename TransformerType::StructureType *>(_structure.get()) != 0;
1045 }
1046 template<typename TransformerType>
1047 const typename TransformerType::StructureType & PseudoJet::structure_of() const{
1048   if (!_structure) 
1049     throw Error("Trying to access the structure of a PseudoJet without an associated structure");
1050   return dynamic_cast<const typename TransformerType::StructureType &>(*_structure);
1051 }
1052 PseudoJet join(const std::vector<PseudoJet> & pieces);
1053 PseudoJet join(const PseudoJet & j1);
1054 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2);
1055 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3);
1056 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4);
1057 FJCORE_END_NAMESPACE
1058 #endif // __FJCORE_PSEUDOJET_HH__
1059 #ifndef __FJCORE_FUNCTION_OF_PSEUDOJET_HH__
1060 #define __FJCORE_FUNCTION_OF_PSEUDOJET_HH__
1061 FJCORE_BEGIN_NAMESPACE
1062 template<typename TOut>
1063 class FunctionOfPseudoJet{
1064 public:
1065   FunctionOfPseudoJet(){}
1066   virtual ~FunctionOfPseudoJet(){}
1067   virtual std::string description() const{ return "";}
1068   virtual TOut result(const PseudoJet &pj) const = 0;
1069   TOut operator()(const PseudoJet &pj) const { return result(pj);}
1070   std::vector<TOut> operator()(const std::vector<PseudoJet> &pjs) const {
1071     std::vector<TOut> res(pjs.size());
1072     for (unsigned int i=0; i<pjs.size(); i++)
1073       res[i] = result(pjs[i]);
1074     return res;
1075   }
1076 };
1077 FJCORE_END_NAMESPACE
1078 #endif  // __FJCORE_FUNCTION_OF_PSEUDOJET_HH__
1079 #ifndef __FJCORE_SELECTOR_HH__
1080 #define __FJCORE_SELECTOR_HH__
1081 #include <limits>
1082 #include <cmath>
1083 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
1084 class Selector;
1085 class SelectorWorker {
1086 public:
1087   virtual ~SelectorWorker() {}
1088   virtual bool pass(const PseudoJet & jet) const = 0;
1089   virtual void terminator(std::vector<const PseudoJet *> & jets) const {
1090     for (unsigned i = 0; i < jets.size(); i++) {
1091       if (jets[i] && !pass(*jets[i])) jets[i] = NULL;
1092     }
1093   }
1094   virtual bool applies_jet_by_jet() const {return true;}
1095   virtual std::string description() const {return "missing description";}
1096   virtual bool takes_reference() const { return false;}
1097   virtual void set_reference(const PseudoJet & /*reference*/){
1098     throw Error("set_reference(...) cannot be used for a selector worker that does not take a reference");
1099   }
1100   virtual SelectorWorker* copy(){ 
1101     throw Error("this SelectorWorker has nothing to copy");
1102   }
1103   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
1104     rapmax = std::numeric_limits<double>::infinity();
1105     rapmin = -rapmax; 
1106   }
1107   virtual bool is_geometric() const { return false;}
1108   virtual bool has_finite_area() const;
1109   virtual bool has_known_area() const { return false;}
1110   virtual double known_area() const{
1111     throw Error("this selector has no computable area");
1112   }
1113 };
1114 class Selector{
1115 public:
1116   Selector() {}
1117   Selector(SelectorWorker * worker_in) {_worker.reset(worker_in);}
1118   virtual ~Selector(){}
1119   bool pass(const PseudoJet & jet) const {
1120     if (!validated_worker()->applies_jet_by_jet()) {
1121       throw Error("Cannot apply this selector to an individual jet");
1122     }
1123     return _worker->pass(jet);
1124   }
1125   bool operator()(const PseudoJet & jet) const {
1126     return pass(jet);
1127   }
1128   unsigned int count(const std::vector<PseudoJet> & jets) const;
1129   PseudoJet sum(const std::vector<PseudoJet> & jets) const;
1130   double scalar_pt_sum(const std::vector<PseudoJet> & jets) const;
1131   void sift(const std::vector<PseudoJet> & jets,
1132           std::vector<PseudoJet> & jets_that_pass,
1133           std::vector<PseudoJet> & jets_that_fail) const;
1134   bool applies_jet_by_jet() const {
1135     return validated_worker()->applies_jet_by_jet();
1136   }
1137   std::vector<PseudoJet> operator()(const std::vector<PseudoJet> & jets) const;
1138   virtual void nullify_non_selected(std::vector<const PseudoJet *> & jets) const {
1139     validated_worker()->terminator(jets);
1140   }
1141   void get_rapidity_extent(double &rapmin, double &rapmax) const {
1142     return validated_worker()->get_rapidity_extent(rapmin, rapmax);
1143   }
1144   std::string description() const {
1145     return validated_worker()->description();
1146   }
1147   bool is_geometric() const{
1148     return validated_worker()->is_geometric();
1149   }
1150   bool has_finite_area() const{
1151     return validated_worker()->has_finite_area();
1152   }
1153   const SharedPtr<SelectorWorker> & worker() const {return _worker;}
1154   const SelectorWorker* validated_worker() const {
1155     const SelectorWorker* worker_ptr = _worker.get();
1156     if (worker_ptr == 0) throw InvalidWorker();
1157     return worker_ptr;
1158   }
1159   bool takes_reference() const {
1160     return validated_worker()->takes_reference();
1161   }
1162   const Selector & set_reference(const PseudoJet &reference){
1163     if (! validated_worker()->takes_reference()){
1164       return *this;
1165     }
1166     _copy_worker_if_needed();
1167     _worker->set_reference(reference);
1168     return *this;
1169   }
1170   class InvalidWorker : public Error {
1171   public:
1172     InvalidWorker() : Error("Attempt to use Selector with no valid underlying worker") {}
1173   };
1174   class InvalidArea : public Error {
1175   public:
1176     InvalidArea() : Error("Attempt to obtain area from Selector for which this is not meaningful") {}
1177   };
1178   Selector & operator &=(const Selector & b);
1179   Selector & operator |=(const Selector & b);
1180 protected:
1181   void _copy_worker_if_needed(){
1182     if (_worker.unique()) return;
1183     _worker.reset(_worker->copy());
1184   }
1185 private:
1186   SharedPtr<SelectorWorker> _worker; ///< the underlying worker
1187 };
1188 Selector SelectorIdentity();
1189 Selector operator!(const Selector & s);
1190 Selector operator ||(const Selector & s1, const Selector & s2);
1191 Selector operator&&(const Selector & s1, const Selector & s2);
1192 Selector operator*(const Selector & s1, const Selector & s2);
1193 Selector SelectorPtMin(double ptmin);                    ///< select objects with pt >= ptmin
1194 Selector SelectorPtMax(double ptmax);                    ///< select objects with pt <= ptmax
1195 Selector SelectorPtRange(double ptmin, double ptmax);    ///< select objects with ptmin <= pt <= ptmax
1196 Selector SelectorEtMin(double Etmin);                    ///< select objects with Et >= Etmin
1197 Selector SelectorEtMax(double Etmax);                    ///< select objects with Et <= Etmax
1198 Selector SelectorEtRange(double Etmin, double Etmax);    ///< select objects with Etmin <= Et <= Etmax
1199 Selector SelectorEMin(double Emin);                      ///< select objects with E >= Emin
1200 Selector SelectorEMax(double Emax);                      ///< select objects with E <= Emax
1201 Selector SelectorERange(double Emin, double Emax);       ///< select objects with Emin <= E <= Emax
1202 Selector SelectorMassMin(double Mmin);                      ///< select objects with Mass >= Mmin
1203 Selector SelectorMassMax(double Mmax);                      ///< select objects with Mass <= Mmax
1204 Selector SelectorMassRange(double Mmin, double Mmax);       ///< select objects with Mmin <= Mass <= Mmax
1205 Selector SelectorRapMin(double rapmin);                  ///< select objects with rap >= rapmin
1206 Selector SelectorRapMax(double rapmax);                  ///< select objects with rap <= rapmax
1207 Selector SelectorRapRange(double rapmin, double rapmax); ///< select objects with rapmin <= rap <= rapmax
1208 Selector SelectorAbsRapMin(double absrapmin);                     ///< select objects with |rap| >= absrapmin
1209 Selector SelectorAbsRapMax(double absrapmax);                     ///< select objects with |rap| <= absrapmax
1210 Selector SelectorAbsRapRange(double absrapmin, double absrapmax); ///< select objects with absrapmin <= |rap| <= absrapmax
1211 Selector SelectorEtaMin(double etamin);                  ///< select objects with eta >= etamin
1212 Selector SelectorEtaMax(double etamax);                  ///< select objects with eta <= etamax
1213 Selector SelectorEtaRange(double etamin, double etamax); ///< select objects with etamin <= eta <= etamax
1214 Selector SelectorAbsEtaMin(double absetamin);                     ///< select objects with |eta| >= absetamin
1215 Selector SelectorAbsEtaMax(double absetamax);                     ///< select objects with |eta| <= absetamax
1216 Selector SelectorAbsEtaRange(double absetamin, double absetamax); ///< select objects with absetamin <= |eta| <= absetamax
1217 Selector SelectorPhiRange(double phimin, double phimax); ///< select objects with phimin <= phi <= phimax
1218 Selector SelectorRapPhiRange(double rapmin, double rapmax, double phimin, double phimax);
1219 Selector SelectorNHardest(unsigned int n); 
1220 Selector SelectorCircle(const double radius); 
1221 Selector SelectorDoughnut(const double radius_in, const double radius_out); 
1222 Selector SelectorStrip(const double half_width);
1223 Selector SelectorRectangle(const double half_rap_width, const double half_phi_width);
1224 Selector SelectorPtFractionMin(double fraction);
1225 Selector SelectorIsZero();
1226 FJCORE_END_NAMESPACE      // defined in fastjet/internal/base.hh
1227 #endif // __FJCORE_SELECTOR_HH__
1228 #ifndef __FJCORE_JETDEFINITION_HH__
1229 #define __FJCORE_JETDEFINITION_HH__
1230 #include<cassert>
1231 #include<string>
1232 #include<memory>
1233 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
1234 std::string fastjet_version_string();
1235 enum Strategy {
1236   N2MHTLazy9AntiKtSeparateGhosts   = -10, 
1237   N2MHTLazy9   = -7, 
1238   N2MHTLazy25   = -6, 
1239   N2MHTLazy9Alt   = -5, 
1240   N2MinHeapTiled   = -4, 
1241   N2Tiled     = -3, 
1242   N2PoorTiled = -2, 
1243   N2Plain     = -1, 
1244   N3Dumb      =  0, 
1245   Best        =  1, 
1246   NlnN        =  2, 
1247   NlnN3pi     =  3, 
1248   NlnN4pi     =  4,
1249   NlnNCam4pi   = 14,
1250   NlnNCam2pi2R = 13,
1251   NlnNCam      = 12, // 2piMultD
1252   BestFJ30     =  21, 
1253   N2PlainEEAccurate =  31,
1254   plugin_strategy = 999
1255 };
1256 enum JetAlgorithm {
1257   kt_algorithm=0,
1258   cambridge_algorithm=1,
1259   antikt_algorithm=2, 
1260   genkt_algorithm=3, 
1261   cambridge_for_passive_algorithm=11,
1262   genkt_for_passive_algorithm=13, 
1263   ee_kt_algorithm=50,
1264   ee_genkt_algorithm=53,
1265   plugin_algorithm = 99,
1266   undefined_jet_algorithm = 999
1267 };
1268 typedef JetAlgorithm JetFinder;
1269 const JetAlgorithm aachen_algorithm = cambridge_algorithm;
1270 const JetAlgorithm cambridge_aachen_algorithm = cambridge_algorithm;
1271 enum RecombinationScheme {
1272   E_scheme=0,
1273   pt_scheme=1,
1274   pt2_scheme=2,
1275   Et_scheme=3,
1276   Et2_scheme=4,
1277   BIpt_scheme=5,
1278   BIpt2_scheme=6,
1279   WTA_pt_scheme=7,
1280   WTA_modp_scheme=8,
1281   external_scheme = 99
1282 };
1283 class ClusterSequence;
1284 class JetDefinition {
1285 public:
1286   class Plugin;
1287   class Recombiner;
1288   JetDefinition(JetAlgorithm jet_algorithm_in, 
1289                 double R_in, 
1290                 RecombinationScheme recomb_scheme_in = E_scheme,
1291                 Strategy strategy_in = Best) {
1292     *this = JetDefinition(jet_algorithm_in, R_in, recomb_scheme_in, strategy_in, 1);
1293   }
1294   JetDefinition(JetAlgorithm jet_algorithm_in, 
1295                 RecombinationScheme recomb_scheme_in = E_scheme,
1296                 Strategy strategy_in = Best) {
1297     double dummyR = 0.0;
1298     *this = JetDefinition(jet_algorithm_in, dummyR, recomb_scheme_in, strategy_in, 0);
1299   }
1300   JetDefinition(JetAlgorithm jet_algorithm_in, 
1301                 double R_in, 
1302                 double xtra_param_in,
1303                 RecombinationScheme recomb_scheme_in = E_scheme,
1304                 Strategy strategy_in = Best) {
1305     *this = JetDefinition(jet_algorithm_in, R_in, recomb_scheme_in, strategy_in, 2);
1306     set_extra_param(xtra_param_in);
1307   }
1308   JetDefinition(JetAlgorithm jet_algorithm_in, 
1309                 double R_in, 
1310                 const Recombiner * recombiner_in,
1311                 Strategy strategy_in = Best) {
1312     *this = JetDefinition(jet_algorithm_in, R_in, external_scheme, strategy_in);
1313     _recombiner = recombiner_in;
1314   }
1315   JetDefinition(JetAlgorithm jet_algorithm_in, 
1316                 const Recombiner * recombiner_in,
1317                 Strategy strategy_in = Best) {
1318     *this = JetDefinition(jet_algorithm_in, external_scheme, strategy_in);
1319     _recombiner = recombiner_in;
1320   }
1321   JetDefinition(JetAlgorithm jet_algorithm_in, 
1322                 double R_in, 
1323                 double xtra_param_in,
1324                 const Recombiner * recombiner_in,
1325                 Strategy strategy_in = Best) {
1326     *this = JetDefinition(jet_algorithm_in, R_in, xtra_param_in, external_scheme, strategy_in);
1327     _recombiner = recombiner_in;
1328   }
1329   JetDefinition()  {
1330     *this = JetDefinition(undefined_jet_algorithm, 1.0);
1331   }
1332   JetDefinition(const Plugin * plugin_in) {
1333     _plugin = plugin_in;
1334     _strategy = plugin_strategy;
1335     _Rparam = _plugin->R();
1336     _extra_param = 0.0; // a dummy value to keep static code checkers happy
1337     _jet_algorithm = plugin_algorithm;
1338     set_recombination_scheme(E_scheme);
1339   }
1340   JetDefinition(JetAlgorithm jet_algorithm_in, 
1341                 double R_in, 
1342                 RecombinationScheme recomb_scheme_in,
1343                 Strategy strategy_in,
1344                 int nparameters_in);
1345   FJCORE_DEPRECATED_MSG("This argument ordering is deprecated. Use JetDefinition(alg, R, strategy, scheme[, n_parameters]) instead",
1346   JetDefinition(JetAlgorithm jet_algorithm_in, 
1347                 double R_in, 
1348                 Strategy strategy_in,
1349                 RecombinationScheme recomb_scheme_in = E_scheme,
1350                 int nparameters_in = 1)){
1351     (*this) = JetDefinition(jet_algorithm_in,R_in,recomb_scheme_in,strategy_in,nparameters_in);
1352   }
1353   template <class L> 
1354   std::vector<PseudoJet> operator()(const std::vector<L> & particles) const;
1355   FJCORE_WINDLL static const double max_allowable_R; //= 1000.0;
1356   void set_recombination_scheme(RecombinationScheme);
1357   void set_recombiner(const Recombiner * recomb) {
1358     if (_shared_recombiner) _shared_recombiner.reset(recomb);
1359     _recombiner = recomb;
1360     _default_recombiner = DefaultRecombiner(external_scheme);
1361   }
1362   void set_recombiner(const JetDefinition &other_jet_def);
1363   void delete_recombiner_when_unused();
1364   const Plugin * plugin() const {return _plugin;};
1365   void delete_plugin_when_unused();
1366   JetAlgorithm jet_algorithm  () const {return _jet_algorithm  ;}
1367   JetAlgorithm jet_finder     () const {return _jet_algorithm  ;}
1368   double    R           () const {return _Rparam      ;}
1369   double    extra_param () const {return _extra_param ;}
1370   Strategy  strategy    () const {return _strategy    ;}
1371   RecombinationScheme recombination_scheme() const {
1372     return _default_recombiner.scheme();}
1373   void set_jet_algorithm(JetAlgorithm njf) {_jet_algorithm = njf;}
1374   void set_jet_finder(JetAlgorithm njf)    {_jet_algorithm = njf;}
1375   void set_extra_param(double xtra_param) {_extra_param = xtra_param;}
1376   const Recombiner * recombiner() const {
1377     return _recombiner == 0 ? & _default_recombiner : _recombiner;}
1378   bool has_same_recombiner(const JetDefinition &other_jd) const;
1379   bool is_spherical() const;
1380   std::string description() const;
1381   std::string description_no_recombiner() const;
1382   static std::string algorithm_description(const JetAlgorithm jet_alg);
1383   static unsigned int n_parameters_for_algorithm(const JetAlgorithm jet_alg);
1384 public:
1385   class Recombiner {
1386   public:
1387     virtual std::string description() const = 0;
1388     virtual void recombine(const PseudoJet & pa, const PseudoJet & pb, 
1389                            PseudoJet & pab) const = 0;
1390     virtual void preprocess(PseudoJet & ) const {};
1391     virtual ~Recombiner() {};
1392     inline void plus_equal(PseudoJet & pa, const PseudoJet & pb) const {
1393       PseudoJet pres; 
1394       recombine(pa,pb,pres);
1395       pa = pres;
1396     }
1397   };
1398   class DefaultRecombiner : public Recombiner {
1399   public:
1400     DefaultRecombiner(RecombinationScheme recomb_scheme = E_scheme) : 
1401       _recomb_scheme(recomb_scheme) {}
1402     virtual std::string description() const FJCORE_OVERRIDE;
1403     virtual void recombine(const PseudoJet & pa, const PseudoJet & pb, 
1404                            PseudoJet & pab) const FJCORE_OVERRIDE;
1405     virtual void preprocess(PseudoJet & p) const FJCORE_OVERRIDE;
1406     RecombinationScheme scheme() const {return _recomb_scheme;}
1407   private:
1408     RecombinationScheme _recomb_scheme;
1409   };
1410   class Plugin{
1411   public:
1412     virtual std::string description() const = 0;
1413     virtual void run_clustering(ClusterSequence &) const = 0;
1414     virtual double R() const = 0;
1415     virtual bool supports_ghosted_passive_areas() const {return false;}
1416     virtual void set_ghost_separation_scale(double scale) const;
1417     virtual double ghost_separation_scale() const {return 0.0;}
1418     virtual bool exclusive_sequence_meaningful() const {return false;}
1419     virtual bool is_spherical() const {return false;}
1420     virtual ~Plugin() {};
1421   };
1422 private:
1423   JetAlgorithm _jet_algorithm;
1424   double    _Rparam;
1425   double    _extra_param ; ///< parameter whose meaning varies according to context
1426   Strategy  _strategy  ;
1427   const Plugin * _plugin;
1428   SharedPtr<const Plugin> _plugin_shared;
1429   DefaultRecombiner _default_recombiner;
1430   const Recombiner * _recombiner;
1431   SharedPtr<const Recombiner> _shared_recombiner;
1432 };
1433 PseudoJet join(const std::vector<PseudoJet> & pieces, const JetDefinition::Recombiner & recombiner);
1434 PseudoJet join(const PseudoJet & j1, 
1435            const JetDefinition::Recombiner & recombiner);
1436 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
1437            const JetDefinition::Recombiner & recombiner);
1438 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, 
1439            const JetDefinition::Recombiner & recombiner);
1440 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4, 
1441            const JetDefinition::Recombiner & recombiner);
1442 FJCORE_END_NAMESPACE
1443 #endif // __FJCORE_JETDEFINITION_HH__
1444 #ifndef __FJCORE_COMPOSITEJET_STRUCTURE_HH__
1445 #define __FJCORE_COMPOSITEJET_STRUCTURE_HH__
1446 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
1447 class CompositeJetStructure : public PseudoJetStructureBase{
1448 public:
1449   CompositeJetStructure() : _area_4vector_ptr(0){};
1450   CompositeJetStructure(const std::vector<PseudoJet> & initial_pieces, 
1451             const JetDefinition::Recombiner * recombiner = 0);
1452   virtual ~CompositeJetStructure(){
1453     if (_area_4vector_ptr) delete _area_4vector_ptr;
1454   };
1455   virtual std::string description() const FJCORE_OVERRIDE;
1456   virtual bool has_constituents() const FJCORE_OVERRIDE;
1457   virtual std::vector<PseudoJet> constituents(const PseudoJet &jet) const FJCORE_OVERRIDE;
1458   virtual bool has_pieces(const PseudoJet & /*jet*/) const FJCORE_OVERRIDE {return true;}
1459   virtual std::vector<PseudoJet> pieces(const PseudoJet &jet) const FJCORE_OVERRIDE;
1460 protected:
1461   std::vector<PseudoJet> _pieces;  ///< the pieces building the jet
1462   PseudoJet * _area_4vector_ptr;   ///< pointer to the 4-vector jet area
1463 };
1464 template<typename T> PseudoJet join(const std::vector<PseudoJet> & pieces){
1465   PseudoJet result(0.0,0.0,0.0,0.0);
1466   for (unsigned int i=0; i<pieces.size(); i++){
1467     const PseudoJet it = pieces[i];
1468     result += it;
1469   }
1470   T *cj_struct = new T(pieces);
1471   result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
1472   return result;
1473 }
1474 template<typename T> PseudoJet join(const PseudoJet & j1){
1475   return join<T>(std::vector<PseudoJet>(1,j1));
1476 }
1477 template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2){
1478   std::vector<PseudoJet> pieces;
1479   pieces.push_back(j1);
1480   pieces.push_back(j2);
1481   return join<T>(pieces);
1482 }
1483 template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
1484                     const PseudoJet & j3){
1485   std::vector<PseudoJet> pieces;
1486   pieces.push_back(j1);
1487   pieces.push_back(j2);
1488   pieces.push_back(j3);
1489   return join<T>(pieces);
1490 }
1491 template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
1492                     const PseudoJet & j3, const PseudoJet & j4){
1493   std::vector<PseudoJet> pieces;
1494   pieces.push_back(j1);
1495   pieces.push_back(j2);
1496   pieces.push_back(j3);
1497   pieces.push_back(j4);
1498   return join<T>(pieces);
1499 }
1500 template<typename T> PseudoJet join(const std::vector<PseudoJet> & pieces, 
1501                     const JetDefinition::Recombiner & recombiner){
1502   PseudoJet result;
1503   if (pieces.size()>0){
1504     result = pieces[0];
1505     for (unsigned int i=1; i<pieces.size(); i++){
1506       recombiner.plus_equal(result, pieces[i]);
1507     }
1508   }
1509   T *cj_struct = new T(pieces, &recombiner);
1510   result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
1511   return result;
1512 }
1513 template<typename T> PseudoJet join(const PseudoJet & j1, 
1514                     const JetDefinition::Recombiner & recombiner){
1515   return join<T>(std::vector<PseudoJet>(1,j1), recombiner);
1516 }
1517 template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
1518                     const JetDefinition::Recombiner & recombiner){
1519   std::vector<PseudoJet> pieces;
1520   pieces.reserve(2);
1521   pieces.push_back(j1);
1522   pieces.push_back(j2);
1523   return join<T>(pieces, recombiner);
1524 }
1525 template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
1526                     const PseudoJet & j3, 
1527                     const JetDefinition::Recombiner & recombiner){
1528   std::vector<PseudoJet> pieces;
1529   pieces.reserve(3);
1530   pieces.push_back(j1);
1531   pieces.push_back(j2);
1532   pieces.push_back(j3);
1533   return join<T>(pieces, recombiner);
1534 }
1535 template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
1536                     const PseudoJet & j3, const PseudoJet & j4, 
1537                     const JetDefinition::Recombiner & recombiner){
1538   std::vector<PseudoJet> pieces;
1539   pieces.reserve(4);
1540   pieces.push_back(j1);
1541   pieces.push_back(j2);
1542   pieces.push_back(j3);
1543   pieces.push_back(j4);
1544   return join<T>(pieces, recombiner);
1545 }
1546 FJCORE_END_NAMESPACE      // defined in fastjet/internal/base.hh
1547 #endif // __FJCORE_MERGEDJET_STRUCTURE_HH__
1548 #ifndef __FJCORE_CLUSTER_SEQUENCE_STRUCTURE_HH__
1549 #define __FJCORE_CLUSTER_SEQUENCE_STRUCTURE_HH__
1550 #include <vector>
1551 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
1552 class ClusterSequenceStructure : public PseudoJetStructureBase{
1553 public:
1554   ClusterSequenceStructure() : _associated_cs(NULL){}
1555   ClusterSequenceStructure(const ClusterSequence *cs){
1556     set_associated_cs(cs);
1557   };
1558   virtual ~ClusterSequenceStructure();
1559   virtual std::string description() const FJCORE_OVERRIDE{
1560     return "PseudoJet with an associated ClusterSequence";
1561   }
1562   virtual bool has_associated_cluster_sequence() const FJCORE_OVERRIDE{ return true;}
1563   virtual const ClusterSequence* associated_cluster_sequence() const FJCORE_OVERRIDE;
1564   virtual bool has_valid_cluster_sequence() const FJCORE_OVERRIDE;
1565   virtual const ClusterSequence * validated_cs() const FJCORE_OVERRIDE;
1566   virtual void set_associated_cs(const ClusterSequence * new_cs){
1567     _associated_cs = new_cs;
1568   }
1569   virtual bool has_partner(const PseudoJet &reference, PseudoJet &partner) const FJCORE_OVERRIDE;
1570   virtual bool has_child(const PseudoJet &reference, PseudoJet &child) const FJCORE_OVERRIDE;
1571   virtual bool has_parents(const PseudoJet &reference, PseudoJet &parent1, PseudoJet &parent2) const FJCORE_OVERRIDE;
1572   virtual bool object_in_jet(const PseudoJet &reference, const PseudoJet &jet) const FJCORE_OVERRIDE;
1573   virtual bool has_constituents() const FJCORE_OVERRIDE;
1574   virtual std::vector<PseudoJet> constituents(const PseudoJet &reference) const FJCORE_OVERRIDE;
1575   virtual bool has_exclusive_subjets() const FJCORE_OVERRIDE;
1576   virtual std::vector<PseudoJet> exclusive_subjets(const PseudoJet &reference, const double & dcut) const FJCORE_OVERRIDE;
1577   virtual int n_exclusive_subjets(const PseudoJet &reference, const double & dcut) const FJCORE_OVERRIDE;
1578   virtual std::vector<PseudoJet> exclusive_subjets_up_to (const PseudoJet &reference, int nsub) const FJCORE_OVERRIDE;
1579   virtual double exclusive_subdmerge(const PseudoJet &reference, int nsub) const FJCORE_OVERRIDE;
1580   virtual double exclusive_subdmerge_max(const PseudoJet &reference, int nsub) const FJCORE_OVERRIDE;
1581   virtual bool has_pieces(const PseudoJet &reference) const FJCORE_OVERRIDE;
1582   virtual std::vector<PseudoJet> pieces(const PseudoJet &reference) const FJCORE_OVERRIDE;
1583 protected:
1584   const ClusterSequence *_associated_cs;
1585 };
1586 FJCORE_END_NAMESPACE
1587 #endif  //  __FJCORE_CLUSTER_SEQUENCE_STRUCTURE_HH__
1588 #ifndef __FJCORE_CLUSTERSEQUENCE_HH__
1589 #define __FJCORE_CLUSTERSEQUENCE_HH__
1590 #include<vector>
1591 #include<map>
1592 #include<memory>
1593 #include<cassert>
1594 #include<iostream>
1595 #include<string>
1596 #include<set>
1597 #include<cmath> // needed to get double std::abs(double)
1598 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
1599 class ClusterSequenceStructure;
1600 class DynamicNearestNeighbours;
1601 class ClusterSequence {
1602  public: 
1603   ClusterSequence () : _deletes_self_when_unused(false) {}
1604   template<class L> ClusterSequence (
1605                                   const std::vector<L> & pseudojets,
1606                                   const JetDefinition & jet_def,
1607                                   const bool & writeout_combinations = false);
1608   ClusterSequence (const ClusterSequence & cs) : _deletes_self_when_unused(false) {
1609     transfer_from_sequence(cs);
1610   }
1611   ClusterSequence & operator=(const ClusterSequence & cs);
1612   virtual ~ClusterSequence (); //{}
1613   std::vector<PseudoJet> inclusive_jets (const double ptmin = 0.0) const;
1614   int n_exclusive_jets (const double dcut) const;
1615   std::vector<PseudoJet> exclusive_jets (const double dcut) const;
1616   std::vector<PseudoJet> exclusive_jets (const int njets) const;
1617   std::vector<PseudoJet> exclusive_jets_up_to (const int njets) const;
1618   double exclusive_dmerge (const int njets) const;
1619   double exclusive_dmerge_max (const int njets) const;
1620   double exclusive_ymerge (int njets) const {return exclusive_dmerge(njets) / Q2();}
1621   double exclusive_ymerge_max (int njets) const {return exclusive_dmerge_max(njets)/Q2();}
1622   int n_exclusive_jets_ycut (double ycut) const {return n_exclusive_jets(ycut*Q2());}
1623   std::vector<PseudoJet> exclusive_jets_ycut (double ycut) const {
1624     int njets = n_exclusive_jets_ycut(ycut);
1625     return exclusive_jets(njets);
1626   }
1627   std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet, 
1628                                             const double dcut) const;
1629   int n_exclusive_subjets(const PseudoJet & jet, 
1630                           const double dcut) const;
1631   std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet, 
1632                                             int nsub) const;
1633   std::vector<PseudoJet> exclusive_subjets_up_to (const PseudoJet & jet, 
1634                                                   int nsub) const;
1635   double exclusive_subdmerge(const PseudoJet & jet, int nsub) const;
1636   double exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const;
1637   double Q() const {return _Qtot;}
1638   double Q2() const {return _Qtot*_Qtot;}
1639   bool object_in_jet(const PseudoJet & object, const PseudoJet & jet) const;
1640   bool has_parents(const PseudoJet & jet, PseudoJet & parent1, 
1641                PseudoJet & parent2) const;
1642   bool has_child(const PseudoJet & jet, PseudoJet & child) const;
1643   bool has_child(const PseudoJet & jet, const PseudoJet * & childp) const;
1644   bool has_partner(const PseudoJet & jet, PseudoJet & partner) const;
1645   std::vector<PseudoJet> constituents (const PseudoJet & jet) const;
1646   void print_jets_for_root(const std::vector<PseudoJet> & jets, 
1647                            std::ostream & ostr = std::cout) const;
1648   void print_jets_for_root(const std::vector<PseudoJet> & jets, 
1649                            const std::string & filename,
1650                            const std::string & comment = "") const;
1651   void add_constituents (const PseudoJet & jet, 
1652                          std::vector<PseudoJet> & subjet_vector) const;
1653   inline Strategy strategy_used () const {return _strategy;}
1654   std::string strategy_string () const {return strategy_string(_strategy);}
1655   std::string strategy_string (Strategy strategy_in) const;
1656   const JetDefinition & jet_def() const {return _jet_def;}
1657   void delete_self_when_unused();
1658   bool will_delete_self_when_unused() const {return _deletes_self_when_unused;}
1659   void signal_imminent_self_deletion() const;
1660   double jet_scale_for_algorithm(const PseudoJet & jet) const;
1661   void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, 
1662                                       int & newjet_k) {
1663     assert(plugin_activated());
1664     _do_ij_recombination_step(jet_i, jet_j, dij, newjet_k);
1665   }
1666   void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, 
1667                                       const PseudoJet & newjet, 
1668                                       int & newjet_k);
1669   void plugin_record_iB_recombination(int jet_i, double diB) {
1670     assert(plugin_activated());
1671     _do_iB_recombination_step(jet_i, diB);
1672   }
1673   PseudoJet & plugin_non_const_jet(unsigned i) {
1674     assert(plugin_activated());
1675     return _jets[i];
1676   }
1677   class Extras {
1678   public:
1679     virtual ~Extras() {}
1680     virtual std::string description() const {return "This is a dummy extras class that contains no extra information! Derive from it if you want to use it to provide extra information from a plugin jet finder";}
1681   };
1682   inline void plugin_associate_extras(Extras * extras_in) {
1683     _extras.reset(extras_in);
1684   }
1685 #ifndef SWIG
1686 #ifdef FJCORE_HAVE_AUTO_PTR_INTERFACE
1687   FJCORE_DEPRECATED_MSG("Please use ClusterSequence::plugin_associate_extras(Extras * extras_in)) instead",
1688   inline void plugin_associate_extras(std::auto_ptr<Extras> extras_in)){
1689     _extras.reset(extras_in.release());
1690   }
1691 #endif
1692 #endif //SWIG
1693   inline bool plugin_activated() const {return _plugin_activated;}
1694   const Extras * extras() const {return _extras.get();}
1695   template<class GBJ> void plugin_simple_N2_cluster () {
1696     assert(plugin_activated());
1697     _simple_N2_cluster<GBJ>();
1698   }
1699 public:
1700   struct history_element{
1701     int parent1; 
1702     int parent2; 
1703     int child;   
1704     int jetp_index; 
1705     double dij;  
1706     double max_dij_so_far; 
1707   };
1708   enum JetType {Invalid=-3, InexistentParent = -2, BeamJet = -1};
1709   const std::vector<PseudoJet> & jets()    const;
1710   const std::vector<history_element> & history() const;
1711   unsigned int n_particles() const;
1712   std::vector<int> particle_jet_indices(const std::vector<PseudoJet> &) const;
1713   std::vector<int> unique_history_order() const;
1714   std::vector<PseudoJet> unclustered_particles() const;
1715   std::vector<PseudoJet> childless_pseudojets() const;
1716   bool contains(const PseudoJet & object) const;
1717   void transfer_from_sequence(const ClusterSequence & from_seq,
1718                               const FunctionOfPseudoJet<PseudoJet> * action_on_jets = 0);
1719   const SharedPtr<PseudoJetStructureBase> & structure_shared_ptr() const{
1720     return _structure_shared_ptr;
1721   }
1722   typedef ClusterSequenceStructure StructureType;
1723   static void print_banner();
1724   static void set_fastjet_banner_stream(std::ostream * ostr) {_fastjet_banner_ostr = ostr;}
1725   static std::ostream * fastjet_banner_stream() {return _fastjet_banner_ostr;}
1726 private:
1727 #ifdef FJCORE_HAVE_LIMITED_THREAD_SAFETY
1728   FJCORE_WINDLL static std::atomic<std::ostream*> _fastjet_banner_ostr;
1729 #else
1730   FJCORE_WINDLL static std::ostream * _fastjet_banner_ostr;
1731 #endif // FJCORE_HAVE_LIMITED_THREAD_SAFETY
1732 protected:
1733   JetDefinition _jet_def;
1734   template<class L> void _transfer_input_jets(
1735                                      const std::vector<L> & pseudojets);
1736   void _initialise_and_run (const JetDefinition & jet_def,
1737                             const bool & writeout_combinations);
1738   void _initialise_and_run_no_decant();
1739   void _decant_options(const JetDefinition & jet_def,
1740                        const bool & writeout_combinations);
1741   void _decant_options_partial();
1742   void _fill_initial_history();
1743   void _do_ij_recombination_step(const int jet_i, const int jet_j, 
1744                                  const double dij, int & newjet_k);
1745   void _do_iB_recombination_step(const int jet_i, const double diB);
1746   void _set_structure_shared_ptr(PseudoJet & j);
1747   void _update_structure_use_count();
1748   Strategy _best_strategy() const;
1749   class _Parabola {
1750   public:
1751     _Parabola(double a, double b, double c) : _a(a), _b(b), _c(c) {}
1752     inline double operator()(const double R) const {return _c*(_a*R*R + _b*R + 1);}
1753   private:
1754     double _a, _b, _c;
1755   };
1756   class _Line {
1757   public:
1758     _Line(double a, double b) : _a(a), _b(b) {}
1759     inline double operator()(const double R) const {return _a*R + _b;}
1760   private:
1761     double _a, _b;
1762   };
1763   std::vector<PseudoJet> _jets;
1764   std::vector<history_element> _history;
1765   void get_subhist_set(std::set<const history_element*> & subhist,
1766                        const  PseudoJet & jet, double dcut, int maxjet) const;
1767   bool _writeout_combinations;
1768   int  _initial_n;
1769   double _Rparam, _R2, _invR2;
1770   double _Qtot;
1771   Strategy    _strategy;
1772   JetAlgorithm  _jet_algorithm;
1773   SharedPtr<PseudoJetStructureBase> _structure_shared_ptr; //< will actually be of type ClusterSequenceStructure
1774   int _structure_use_count_after_construction; //< info of use when CS handles its own memory
1775 #ifdef FJCORE_HAVE_THREAD_SAFETY
1776   mutable std::atomic<bool> _deletes_self_when_unused;
1777 #else
1778   mutable bool _deletes_self_when_unused;
1779 #endif
1780  private:
1781   bool _plugin_activated;
1782   SharedPtr<Extras> _extras; // things the plugin might want to add
1783   void _really_dumb_cluster ();
1784   void _delaunay_cluster ();
1785   template<class BJ> void _simple_N2_cluster ();
1786   void _tiled_N2_cluster ();
1787   void _faster_tiled_N2_cluster ();
1788   void _minheap_faster_tiled_N2_cluster();
1789   void _CP2DChan_cluster();
1790   void _CP2DChan_cluster_2pi2R ();
1791   void _CP2DChan_cluster_2piMultD ();
1792   void _CP2DChan_limited_cluster(double D);
1793   void _do_Cambridge_inclusive_jets();
1794   void _fast_NsqrtN_cluster();
1795   void _add_step_to_history( //const int step_number,
1796                             const int parent1, 
1797                             const int parent2, const int jetp_index,
1798                             const double dij);
1799   void _extract_tree_children(int pos, std::valarray<bool> &, 
1800                 const std::valarray<int> &, std::vector<int> &) const;
1801   void _extract_tree_parents (int pos, std::valarray<bool> &, 
1802                 const std::valarray<int> &,  std::vector<int> &) const;
1803   typedef std::pair<int,int> TwoVertices;
1804   typedef std::pair<double,TwoVertices> DijEntry;
1805   typedef std::multimap<double,TwoVertices> DistMap;
1806   void _add_ktdistance_to_map(const int ii, 
1807                               DistMap & DijMap,
1808                                 const DynamicNearestNeighbours * DNN);
1809   FJCORE_WINDLL static thread_safety_helpers::FirstTimeTrue _first_time;
1810   FJCORE_WINDLL static LimitedWarning _exclusive_warnings;
1811   FJCORE_WINDLL static LimitedWarning _changed_strategy_warning;
1812   struct BriefJet {
1813     double     eta, phi, kt2, NN_dist;
1814     BriefJet * NN;
1815     int        _jets_index;
1816   };
1817   class TiledJet {
1818   public:
1819     double     eta, phi, kt2, NN_dist;
1820     TiledJet * NN, *previous, * next; 
1821     int        _jets_index, tile_index, diJ_posn;
1822     inline void label_minheap_update_needed() {diJ_posn = 1;}
1823     inline void label_minheap_update_done()   {diJ_posn = 0;}
1824     inline bool minheap_update_needed() const {return diJ_posn==1;}
1825   };
1826   template <class J> void _bj_set_jetinfo( J * const jet, 
1827                                                  const int _jets_index) const;
1828   void _bj_remove_from_tiles( TiledJet * const jet) const;
1829   template <class J> double _bj_dist(const J * const jeta, 
1830                         const J * const jetb) const;
1831   template <class J> double _bj_diJ(const J * const jeta) const;
1832   template <class J> inline J * _bj_of_hindex(
1833                           const int hist_index, 
1834                           J * const head, J * const tail) 
1835     const {
1836     J * res;
1837     for(res = head; res<tail; res++) {
1838       if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
1839     }
1840     return res;
1841   }
1842   template <class J> void _bj_set_NN_nocross(J * const jeta, 
1843             J * const head, const J * const tail) const;
1844   template <class J> void _bj_set_NN_crosscheck(J * const jeta, 
1845             J * const head, const J * const tail) const;
1846   FJCORE_WINDLL static const int n_tile_neighbours = 9;
1847   struct Tile {
1848     Tile *   begin_tiles[n_tile_neighbours]; 
1849     Tile **  surrounding_tiles; 
1850     Tile **  RH_tiles;  
1851     Tile **  end_tiles; 
1852     TiledJet * head;    
1853     bool     tagged;    
1854   };
1855   std::vector<Tile> _tiles;
1856   double _tiles_eta_min, _tiles_eta_max;
1857   double _tile_size_eta, _tile_size_phi;
1858   int    _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
1859   inline int _tile_index (int ieta, int iphi) const {
1860     return (ieta-_tiles_ieta_min)*_n_tiles_phi
1861                   + (iphi+_n_tiles_phi) % _n_tiles_phi;
1862   }
1863   int  _tile_index(const double eta, const double phi) const;
1864   void _tj_set_jetinfo ( TiledJet * const jet, const int _jets_index);
1865   void  _bj_remove_from_tiles(TiledJet * const jet);
1866   void _initialise_tiles();
1867   void _print_tiles(TiledJet * briefjets ) const;
1868   void _add_neighbours_to_tile_union(const int tile_index, 
1869                  std::vector<int> & tile_union, int & n_near_tiles) const;
1870   void _add_untagged_neighbours_to_tile_union(const int tile_index, 
1871                  std::vector<int> & tile_union, int & n_near_tiles);
1872   struct EEBriefJet {
1873     double NN_dist;  // obligatorily present
1874     double kt2;      // obligatorily present == E^2 in general
1875     EEBriefJet * NN; // must be present too
1876     int    _jets_index; // must also be present!
1877     double nx, ny, nz;  // our internal storage for fast distance calcs
1878   };
1879   class EEAccurateBriefJet : public EEBriefJet { };
1880   void _simple_N2_cluster_BriefJet();
1881   void _simple_N2_cluster_EEBriefJet();
1882   void _simple_N2_cluster_EEAccurateBriefJet();
1883 };
1884 template<class L> void ClusterSequence::_transfer_input_jets(
1885                                        const std::vector<L> & pseudojets) {
1886   _jets.reserve(pseudojets.size()*2);
1887   for (unsigned int i = 0; i < pseudojets.size(); i++) {
1888     _jets.push_back(pseudojets[i]);}
1889 }
1890 template<class L> ClusterSequence::ClusterSequence (
1891                                   const std::vector<L> & pseudojets,
1892                                   const JetDefinition & jet_def_in,
1893                                   const bool & writeout_combinations) :
1894   _jet_def(jet_def_in), _writeout_combinations(writeout_combinations),
1895   _structure_shared_ptr(new ClusterSequenceStructure(this))
1896 {
1897   _transfer_input_jets(pseudojets);
1898   _decant_options_partial();
1899   _initialise_and_run_no_decant();
1900 }
1901 inline const std::vector<PseudoJet> & ClusterSequence::jets () const {
1902   return _jets;
1903 }
1904 inline const std::vector<ClusterSequence::history_element> & ClusterSequence::history () const {
1905   return _history;
1906 }
1907 inline unsigned int ClusterSequence::n_particles() const {return _initial_n;}
1908 #ifndef __CINT__
1909 template<class L>
1910 std::vector<PseudoJet> JetDefinition::operator()(const std::vector<L> & particles) const {
1911   ClusterSequence * cs = new ClusterSequence(particles, *this);
1912   std::vector<PseudoJet> jets;
1913   if (is_spherical()) {
1914     jets = sorted_by_E(cs->inclusive_jets());
1915   } else {
1916     jets = sorted_by_pt(cs->inclusive_jets());
1917   }
1918   if (jets.size() != 0) {
1919     cs->delete_self_when_unused();
1920   } else {
1921     delete cs;
1922   }
1923   return jets;
1924 }
1925 #endif // __CINT__
1926 template <class J> inline void ClusterSequence::_bj_set_jetinfo(
1927                             J * const jetA, const int _jets_index) const {
1928     jetA->eta  = _jets[_jets_index].rap();
1929     jetA->phi  = _jets[_jets_index].phi_02pi();
1930     jetA->kt2  = jet_scale_for_algorithm(_jets[_jets_index]);
1931     jetA->_jets_index = _jets_index;
1932     jetA->NN_dist = _R2;
1933     jetA->NN      = NULL;
1934 }
1935 template <class J> inline double ClusterSequence::_bj_dist(
1936                 const J * const jetA, const J * const jetB) const {
1937 #ifndef FJCORE_NEW_DELTA_PHI
1938   double dphi = std::abs(jetA->phi - jetB->phi);
1939   double deta = (jetA->eta - jetB->eta);
1940   if (dphi > pi) {dphi = twopi - dphi;}
1941 #else 
1942   double dphi = pi-std::abs(pi-std::abs(jetA->phi - jetB->phi));
1943   double deta = (jetA->eta - jetB->eta);
1944 #endif 
1945   return dphi*dphi + deta*deta;
1946 }
1947 template <class J> inline double ClusterSequence::_bj_diJ(const J * const jet) const {
1948   double kt2 = jet->kt2;
1949   if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
1950   return jet->NN_dist * kt2;
1951 }
1952 template <class J> inline void ClusterSequence::_bj_set_NN_nocross(
1953                  J * const jet, J * const head, const J * const tail) const {
1954   double NN_dist = _R2;
1955   J * NN  = NULL;
1956   if (head < jet) {
1957     for (J * jetB = head; jetB != jet; jetB++) {
1958       double dist = _bj_dist(jet,jetB);
1959       if (dist < NN_dist) {
1960         NN_dist = dist;
1961         NN = jetB;
1962       }
1963     }
1964   }
1965   if (tail > jet) {
1966     for (J * jetB = jet+1; jetB != tail; jetB++) {
1967       double dist = _bj_dist(jet,jetB);
1968       if (dist < NN_dist) {
1969         NN_dist = dist;
1970         NN = jetB;
1971       }
1972     }
1973   }
1974   jet->NN = NN;
1975   jet->NN_dist = NN_dist;
1976 }
1977 template <class J> inline void ClusterSequence::_bj_set_NN_crosscheck(J * const jet, 
1978                     J * const head, const J * const tail) const {
1979   double NN_dist = _R2;
1980   J * NN  = NULL;
1981   for (J * jetB = head; jetB != tail; jetB++) {
1982     double dist = _bj_dist(jet,jetB);
1983     if (dist < NN_dist) {
1984       NN_dist = dist;
1985       NN = jetB;
1986     }
1987     if (dist < jetB->NN_dist) {
1988       jetB->NN_dist = dist;
1989       jetB->NN = jet;
1990     }
1991   }
1992   jet->NN = NN;
1993   jet->NN_dist = NN_dist;
1994 }
1995 FJCORE_END_NAMESPACE
1996 #endif // __FJCORE_CLUSTERSEQUENCE_HH__
1997 #ifndef __FJCORE_NNBASE_HH__
1998 #define __FJCORE_NNBASE_HH__
1999 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
2000 class _NoInfo {};
2001 template<class I> class NNInfo {
2002 public:
2003   NNInfo()         : _info(NULL) {}
2004   NNInfo(I * info) : _info(info) {}
2005   template<class BJ> void init_jet(BJ * briefjet, const fjcore::PseudoJet & jet, int index) { briefjet->init(jet, index, _info);}
2006 private:
2007   I * _info;
2008 };
2009 template<> class NNInfo<_NoInfo>  {
2010 public:
2011   NNInfo()           {}
2012   NNInfo(_NoInfo * ) {}
2013   template<class BJ> void init_jet(BJ * briefjet, const fjcore::PseudoJet & jet, int index) { briefjet->init(jet, index);}
2014 };
2015 template<class I = _NoInfo> class NNBase : public NNInfo<I> {
2016 public:
2017   NNBase() {}
2018   NNBase(I * info) : NNInfo<I>(info) {}
2019   virtual void start(const std::vector<PseudoJet> & jets) = 0;
2020   virtual double dij_min(int & iA, int & iB) = 0;
2021   virtual void remove_jet(int iA) = 0;
2022   virtual void merge_jets(int iA, int iB, const PseudoJet & jet, int jet_index) =  0;
2023   virtual ~NNBase() {};
2024 };
2025 FJCORE_END_NAMESPACE      // defined in fastjet/internal/base.hh
2026 #endif // __FJCORE_NNBASE_HH__
2027 #ifndef __FJCORE_NNH_HH__
2028 #define __FJCORE_NNH_HH__
2029 FJCORE_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
2030 template<class BJ, class I = _NoInfo> class NNH : public NNBase<I> {
2031 public:
2032   NNH(const std::vector<PseudoJet> & jets)           : NNBase<I>()     {start(jets);}
2033   NNH(const std::vector<PseudoJet> & jets, I * info) : NNBase<I>(info) {start(jets);}
2034   void start(const std::vector<PseudoJet> & jets);
2035   double dij_min(int & iA, int & iB);
2036   void remove_jet(int iA);
2037   void merge_jets(int iA, int iB, const PseudoJet & jet, int jet_index);
2038   ~NNH() {
2039     delete[] briefjets;
2040   }
2041 private:
2042   class NNBJ; // forward declaration
2043   void set_NN_crosscheck(NNBJ * jet, NNBJ * begin, NNBJ * end);
2044   void set_NN_nocross   (NNBJ * jet, NNBJ * begin, NNBJ * end);
2045   NNBJ * briefjets;
2046   NNBJ * head, * tail;
2047   int n;
2048   std::vector<NNBJ *> where_is;
2049   class NNBJ : public BJ {
2050   public:
2051     void init(const PseudoJet & jet, int index_in) {
2052       BJ::init(jet);
2053       other_init(index_in);
2054     }
2055     void init(const PseudoJet & jet, int index_in, I * info) {
2056       BJ::init(jet, info);
2057       other_init(index_in);
2058     }
2059     void other_init(int index_in) {
2060       _index = index_in;
2061       NN_dist = BJ::beam_distance();
2062       NN = NULL;
2063     }
2064     int index() const {return _index;}
2065     double NN_dist;
2066     NNBJ * NN;
2067   private:
2068     int _index;
2069   };
2070 };
2071 template<class BJ, class I> void NNH<BJ,I>::start(const std::vector<PseudoJet> & jets) {
2072   n = jets.size();
2073   briefjets = new NNBJ[n];
2074   where_is.resize(2*n);
2075   NNBJ * jetA = briefjets;
2076   for (int i = 0; i< n; i++) {
2077     this->init_jet(jetA, jets[i], i);
2078     where_is[i] = jetA;
2079     jetA++; // move on to next entry of briefjets
2080   }
2081   tail = jetA; // a semaphore for the end of briefjets
2082   head = briefjets; // a nicer way of naming start
2083   for (jetA = head + 1; jetA != tail; jetA++) {
2084     set_NN_crosscheck(jetA, head, jetA);
2085   }
2086 }
2087 template<class BJ, class I> double NNH<BJ,I>::dij_min(int & iA, int & iB) {
2088   double diJ_min = briefjets[0].NN_dist;
2089   int diJ_min_jet = 0;
2090   for (int i = 1; i < n; i++) {
2091     if (briefjets[i].NN_dist < diJ_min) {
2092       diJ_min_jet = i; 
2093       diJ_min  = briefjets[i].NN_dist;
2094     }
2095   }
2096   NNBJ * jetA = & briefjets[diJ_min_jet];
2097   iA = jetA->index();
2098   iB = jetA->NN ? jetA->NN->index() : -1;
2099   return diJ_min;
2100 }
2101 template<class BJ, class I> void NNH<BJ,I>::remove_jet(int iA) {
2102   NNBJ * jetA = where_is[iA];
2103   tail--; n--;
2104   *jetA = *tail;
2105   where_is[jetA->index()] = jetA;
2106   for (NNBJ * jetI = head; jetI != tail; jetI++) {
2107     if (jetI->NN == jetA) set_NN_nocross(jetI, head, tail);
2108     if (jetI->NN == tail) {jetI->NN = jetA;}
2109   }
2110 }
2111 template<class BJ, class I> void NNH<BJ,I>::merge_jets(int iA, int iB, 
2112                     const PseudoJet & jet, int index) {
2113   NNBJ * jetA = where_is[iA];
2114   NNBJ * jetB = where_is[iB];
2115   if (jetA < jetB) std::swap(jetA,jetB);
2116   this->init_jet(jetB, jet, index);
2117   if (index >= int(where_is.size())) where_is.resize(2*index);
2118   where_is[jetB->index()] = jetB;
2119   tail--; n--;
2120   *jetA = *tail;
2121   where_is[jetA->index()] = jetA;
2122   for (NNBJ * jetI = head; jetI != tail; jetI++) {
2123     if (jetI->NN == jetA || jetI->NN == jetB) {
2124       set_NN_nocross(jetI, head, tail);
2125     } 
2126     double dist = jetI->distance(jetB);
2127     if (dist < jetI->NN_dist) {
2128       if (jetI != jetB) {
2129     jetI->NN_dist = dist;
2130     jetI->NN = jetB;
2131       }
2132     }
2133     if (dist < jetB->NN_dist) {
2134       if (jetI != jetB) {
2135     jetB->NN_dist = dist;
2136     jetB->NN      = jetI;
2137       }
2138     }
2139     if (jetI->NN == tail) {jetI->NN = jetA;}
2140   }
2141 }
2142 template <class BJ, class I> void NNH<BJ,I>::set_NN_crosscheck(NNBJ * jet, 
2143             NNBJ * begin, NNBJ * end) {
2144   double NN_dist = jet->beam_distance();
2145   NNBJ * NN      = NULL;
2146   for (NNBJ * jetB = begin; jetB != end; jetB++) {
2147     double dist = jet->distance(jetB);
2148     if (dist < NN_dist) {
2149       NN_dist = dist;
2150       NN = jetB;
2151     }
2152     if (dist < jetB->NN_dist) {
2153       jetB->NN_dist = dist;
2154       jetB->NN = jet;
2155     }
2156   }
2157   jet->NN = NN;
2158   jet->NN_dist = NN_dist;
2159 }
2160 template <class BJ, class I>  void NNH<BJ,I>::set_NN_nocross(
2161                  NNBJ * jet, NNBJ * begin, NNBJ * end) {
2162   double NN_dist = jet->beam_distance();
2163   NNBJ * NN      = NULL;
2164   if (begin < jet) {
2165     for (NNBJ * jetB = begin; jetB != jet; jetB++) {
2166       double dist = jet->distance(jetB);
2167       if (dist < NN_dist) {
2168     NN_dist = dist;
2169     NN = jetB;
2170       }
2171     }
2172   }
2173   if (end > jet) {
2174     for (NNBJ * jetB = jet+1; jetB != end; jetB++) {
2175       double dist = jet->distance (jetB);
2176       if (dist < NN_dist) {
2177     NN_dist = dist;
2178     NN = jetB;
2179       }
2180     }
2181   }
2182   jet->NN = NN;
2183   jet->NN_dist = NN_dist;
2184 }
2185 FJCORE_END_NAMESPACE      // defined in fastjet/internal/base.hh
2186 #endif // __FJCORE_NNH_HH__
2187 #endif