Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:19

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : A.Sailer
0011 //
0012 //==========================================================================
0013 #ifndef DDG4_PLUGINS_GEANT4EVENTSEED_H
0014 #define DDG4_PLUGINS_GEANT4EVENTSEED_H
0015 
0016 // Framework include files
0017 #include <DDG4/Geant4RunAction.h>
0018 
0019 // fallthrough only exists from c++17
0020 #if defined __has_cpp_attribute
0021     #if __has_cpp_attribute(fallthrough)
0022         #define ATTR_FALLTHROUGH [[fallthrough]]
0023     #else
0024         #define ATTR_FALLTHROUGH
0025     #endif
0026 #else
0027     #define ATTR_FALLTHROUGH
0028 #endif
0029 
0030 
0031 /// Namespace for the AIDA detector description toolkit
0032 namespace dd4hep {
0033 
0034   /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
0035   namespace sim {
0036 
0037     /**
0038      * \addtogroup Geant4RunActions
0039      * @{
0040      * \package EventSeed
0041      * \brief   Set the event seed for each event
0042      *
0043      *  This plugins allows one to skip events and still be reproducible.
0044      *  We are using jenkins_hash from an intial seed, runID and eventID
0045      *  see http://burtleburtle.net/bob/hash/evahash.html
0046      *
0047      *  \author  A.Sailer
0048      *  \version 1.0
0049      *  \ingroup DD4HEP_SIMULATION
0050      * @}
0051      */
0052     /// Plugin class to set the event seed for each event
0053     class Geant4EventSeed: public Geant4RunAction {
0054 
0055     protected:
0056       unsigned int m_initialSeed;
0057       unsigned int m_runID;
0058       std::string m_type;
0059       bool m_initialised;
0060     public:
0061       /// Standard constructor with initializing arguments
0062       Geant4EventSeed(Geant4Context*, const std::string& );
0063       /// Default destructor
0064       virtual ~Geant4EventSeed();
0065       /// begin-of-run callback
0066       void begin(const G4Run*);
0067       /// begin-of-event callback
0068       void beginEvent(const G4Event*);
0069     };
0070 
0071     /*
0072 
0073       Hashing for random seed as used in Marlin EventSeeder processor
0074 
0075       Original source by Bob Jenkins
0076 
0077       http://www.burtleburtle.net/bob/hash/doobs.html
0078 
0079       Hash a variable-length key into a 32-bit value
0080 
0081     */
0082 
0083 #define hashsize(n) ( 1U << (n) )
0084 #define hashmask(n) ( hashsize ( n ) - 1 )
0085 
0086 
0087     /*
0088       --------------------------------------------------------------------
0089       mix -- mix 3 32-bit values reversibly.
0090       For every delta with one or two bits set, and the deltas of all three
0091       high bits or all three low bits, whether the original value of a,b,c
0092       is almost all zero or is uniformly distributed,
0093       * If mix() is run forward or backward, at least 32 bits in a,b,c
0094       have at least 1/4 probability of changing.
0095       * If mix() is run forward, every bit of c will change between 1/3 and
0096       2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
0097       mix() was built out of 36 single-cycle latency instructions in a
0098       structure that could supported 2x parallelism, like so:
0099       a -= b;
0100       a -= c; x = (c>>13);
0101       b -= c; a ^= x;
0102       b -= a; x = (a<<8);
0103       c -= a; b ^= x;
0104       c -= b; x = (b>>13);
0105       ...
0106       Unfortunately, superscalar Pentiums and Sparcs can't take advantage
0107       of that parallelism.  They've also turned some of those single-cycle
0108       latency instructions into multi-cycle latency instructions.  Still,
0109       this is the fastest good hash I could find.  There were about 2^^68
0110       to choose from.  I only looked at a billion or so.
0111       --------------------------------------------------------------------
0112     */
0113 #define mix(a,b,c)                              \
0114     {                                           \
0115       a -= b; a -= c; a ^= (c>>13);             \
0116       b -= c; b -= a; b ^= (a<<8);              \
0117       c -= a; c -= b; c ^= (b>>13);             \
0118       a -= b; a -= c; a ^= (c>>12);             \
0119       b -= c; b -= a; b ^= (a<<16);             \
0120       c -= a; c -= b; c ^= (b>>5);              \
0121       a -= b; a -= c; a ^= (c>>3);              \
0122       b -= c; b -= a; b ^= (a<<10);             \
0123       c -= a; c -= b; c ^= (b>>15);             \
0124     }
0125 
0126     /*
0127       --------------------------------------------------------------------
0128       jenkins_hash() -- hash a variable-length key into a 32-bit value
0129       k       : the key (the unaligned variable-length array of bytes)
0130       len     : the length of the key, counting by bytes
0131       initval : can be any 4-byte value
0132       Returns a 32-bit value.  Every bit of the key affects every bit of
0133       the return value.  Every 1-bit and 2-bit delta achieves avalanche.
0134       About 6*len+35 instructions.
0135 
0136       The best hash table sizes are powers of 2.  There is no need to do
0137       mod a prime (mod is sooo slow!).  If you need less than 32 bits,
0138       use a bitmask.  For example, if you need only 10 bits, do
0139       h = (h & hashmask(10));
0140       In which case, the hash table should have hashsize(10) elements.
0141 
0142       If you are hashing n strings (ub1 **)k, do it like this:
0143       for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
0144 
0145       By Bob Jenkins, 1996.  bob_jenkins@burtleburtle.net.  You may use this
0146       code any way you wish, private, educational, or commercial.  It's free.
0147 
0148       See http://burtleburtle.net/bob/hash/evahash.html
0149       Use for hash table lookup, or anything where one collision in 2^^32 is
0150       acceptable.  Do NOT use for cryptographic purposes.
0151       --------------------------------------------------------------------
0152     */
0153     unsigned jenkins_hash ( unsigned char *k, unsigned length, unsigned initval )
0154     {
0155       unsigned a, b;
0156       unsigned c = initval;
0157       unsigned len = length;
0158 
0159       a = b = 0x9e3779b9;
0160 
0161       while ( len >= 12 ) {
0162         a += ( k[0] + ( (unsigned)k[1] << 8 )
0163                + ( (unsigned)k[2] << 16 )
0164                + ( (unsigned)k[3] << 24 ) );
0165         b += ( k[4] + ( (unsigned)k[5] << 8 )
0166                + ( (unsigned)k[6] << 16 )
0167                + ( (unsigned)k[7] << 24 ) );
0168         c += ( k[8] + ( (unsigned)k[9] << 8 )
0169                + ( (unsigned)k[10] << 16 )
0170                + ( (unsigned)k[11] << 24 ) );
0171 
0172         mix ( a, b, c );
0173 
0174         k += 12;
0175         len -= 12;
0176       }
0177 
0178       c += length;
0179 
0180       switch ( len ) {
0181       case 11: c += ( (unsigned)k[10] << 24 ); ATTR_FALLTHROUGH;
0182       case 10: c += ( (unsigned)k[9] << 16 ); ATTR_FALLTHROUGH;
0183       case 9 : c += ( (unsigned)k[8] << 8 ); ATTR_FALLTHROUGH;
0184         /* First byte of c reserved for length */
0185       case 8 : b += ( (unsigned)k[7] << 24 ); ATTR_FALLTHROUGH;
0186       case 7 : b += ( (unsigned)k[6] << 16 ); ATTR_FALLTHROUGH;
0187       case 6 : b += ( (unsigned)k[5] << 8 ); ATTR_FALLTHROUGH;
0188       case 5 : b += k[4]; ATTR_FALLTHROUGH;
0189       case 4 : a += ( (unsigned)k[3] << 24 ); ATTR_FALLTHROUGH;
0190       case 3 : a += ( (unsigned)k[2] << 16 ); ATTR_FALLTHROUGH;
0191       case 2 : a += ( (unsigned)k[1] << 8 ); ATTR_FALLTHROUGH;
0192       case 1 : a += k[0];
0193       }
0194 
0195       mix ( a, b, c );
0196 
0197       return c;
0198     }
0199 
0200     /// calculate hash from initialSeed, eventID and runID
0201     unsigned int hash( unsigned int initialSeed, unsigned int eventNumber, unsigned int runNumber ){
0202       unsigned int seed = 0;
0203       unsigned char * c = (unsigned char *) &eventNumber ;
0204       seed = jenkins_hash( c, sizeof eventNumber, seed) ;
0205 
0206       c = (unsigned char *) &runNumber ;
0207       seed = jenkins_hash( c, sizeof runNumber, seed) ;
0208 
0209       c = (unsigned char *) &initialSeed ;
0210       seed = jenkins_hash( c, sizeof initialSeed, seed) ;
0211 
0212       return seed;
0213     }
0214 
0215   }    // End namespace sim
0216 }      // End namespace dd4hep
0217 
0218 #endif // DDG4_PLUGINS_GEANT4EVENTSEED_H