Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:06:24

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