Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
GSLRngROOTWrapper.h
Go to the documentation of this file.
1 // wrapper class used to wrap ROOT random number engines with GSL interface
2 
3 // @(#)root/mathmore:$Id$
4 // Author: L. Moneta Fri Aug 24 17:20:45 2007
5 
6 /**********************************************************************
7  * *
8  * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
9  * *
10  * *
11  **********************************************************************/
12 
13 // Header file for class GSLRngWrapper
14 
15 #ifndef ROOT_Math_GSLRngROOTWrapper
16 #define ROOT_Math_GSLRngROOTWrapper
17 
18 #include "gsl/gsl_rng.h"
19 
20 
21 namespace ROOT {
22 
23  namespace Math {
24 
25  /**
26  * class for wrapping ROOT Engines in gsl_rng types which can be used as extra
27  * GSL random number generators
28  * For this we need to implment functions which will be called by gsl_rng.
29  * The functions (Seed, Rndm, IntRndm) are passed in the gsl_rng_type and used to build a gsl_rng object.
30  * When gsl_rng is alloacated, only the memory state is allocated using calloc(1,size), which gives a memory
31  * block of the given bytes and it initializes to zero. Therefore no constructor of GSLRngROOTWrapper can be called
32  * and also we cannot call non-static member funciton of the class.
33  * The underlined ROOT engine is then built and deleted using the functions CreateEngine() and FreeEngine(),
34  * called by the specific GSLRandomEngine class that instantiates for the the generator (e.g. GSLRngMixMax)
35  *
36  **/
37  template <class Engine>
38  struct GSLRngROOTWrapper {
39 
40  Engine *fEngine = nullptr;
41 
42  // non need to have specific ctor/dtor since we cannot call them
43 
44  // function called by the specific GSLRndmEngine to create the ROOT engine
45  static void CreateEngine(gsl_rng *r)
46  {
47  // the engine pointer is retrieved from r
48  GSLRngROOTWrapper *wrng = ((GSLRngROOTWrapper *)r->state);
49  //printf("calling create engine - engine pointer : %p\n", wrng->fEngine);
50  if (!wrng->fEngine)
51  wrng->fEngine = new Engine();
52  // do nothing in case it is already created (e.g. when calling with default_seed)
53  }
54 
55  static double Rndm(void *p) { return ((GSLRngROOTWrapper *)p)->fEngine->operator()(); }
56  static unsigned long IntRndm(void *p) { return ((GSLRngROOTWrapper *)p)->fEngine->IntRndm(); }
57 
58  static void Seed(void *p, unsigned long seed)
59  {
60  auto wrng = ((GSLRngROOTWrapper *)p);
61  // (GSL calls at the beginning with the defaul seed (typically zero))
62  //printf("calling the seed function with %d on %p and engine %p\n", seed, p, wrng->fEngine);
63  if (seed == gsl_rng_default_seed) {
64  seed = 111; // avoid using 0 that for ROOT means a specific seed
65  if (!wrng->fEngine) wrng->fEngine = new Engine();
66  }
67  assert(wrng->fEngine != nullptr);
68  wrng->fEngine->SetSeed(seed);
69  }
70  static void FreeEngine(gsl_rng *r)
71  {
72  auto wrng = ((GSLRngROOTWrapper *)r->state);
73  if (wrng->fEngine)
74  delete wrng->fEngine;
75  wrng->fEngine = nullptr;
76  }
77 
78  static unsigned long Max() { return Engine::MaxInt(); }
79  static unsigned long Min() { return Engine::MinInt(); }
80  static size_t Size() { return sizeof(GSLRngROOTWrapper<Engine>); }
81  static std::string Name() { return std::string("GSL_") + Engine::Name(); }
82  };
83 
84  } // end namespace Math
85 } // end namespace ROOT
86 
87 #include "Math/MixMaxEngine.h"
88 
89 // now define and implement the specific types
90 
91 typedef ROOT::Math::GSLRngROOTWrapper<ROOT::Math::MixMaxEngine<17,0>> GSLMixMaxWrapper;
92 
93 static const std::string gsl_mixmax_name = GSLMixMaxWrapper::Name();
94 static const gsl_rng_type mixmax_type =
95 {
96  gsl_mixmax_name.c_str(),
97  GSLMixMaxWrapper::Max(),
98  GSLMixMaxWrapper::Min(),
99  GSLMixMaxWrapper::Size(),
100  &GSLMixMaxWrapper::Seed,
101  &GSLMixMaxWrapper::IntRndm,
102  &GSLMixMaxWrapper::Rndm
103 };
104 
105 const gsl_rng_type *gsl_rng_mixmax = &mixmax_type;
106 
107 #endif
108