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 @@
#include "GaudiKernel/DataObject.h"
#include "GaudiKernel/SmartDataPtr.h"
#include "GaudiUtils/QuasiRandom.h"
#include "AIDA/IHistogram1D.h"
using AIDA::IHistogram1D;
// Example related include files
#include "RandomNumberAlg.h"
namespace {
namespace QuasiRandom = Gaudi::Utils::QuasiRandom;
}
DECLARE_COMPONENT(RandomNumberAlg)
/** Algorithm parameters which can be set at run time must be declared.
......@@ -102,14 +108,17 @@ StatusCode RandomNumberAlg::initialize() {
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");
if ( m_ntuple ) {
status = m_ntuple->addItem ("Event#", m_int);
status = m_ntuple->addItem ("Gauss", m_gauss);
status = m_ntuple->addItem ("Exp", m_exponential);
status = m_ntuple->addItem ("Poisson", m_poisson);
status = m_ntuple->addItem ("Event#", m_int);
status = m_ntuple->addItem ("DeterInt", m_deter);
status = m_ntuple->addItem ("Gauss", m_gauss);
status = m_ntuple->addItem ("Exp", m_exponential);
status = m_ntuple->addItem ("Poisson", m_poisson);
}
return status;
}
......@@ -123,7 +132,14 @@ StatusCode RandomNumberAlg::execute() {
Rndm::Numbers exponential(randSvc(), Rndm::Exponential(0.2));
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_deter = scale(QuasiRandom::mix32(m_initial, m_int), 100);
m_gauss = (float)gauss();
m_exponential = (float)exponential();
m_poisson = (float)poisson();
......@@ -139,4 +155,3 @@ StatusCode RandomNumberAlg::finalize() {
m_numbers.finalize().ignore();
return StatusCode::SUCCESS;
}
......@@ -16,13 +16,16 @@ class RandomNumberAlg : public Algorithm {
protected:
/// Allocate wrapper for random number generator
Rndm::Numbers m_numbers;
/// Initial seed to fill deterministic random numbers
uint32_t m_initial;
/// Pointer to N-tuple
NTuple::Tuple* m_ntuple;
/// N-tuple items
NTuple::Item<int> m_int;
NTuple::Item<float> m_gauss;
NTuple::Item<float> m_exponential;
NTuple::Item<float> m_poisson;
NTuple::Item<int> m_int;
NTuple::Item<uint32_t> m_deter;
NTuple::Item<float> m_gauss;
NTuple::Item<float> m_exponential;
NTuple::Item<float> m_poisson;
public:
/// Constructor: A constructor of this form must be provided.
......
JobOptionsSvc INFO
//GP:================================================================================
//GP: include "/afs/cern.ch/user/m/marcocle/scratch0/workspace/Gaudi/GaudiExamples/options/RandomNumber.opts" (0,0)
AuditorSvc.Auditors = [ "ChronoAuditor" ] ; //GP: (1,1)
ApplicationMgr.TopAlg = [ "RandomNumberAlg" ] ; //GP: (1,1)
MessageSvc.OutputLevel = 2; //GP: (1,1)
ApplicationMgr.EvtMax = 1000; //GP: (1,1)
ApplicationMgr.EvtSel = "NONE"; //GP: (1,1)
ApplicationMgr.HistogramPersistency = "ROOT"; //GP: (1,1)
HistogramPersistencySvc.OutputFile = "histo.root"; //GP: (1,1)
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
JobOptionsSvc INFO # =======> /afs/cern.ch/work/r/raaij/dev-dir/GAUDI/GAUDI_v26r3/GaudiExamples/options/RandomNumber.opts
JobOptionsSvc INFO # (5,1): AuditorSvc.Auditors = ["ChronoAuditor"]
JobOptionsSvc INFO # (12,1): ApplicationMgr.TopAlg = ["RandomNumberAlg"]
JobOptionsSvc INFO # (15,1): MessageSvc.OutputLevel = 2
JobOptionsSvc INFO # (20,1): ApplicationMgr.EvtMax = 1000
JobOptionsSvc INFO # (21,1): ApplicationMgr.EvtSel = "NONE"
JobOptionsSvc INFO # (31,1): ApplicationMgr.HistogramPersistency = "ROOT"
JobOptionsSvc INFO # (32,1): HistogramPersistencySvc.OutputFile = "histo.root"
JobOptionsSvc INFO # (33,1): NTupleSvc.Output = ["FILE1 DATAFILE='NTuple.root' OPT='NEW' TYP='ROOT'"]
JobOptionsSvc INFO Job options successfully read in from /afs/cern.ch/work/r/raaij/dev-dir/GAUDI/GAUDI_v26r3/GaudiExamples/options/RandomNumber.opts
ApplicationMgr DEBUG Getting my own properties
ApplicationMgr SUCCESS
====================================================================================================================================
Welcome to ApplicationMgr $Revision: 1.77 $
running on pclhcb55 on Fri Apr 23 10:08:17 2010
Welcome to ApplicationMgr (GaudiCoreSvc v3r5)
running on lxplus0090.cern.ch on Tue Aug 25 14:01:55 2015
====================================================================================================================================
ApplicationMgr INFO Application Manager Configured successfully
ServiceManager DEBUG Initializing service AppMgrRunable
......@@ -60,6 +55,7 @@ ServiceManager DEBUG Starting service EventDataSvc
ServiceManager DEBUG Starting service EventLoopMgr
ApplicationMgr INFO Application Manager Started successfully
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: Exp / Exp/F
RRWNTupleCnv INFO ID 100: added branch: Poisson / Poisson/F
......@@ -86,22 +82,26 @@ RFileCnv INFO dumping contents of /NTUPLES/FILE1
TFile: name=NTuple.root, title=Gaudi Trees, option=CREATE
******************************************************************************
*Tree :100 : Hello World *
*Entries : 1000 : Total = 18571 bytes File Size = 10130 *
* : : Tree compression factor = 1.71 *
*Entries : 1000 : Total = 23150 bytes File Size = 11808 *
* : : Tree compression factor = 1.84 *
******************************************************************************
*Br 0 :Event# : Event#/I *
*Entries : 1000 : Total Size= 4558 bytes File Size = 1516 *
*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 *
*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 *
*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 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 7.22 *
*............................................................................*
......@@ -117,9 +117,9 @@ ServiceManager DEBUG Finalizing service RootHistSvc
RootHistSvc DEBUG RootHistCnv::PersSvc::finalize()
ServiceManager DEBUG Finalizing service RndmGenSvc
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 Service reference count check:
ServiceManager DEBUG Looping over all active services...
ServiceManager DEBUG ---- MessageSvc (refCount = 14)
ServiceManager DEBUG ---- JobOptionsSvc (refCount = 2)
ServiceManager DEBUG ---- RndmGenSvc.Engine (refCount = 3)
......
......@@ -76,6 +76,7 @@
#include "GaudiUtils/HistoStats.h"
#include "GaudiUtils/HistoDump.h"
#include "GaudiUtils/HistoStrings.h"
#include "GaudiUtils/QuasiRandom.h"
#include <iostream>
#include <istream>
......
......@@ -96,6 +96,11 @@
<class name= "Gaudi::Utils::Histos::Table" />
<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_" />
<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