Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-06 09:24:23

0001 // -*- C++ -*-
0002 //
0003 // utility.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
0004 //
0005 // Copyright (C) 2008-2019 Simon Platzer -- simon.plaetzer@desy.de, The Herwig Collaboration
0006 //
0007 // ExSample is licenced under version 3 of the GPL, see COPYING for details.
0008 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
0009 //
0010 //
0011 #ifndef EXSAMPLE_utility_h_included
0012 #define EXSAMPLE_utility_h_included
0013 
0014 #include "config.h"
0015 #include <memory>
0016 
0017 namespace exsample {
0018 
0019   /// \brief separate quantities written to an ostream
0020   template<class OStream>
0021   struct ostream_traits {
0022 
0023     /// put the separator to the ostream
0024     static void separator(OStream& os) { os << "\n"; }
0025 
0026   };
0027 
0028 #ifdef EXSAMPLE_has_ThePEG
0029 
0030   /// \brief separate quantities written to a ThePEG::PersistentOStream
0031   template<>
0032   struct ostream_traits<ThePEG::PersistentOStream> {
0033 
0034     /// put the separator to the ostream
0035     static void separator(ThePEG::PersistentOStream&) { }
0036 
0037   };  
0038 
0039 #endif // EXSAMPLE_has_ThePEG
0040 
0041   /// \brief Compile time conversion of unsigned long to bool
0042   template<unsigned long>
0043   struct static_binary {
0044     enum { value = 1 };
0045   };
0046 
0047   /// \brief Compile time conversion of unsigned long to bool
0048   template<>
0049   struct static_binary<0> {
0050     enum { value = 0 };
0051   };
0052 
0053   /// \brief Fixed-size, packed vector of bools
0054   template<unsigned long bits>
0055   struct bit_container {
0056 
0057     enum {
0058       /// the number of bits contained
0059       n_bits = bits,
0060       /// the number of bits fitting in a unsigned long
0061       uint_bits = CHAR_BIT * sizeof(unsigned long),
0062       /// the number of unsigned long segments needed
0063       n_segments = bits / uint_bits + static_binary<bits % uint_bits>::value
0064     };
0065 
0066 
0067     /// the default constructor
0068     bit_container() {
0069       for (std::size_t i = 0; i < n_segments; ++i)
0070     segments[i] = 0;
0071     }
0072 
0073     /// put all values to false
0074     void reset() {
0075       for (std::size_t i = 0; i < n_segments; ++i)
0076     segments[i] = 0;
0077     }
0078 
0079     /// compare for equality
0080     bool operator==(const bit_container& x) const {
0081       for (std::size_t i = 0; i < n_segments; ++i)
0082     if(segments[i] != x.segments[i])
0083       return false;
0084       return true;
0085     }
0086 
0087     /// compare for ordering
0088     bool operator<(const bit_container& x) const {
0089       for (std::size_t i = 0; i < n_segments; ++i)
0090     if(segments[i] != x.segments[i])
0091       return (segments[i] < x.segments[i]);
0092       return false;
0093     }
0094 
0095     /// set the k'th bit
0096     void bit(unsigned long k, bool value) {
0097       assert(k<n_bits);
0098       if (value)
0099     segments[n_segments-k/uint_bits-1] |= (1ul << (k % uint_bits));
0100       else
0101     segments[n_segments-k/uint_bits-1] &= ~(1ul << (k % uint_bits));
0102     }
0103 
0104     /// get the k'th bit
0105     bool bit(unsigned long k) const {
0106       assert(k<n_bits);
0107       return (segments[n_segments-k/uint_bits-1] & (1ul << (k % uint_bits)));
0108     }
0109 
0110     /// print to ostream
0111     template<class OStream>
0112     void dump(OStream& os) const {
0113       for ( unsigned int k = 0; k < n_segments; ++k )
0114     os << segments[k] << " ";
0115     }
0116 
0117     /// put to ostream
0118     template<class OStream>
0119     void put(OStream& os) const {
0120       for ( size_t k = 0; k < n_segments; ++k ) {
0121     os << segments[k];
0122     ostream_traits<OStream>::separator(os);
0123       }
0124     }
0125 
0126     /// get from istream
0127     template<class IStream>
0128     void get(IStream& is) {
0129       for ( size_t k = 0; k < n_segments; ++k ) {
0130     is >> segments[k];
0131       }
0132     }
0133 
0134   private:
0135 
0136     /// segments needed to keep the hash value
0137     unsigned long segments[n_segments];
0138 
0139   };
0140 
0141   /// \brief square a number
0142   template<class T>
0143   T sqr(T x) {
0144     return x*x;
0145   }
0146 
0147   /// \brief cube a number
0148   template<class T>
0149   T cube(T x) {
0150     return x*x*x;
0151   }
0152 
0153 
0154   /// \brief Round a floating point value to an integer value of the
0155   /// same type.
0156   template<class T>
0157   T round(T x) {
0158     T f = std::floor(x);
0159     T c = std::ceil(x);
0160     if (x < (f+c)/2.)
0161       return f;
0162     return c;
0163   }
0164 
0165   /// \brief Calculate fast powers of two.
0166   inline std::size_t two_to(std::size_t n) {
0167     assert(n <= sizeof(std::size_t)*CHAR_BIT);
0168     return (1 << n);
0169   }
0170 
0171   /// \brief Fast, zero memory-overhead one-dimensional
0172   /// histogram with 2^n equally spaced bins
0173   template<class Statistics>
0174   struct fast_small_histogram {
0175 
0176     /// default constructor
0177     fast_small_histogram()
0178       : depth(0), bins(nullptr) {}
0179 
0180     /// copy constructor
0181     fast_small_histogram(const fast_small_histogram& x)
0182       : depth(x.depth), bins(0) {
0183       if (x.bins) {
0184     bins.reset(new Statistics[two_to(depth)]);
0185     for(std::size_t k = 0; k < two_to(depth); ++k)
0186       bins[k] = x.bins[k];
0187       }
0188     }
0189 
0190     /// assignment
0191     fast_small_histogram& operator=(const fast_small_histogram& x) {
0192       if (&x == this)
0193     return *this;
0194       depth = x.depth;
0195       bins.reset(nullptr);
0196       if (x.bins) {
0197     bins.reset(new Statistics[two_to(depth)]);
0198     for(std::size_t k = 0; k < two_to(depth); ++k)
0199       bins[k] = x.bins[k];
0200       }
0201       return *this;
0202     }
0203 
0204     /// construct from depth d, creating 2^d bins
0205     explicit fast_small_histogram(std::size_t d)
0206       : depth(d), bins(nullptr) {
0207       bins.reset(new Statistics[two_to(d)]);
0208     }
0209 
0210     /// return the bin from event belongs to given outer boundaries
0211     Statistics& bin(double lower,
0212             double upper,
0213             double event) {
0214       double thelower = lower;
0215       double theupper = upper;
0216       std::size_t bindex = 0;
0217       std::size_t current_depth = 0;
0218       while (true) {
0219     double cut
0220       = (thelower+theupper)/2.;
0221     if (event < cut) {
0222       theupper = cut;
0223     } else {
0224       thelower = cut;
0225       bindex += two_to(depth-current_depth-1);
0226     }
0227     if(++current_depth == depth)
0228       break;
0229       }
0230       return bins[bindex];
0231     }
0232 
0233     /// the depth, defining a histogram of 2^depth bins
0234     std::size_t depth;
0235 
0236     /// the contained statistics objects
0237     std::unique_ptr<Statistics[]> bins;
0238 
0239     /// put histogram to an ostream
0240     template<class OStream>
0241     void put(OStream& os) const {
0242       os << depth;
0243       ostream_traits<OStream>::separator(os);
0244       for (std::size_t k = 0; k < two_to(depth); ++k) {
0245     bins[k].put(os);
0246       }
0247     }
0248 
0249     /// get histogram from an istream
0250     template<class IStream>
0251     void get(IStream& is) {
0252       is >> depth;
0253       bins.reset(new Statistics[two_to(depth)]);
0254       for(std::size_t k = 0; k < two_to(depth); ++k) {
0255     bins[k].get(is);
0256       }
0257     }
0258      
0259   };
0260  
0261   /// \brief Generalize the transform algorithm to only apply
0262   /// depending on a range of flags accompanying the input range
0263   template<class FirstInputIterator, 
0264        class SecondInputIterator, 
0265        class FlagIterator,
0266        class OutputIterator,
0267        class BinaryOperation>
0268   OutputIterator conditional_transform(FirstInputIterator first1,
0269                        FirstInputIterator last1,
0270                        SecondInputIterator first2,
0271                        FlagIterator firstf,
0272                        OutputIterator result,
0273                        BinaryOperation binary_op) {
0274     for (; first1 != last1; ++first1, ++first2, ++firstf, ++result)
0275       if (*firstf)
0276     *result = binary_op(*first1, *first2);
0277     return result;
0278   }
0279 
0280   /// \brief calculate a volume given lower left and upper right
0281   /// corners
0282   inline double volume(const std::vector<double>& lower_left,
0283                const std::vector<double>& upper_right) {
0284     std::vector<double> delta;
0285     std::transform(upper_right.begin(),upper_right.end(),
0286            lower_left.begin(),std::back_inserter(delta),
0287            std::minus<double>());
0288     return
0289       std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
0290   }
0291 
0292   /// \brief calculate a volume given lower left and upper right
0293   /// corners, taking into account only part of the dimensions, which
0294   /// are flagged with true in the correspponding random access
0295   /// container
0296   inline double volume(const std::vector<double>& lower_left,
0297                const std::vector<double>& upper_right,
0298                const std::vector<bool>& flags) {
0299     std::vector<double> delta;
0300     conditional_transform(upper_right.begin(),upper_right.end(),
0301               lower_left.begin(),flags.begin(),
0302               std::back_inserter(delta),
0303               std::minus<double>());
0304     return
0305       std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
0306   }
0307 
0308 
0309   /// \brief Exception thrown if the maximum number of attempts to
0310   /// select a cell has been reached.
0311   struct selection_maxtry{};
0312 
0313   /// \brief Exception thrown, if the maximum number of misses has
0314   /// been reached.
0315   struct hit_and_miss_maxtry{};
0316 
0317   /// \brief Random generator traits.
0318   template<class Random>
0319   struct rnd_generator {
0320 
0321     ///Generate uniform random number on [0,1]
0322     double operator()() const {
0323       return Random::rnd();
0324     }
0325 
0326     ///Generate uniform random number on [0,a]
0327     double operator()(double a) const {
0328       return a*Random::rnd();
0329     }
0330 
0331     ///Generate uniform random number on [a,b]
0332     double operator()(double a, double b) const {
0333       return (a + (b-a)*Random::rnd());
0334     }
0335 
0336   };
0337 
0338 }
0339 
0340 #endif // EXSAMPLE_utility_h_included