Skip to content
Snippets Groups Projects
Commit 850d8016 authored by Marco Clemencic's avatar Marco Clemencic
Browse files

Merge branch 'master' into 'master'

Functions added to GaudiUtils that allow generation of random numbers from integer and string input

Add hash functions with good avalanche characteristiscs to GaudiUtils.

- Header and implementation are QuasiRandom.{h,cpp} in GaudiUtils
- Relevant functions have been added to GaudiPython dictionary for
  interactive use
- Update RandomNumber test to include these functions
- Update RandomNumber test reference

See merge request !20
parents a7d3a5a1 75e5ab9f
No related branches found
No related tags found
No related merge requests found
...@@ -10,12 +10,18 @@ ...@@ -10,12 +10,18 @@
#include "GaudiKernel/DataObject.h" #include "GaudiKernel/DataObject.h"
#include "GaudiKernel/SmartDataPtr.h" #include "GaudiKernel/SmartDataPtr.h"
#include "GaudiUtils/QuasiRandom.h"
#include "AIDA/IHistogram1D.h" #include "AIDA/IHistogram1D.h"
using AIDA::IHistogram1D; using AIDA::IHistogram1D;
// Example related include files // Example related include files
#include "RandomNumberAlg.h" #include "RandomNumberAlg.h"
namespace {
namespace QuasiRandom = Gaudi::Utils::QuasiRandom;
}
DECLARE_COMPONENT(RandomNumberAlg) DECLARE_COMPONENT(RandomNumberAlg)
/** Algorithm parameters which can be set at run time must be declared. /** Algorithm parameters which can be set at run time must be declared.
...@@ -102,14 +108,17 @@ StatusCode RandomNumberAlg::initialize() { ...@@ -102,14 +108,17 @@ StatusCode RandomNumberAlg::initialize() {
return StatusCode::FAILURE; return StatusCode::FAILURE;
} }
// Book N-tuple // Initial randomness for deterministic random numbers
m_initial = QuasiRandom::mixString(name().size(), name());
// Book N-tuple
m_ntuple = ntupleSvc()->book ("/NTUPLES/FILE1/100", CLID_RowWiseTuple, "Hello World"); m_ntuple = ntupleSvc()->book ("/NTUPLES/FILE1/100", CLID_RowWiseTuple, "Hello World");
if ( m_ntuple ) { if ( m_ntuple ) {
status = m_ntuple->addItem ("Event#", m_int); status = m_ntuple->addItem ("Event#", m_int);
status = m_ntuple->addItem ("Gauss", m_gauss); status = m_ntuple->addItem ("DeterInt", m_deter);
status = m_ntuple->addItem ("Exp", m_exponential); status = m_ntuple->addItem ("Gauss", m_gauss);
status = m_ntuple->addItem ("Poisson", m_poisson); status = m_ntuple->addItem ("Exp", m_exponential);
status = m_ntuple->addItem ("Poisson", m_poisson);
} }
return status; return status;
} }
...@@ -123,7 +132,14 @@ StatusCode RandomNumberAlg::execute() { ...@@ -123,7 +132,14 @@ StatusCode RandomNumberAlg::execute() {
Rndm::Numbers exponential(randSvc(), Rndm::Exponential(0.2)); Rndm::Numbers exponential(randSvc(), Rndm::Exponential(0.2));
Rndm::Numbers poisson(randSvc(), Rndm::Poisson(0.3)); Rndm::Numbers poisson(randSvc(), Rndm::Poisson(0.3));
// Return integer in interval [0, size) from random integer in interval [0, MAX_INT]
auto scale = [](uint32_t x, uint32_t size) {
const uint32_t denom = boost::integer_traits<uint32_t>::const_max / size;
return x / denom;
};
m_int = ++count; m_int = ++count;
m_deter = scale(QuasiRandom::mix32(m_initial, m_int), 100);
m_gauss = (float)gauss(); m_gauss = (float)gauss();
m_exponential = (float)exponential(); m_exponential = (float)exponential();
m_poisson = (float)poisson(); m_poisson = (float)poisson();
...@@ -139,4 +155,3 @@ StatusCode RandomNumberAlg::finalize() { ...@@ -139,4 +155,3 @@ StatusCode RandomNumberAlg::finalize() {
m_numbers.finalize().ignore(); m_numbers.finalize().ignore();
return StatusCode::SUCCESS; return StatusCode::SUCCESS;
} }
...@@ -16,13 +16,16 @@ class RandomNumberAlg : public Algorithm { ...@@ -16,13 +16,16 @@ class RandomNumberAlg : public Algorithm {
protected: protected:
/// Allocate wrapper for random number generator /// Allocate wrapper for random number generator
Rndm::Numbers m_numbers; Rndm::Numbers m_numbers;
/// Initial seed to fill deterministic random numbers
uint32_t m_initial;
/// Pointer to N-tuple /// Pointer to N-tuple
NTuple::Tuple* m_ntuple; NTuple::Tuple* m_ntuple;
/// N-tuple items /// N-tuple items
NTuple::Item<int> m_int; NTuple::Item<int> m_int;
NTuple::Item<float> m_gauss; NTuple::Item<uint32_t> m_deter;
NTuple::Item<float> m_exponential; NTuple::Item<float> m_gauss;
NTuple::Item<float> m_poisson; NTuple::Item<float> m_exponential;
NTuple::Item<float> m_poisson;
public: public:
/// Constructor: A constructor of this form must be provided. /// Constructor: A constructor of this form must be provided.
......
JobOptionsSvc INFO JobOptionsSvc INFO # =======> /afs/cern.ch/work/r/raaij/dev-dir/GAUDI/GAUDI_v26r3/GaudiExamples/options/RandomNumber.opts
//GP:================================================================================ JobOptionsSvc INFO # (5,1): AuditorSvc.Auditors = ["ChronoAuditor"]
//GP: include "/afs/cern.ch/user/m/marcocle/scratch0/workspace/Gaudi/GaudiExamples/options/RandomNumber.opts" (0,0) JobOptionsSvc INFO # (12,1): ApplicationMgr.TopAlg = ["RandomNumberAlg"]
AuditorSvc.Auditors = [ "ChronoAuditor" ] ; //GP: (1,1) JobOptionsSvc INFO # (15,1): MessageSvc.OutputLevel = 2
ApplicationMgr.TopAlg = [ "RandomNumberAlg" ] ; //GP: (1,1) JobOptionsSvc INFO # (20,1): ApplicationMgr.EvtMax = 1000
MessageSvc.OutputLevel = 2; //GP: (1,1) JobOptionsSvc INFO # (21,1): ApplicationMgr.EvtSel = "NONE"
ApplicationMgr.EvtMax = 1000; //GP: (1,1) JobOptionsSvc INFO # (31,1): ApplicationMgr.HistogramPersistency = "ROOT"
ApplicationMgr.EvtSel = "NONE"; //GP: (1,1) JobOptionsSvc INFO # (32,1): HistogramPersistencySvc.OutputFile = "histo.root"
ApplicationMgr.HistogramPersistency = "ROOT"; //GP: (1,1) JobOptionsSvc INFO # (33,1): NTupleSvc.Output = ["FILE1 DATAFILE='NTuple.root' OPT='NEW' TYP='ROOT'"]
HistogramPersistencySvc.OutputFile = "histo.root"; //GP: (1,1) JobOptionsSvc INFO Job options successfully read in from /afs/cern.ch/work/r/raaij/dev-dir/GAUDI/GAUDI_v26r3/GaudiExamples/options/RandomNumber.opts
NTupleSvc.Output = [ "FILE1 DATAFILE='NTuple.root' OPT='NEW' TYP='ROOT'" ] ;//GP: (1,1)
//GP: end "/afs/cern.ch/user/m/marcocle/scratch0/workspace/Gaudi/GaudiExamples/options/RandomNumber.opts" (36,1)
//GP:================================================================================
JobOptionsSvc INFO Job options successfully read in from /afs/cern.ch/user/m/marcocle/scratch0/workspace/Gaudi/GaudiExamples/options/RandomNumber.opts
ApplicationMgr DEBUG Getting my own properties ApplicationMgr DEBUG Getting my own properties
ApplicationMgr SUCCESS ApplicationMgr SUCCESS
==================================================================================================================================== ====================================================================================================================================
Welcome to ApplicationMgr $Revision: 1.77 $ Welcome to ApplicationMgr (GaudiCoreSvc v3r5)
running on pclhcb55 on Fri Apr 23 10:08:17 2010 running on lxplus0090.cern.ch on Tue Aug 25 14:01:55 2015
==================================================================================================================================== ====================================================================================================================================
ApplicationMgr INFO Application Manager Configured successfully ApplicationMgr INFO Application Manager Configured successfully
ServiceManager DEBUG Initializing service AppMgrRunable ServiceManager DEBUG Initializing service AppMgrRunable
...@@ -60,6 +55,7 @@ ServiceManager DEBUG Starting service EventDataSvc ...@@ -60,6 +55,7 @@ ServiceManager DEBUG Starting service EventDataSvc
ServiceManager DEBUG Starting service EventLoopMgr ServiceManager DEBUG Starting service EventLoopMgr
ApplicationMgr INFO Application Manager Started successfully ApplicationMgr INFO Application Manager Started successfully
RRWNTupleCnv INFO ID 100: added branch: Event# / Event#/I RRWNTupleCnv INFO ID 100: added branch: Event# / Event#/I
RRWNTupleCnv INFO ID 100: added branch: DeterInt / DeterInt/i
RRWNTupleCnv INFO ID 100: added branch: Gauss / Gauss/F RRWNTupleCnv INFO ID 100: added branch: Gauss / Gauss/F
RRWNTupleCnv INFO ID 100: added branch: Exp / Exp/F RRWNTupleCnv INFO ID 100: added branch: Exp / Exp/F
RRWNTupleCnv INFO ID 100: added branch: Poisson / Poisson/F RRWNTupleCnv INFO ID 100: added branch: Poisson / Poisson/F
...@@ -86,22 +82,26 @@ RFileCnv INFO dumping contents of /NTUPLES/FILE1 ...@@ -86,22 +82,26 @@ RFileCnv INFO dumping contents of /NTUPLES/FILE1
TFile: name=NTuple.root, title=Gaudi Trees, option=CREATE TFile: name=NTuple.root, title=Gaudi Trees, option=CREATE
****************************************************************************** ******************************************************************************
*Tree :100 : Hello World * *Tree :100 : Hello World *
*Entries : 1000 : Total = 18571 bytes File Size = 10130 * *Entries : 1000 : Total = 23150 bytes File Size = 11808 *
* : : Tree compression factor = 1.71 * * : : Tree compression factor = 1.84 *
****************************************************************************** ******************************************************************************
*Br 0 :Event# : Event#/I * *Br 0 :Event# : Event#/I *
*Entries : 1000 : Total Size= 4558 bytes File Size = 1516 * *Entries : 1000 : Total Size= 4558 bytes File Size = 1516 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 2.69 * *Baskets : 1 : Basket Size= 32000 bytes Compression= 2.69 *
*............................................................................* *............................................................................*
*Br 1 :Gauss : Gauss/F * *Br 1 :DeterInt : DeterInt/i *
*Entries : 1000 : Total Size= 4568 bytes File Size = 1558 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 2.61 *
*............................................................................*
*Br 2 :Gauss : Gauss/F *
*Entries : 1000 : Total Size= 4553 bytes File Size = 3676 * *Entries : 1000 : Total Size= 4553 bytes File Size = 3676 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.11 * *Baskets : 1 : Basket Size= 32000 bytes Compression= 1.11 *
*............................................................................* *............................................................................*
*Br 2 :Exp : Exp/F * *Br 3 :Exp : Exp/F *
*Entries : 1000 : Total Size= 4543 bytes File Size = 3757 * *Entries : 1000 : Total Size= 4543 bytes File Size = 3757 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.08 * *Baskets : 1 : Basket Size= 32000 bytes Compression= 1.08 *
*............................................................................* *............................................................................*
*Br 3 :Poisson : Poisson/F * *Br 4 :Poisson : Poisson/F *
*Entries : 1000 : Total Size= 4563 bytes File Size = 564 * *Entries : 1000 : Total Size= 4563 bytes File Size = 564 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 7.22 * *Baskets : 1 : Basket Size= 32000 bytes Compression= 7.22 *
*............................................................................* *............................................................................*
...@@ -117,9 +117,9 @@ ServiceManager DEBUG Finalizing service RootHistSvc ...@@ -117,9 +117,9 @@ ServiceManager DEBUG Finalizing service RootHistSvc
RootHistSvc DEBUG RootHistCnv::PersSvc::finalize() RootHistSvc DEBUG RootHistCnv::PersSvc::finalize()
ServiceManager DEBUG Finalizing service RndmGenSvc ServiceManager DEBUG Finalizing service RndmGenSvc
ServiceManager DEBUG Finalizing service IncidentSvc ServiceManager DEBUG Finalizing service IncidentSvc
IncidentSvc DEBUG Incident timing: Mean(+-rms)/Min/Max:0.0034995(+-0.0590487)/0/1[ms] Total:0.006999[s] IncidentSvc DEBUG Incident timing: Mean(+-rms)/Min/Max:0.001(+-0.031607)/0/1[ms] Total:0.004[s]
ServiceManager DEBUG Finalizing service AppMgrRunable ServiceManager DEBUG Finalizing service AppMgrRunable
ServiceManager DEBUG Service reference count check: ServiceManager DEBUG Looping over all active services...
ServiceManager DEBUG ---- MessageSvc (refCount = 14) ServiceManager DEBUG ---- MessageSvc (refCount = 14)
ServiceManager DEBUG ---- JobOptionsSvc (refCount = 2) ServiceManager DEBUG ---- JobOptionsSvc (refCount = 2)
ServiceManager DEBUG ---- RndmGenSvc.Engine (refCount = 3) ServiceManager DEBUG ---- RndmGenSvc.Engine (refCount = 3)
......
...@@ -76,6 +76,7 @@ ...@@ -76,6 +76,7 @@
#include "GaudiUtils/HistoStats.h" #include "GaudiUtils/HistoStats.h"
#include "GaudiUtils/HistoDump.h" #include "GaudiUtils/HistoDump.h"
#include "GaudiUtils/HistoStrings.h" #include "GaudiUtils/HistoStrings.h"
#include "GaudiUtils/QuasiRandom.h"
#include <iostream> #include <iostream>
#include <istream> #include <istream>
......
...@@ -96,6 +96,11 @@ ...@@ -96,6 +96,11 @@
<class name= "Gaudi::Utils::Histos::Table" /> <class name= "Gaudi::Utils::Histos::Table" />
<class name= "Gaudi::Utils::HistoStats" /> <class name= "Gaudi::Utils::HistoStats" />
<function name= "Gaudi::Utils::QuasiRandom::mix" />
<function name= "Gaudi::Utils::QuasiRandom::mix32" />
<function name= "Gaudi::Utils::QuasiRandom::mix64" />
<function name= "Gaudi::Utils::QuasiRandom::mixString" />
<class name= "Gaudi::RangeBase_" /> <class name= "Gaudi::RangeBase_" />
<exclusion> <exclusion>
......
#ifndef GAUDIUTILS_QUASIRANDOM_H
#define GAUDIUTILS_QUASIRANDOM_H 1
// Include files
#include <string>
// boost
#include <boost/integer/integer_mask.hpp>
/// Create a hash with a large avalanche effect from 32 or 64 bit integers or a string.
///
/// note: the constants below are _not_ arbitrary, but are picked
/// carefully such that the bit shuffling has a large 'avalanche' effect...
/// Code by Brett Mulvey (old link: http://bretm.home.comcast.net/~bretm/hash/)
///
/// note: as a result, you might call this a quasi-random (not to be confused
/// with psuedo-random!) number generator, in that it generates an output
/// which satisfies a requirement on the uniformity of its output distribution.
/// (and not on the predictability of the next number in the sequence,
/// based on knowledge of the preceding numbers)
///
/// note: another way to look at this is is as an (approximation of an) evaporating
/// black hole: whatever you dump in to it, you get something uniformly
/// distributed back ;-)
///
namespace Gaudi {
namespace Utils {
namespace QuasiRandom {
/// Create a hash with a large avalanche effect from a 32 bit integer
uint32_t mix(uint32_t state);
/// mix some 'extra' entropy into 'state' and return result
uint32_t mix32(uint32_t state, uint32_t extra);
/// mix some 'extra' entropy into 'state' and return result
uint32_t mix64(uint32_t state, uint64_t extra);
/// mix some 'extra' entropy into 'state' and return result
uint32_t mixString(uint32_t state, const std::string& extra);
}
}
}
#endif // GAUDIUTILS_QUASIRANDOM_H
// Include files
#include <string>
// local
#include "GaudiUtils/QuasiRandom.h"
namespace Gaudi {
namespace Utils {
namespace QuasiRandom {
uint32_t mix(uint32_t state)
{
state += (state << 16); state ^= (state >> 13);
state += (state << 4); state ^= (state >> 7);
state += (state << 10); state ^= (state >> 5);
state += (state << 8); state ^= (state >> 16);
return state;
}
uint32_t mix32(uint32_t state, uint32_t extra)
{
return mix( state + extra );
}
uint32_t mix64(uint32_t state, uint64_t extra)
{
typedef boost::low_bits_mask_t<32> mask_t;
state = mix32( state , uint32_t( extra & mask_t::sig_bits_fast) );
return mix32( state , uint32_t((extra >> 32) & mask_t::sig_bits_fast) );
}
uint32_t mixString(uint32_t state, const std::string& extra)
{
// prefix name with ' ' until the size is a multiple of 4.
std::string s = std::string((4 - extra.size() % 4) % 4, ' ') + extra;
for (size_t i=0; i < s.size() / 4; ++i) {
//FIXME: this might do something different on big endian vs. small endian machines...
uint32_t x = uint32_t(s[i * 4])
| uint32_t(s[i * 4 + 1]) << 8
| uint32_t(s[i * 4 + 2]) << 16
| uint32_t(s[i * 4 + 3]) << 24 ;
state = mix32(state , x);
}
return state;
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment