Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:08:23

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