FastJet  3.4.0
BasicRandom.hh
1 // Simple random number generator class taken from nlojet++.
2 // $Id$
3 //
4 // Copyright (C) 2002 Zoltan Nagy
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 //
20 // Changes compared to the original version
21 // 2006-08: Some doxygen-style comments added by Gavin Salam
22 // 2017-02: The operator() (size_type, pointer, std::vector<int> &);
23 // members have been added to implement thread-safe access to the
24 // generators
25 //
26 
27 #ifndef __FASTJET_BASICRANDOM_HH__
28 #define __FASTJET_BASICRANDOM_HH__ 1
29 
30 // Standard includes
31 #include <iostream>
32 #include <vector>
33 #include <cassert>
34 #include "fastjet/internal/base.hh"
35 
36 #include "fastjet/config.h"
37 #ifdef FASTJET_HAVE_LIMITED_THREAD_SAFETY
38 #include <mutex>
39 #endif
40 
41 
42 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
43 
44 /// \if internal_doc
45 /// @ingroup internal
46 /// \class BasicRandom
47 /// Base class for random number generator of a generic value type
48 /// \endif
49 template<typename _Tp> class BasicRandom {
50 public:
51  typedef _Tp value_type;
52  typedef unsigned int size_type;
53  typedef value_type* pointer;
54 
55  // give pseudo random numbers
56  value_type operator() ();
57  void operator() (size_type, pointer);
58 
59  // (re)initialize the random number generator
60  void randomize(void *);
61 
62  // minimum and maximum values
63  static value_type min();
64  static value_type max();
65 
66  // print the informations about the generator to the stream
67  void print_info(std::ostream& __os = std::cout);
68 };
69 
70 // default random generator
71 int __default_random_generator(int *__iseed);
72 
73 
74 // specializations
75 
76 /// \if internal_doc
77 /// @ingroup internal
78 /// template specialization (int) for the BasicRandom template class.
79 /// \endif
80 template<>
81 class BasicRandom<int>
82 {
83 public:
84  typedef int value_type;
85  typedef unsigned int size_type;
86  typedef value_type* pointer;
87 
88  // constructors
89  explicit BasicRandom(int __s1 = 12345, int __s2 = 67890) {
90  _M_iseed[0] = __s1;
91  _M_iseed[1] = __s2;
92  }
93 
94  // give pseudo random numbers
95  value_type operator() () {
96  return __default_random_generator(_M_iseed);
97  }
98 
99  void operator() (size_type __n, pointer __res) {
100  for(size_type __i = 0; __i < __n; __i++)
101  __res[__i] = __default_random_generator(_M_iseed);
102  }
103 
104  /// given a pointer __res to the beginning of an array, fill that array
105  /// with __n random numbers
106  ///
107  /// This now acquired an extra argument which allows to retreive the
108  /// set of seeds used for this generation.
109  void operator() (size_type __n, pointer __res, std::vector<int> & __iseed) {
110  // if we have (limited) thread safety, lock things
111 #ifdef FASTJET_HAVE_LIMITED_THREAD_SAFETY
112  // is the lock here really necessary or would a spinlock do better?
113  std::lock_guard<std::mutex> guard(_multiple_number_generation_mutex);
114 #endif
115  // get the seeds
116  get_status(__iseed);
117 
118  // get the numbers
119  for(size_type __i = 0; __i < __n; __i++)
120  __res[__i] = __default_random_generator(_M_iseed);
121  }
122 
123  // (re)initialize the random number generator
124  void randomize(void *__iseed) {
125  int *__new_seed = (int*) __iseed;
126  _M_iseed[0] = __new_seed[0];
127  _M_iseed[1] = __new_seed[1];
128  }
129 
130  void set_status(const std::vector<int> & __iseed) {
131  assert(__iseed.size() >= 2);
132  _M_iseed[0] = __iseed[0];
133  _M_iseed[1] = __iseed[1];
134  }
135 
136  void get_status(std::vector<int> & __iseed) {
137  __iseed.resize(2);
138  __iseed[0] = _M_iseed[0];
139  __iseed[1] = _M_iseed[1];
140  }
141 
142  // minimum and maximum values
143  inline static value_type min() { return 0;}
144  inline static value_type max() { return 2147483647;}
145 
146  // print the informations about the generator to the stream
147  void print_info(std::ostream& __os = std::cout) {
148  __os<<"BasicRandom<int> : "<<_M_iseed[0]<<", "<<_M_iseed[1]<<std::endl;
149  }
150 
151 private:
152  int _M_iseed[2];
153 #ifdef FASTJET_HAVE_LIMITED_THREAD_SAFETY
154  static std::mutex _multiple_number_generation_mutex;
155 #endif
156 };
157 
158 
159 /// \if internal_doc
160 /// @ingroup internal
161 /// template specialization (double) for the BasicRandom template class.
162 /// \endif
163 template<> class BasicRandom<double> {
164 public:
165  typedef double value_type;
166  typedef unsigned int size_type;
167  typedef value_type* pointer;
168 
169  /// constructor that takes two integers to specify the seed
170  explicit BasicRandom(int __s1 = 12345, int __s2 = 67890) {
171  _M_iseed[0] = __s1;
172  _M_iseed[1] = __s2;
173  }
174 
175  /// return a single pseudorandom double number, in the range 0.0 to 1.0
176  /// (not sure whether this range is open or closed)
177  value_type operator() () {
178  return 4.6566128752457969241e-10*__default_random_generator(_M_iseed);
179  }
180 
181  /// given a pointer __res to the beginning of an array, fill that array
182  /// with __n random numbers
183  void operator() (size_type __n, pointer __res) {
184  for(size_type __i = 0; __i < __n; __i++)
185  __res[__i] = this -> operator()();
186  }
187 
188  /// given a pointer __res to the beginning of an array, fill that array
189  /// with __n random numbers
190  ///
191  /// This now acquired an extra argument which allows to retreive the
192  /// set of seeds used for this generation.
193  void operator() (size_type __n, pointer __res, std::vector<int> & __iseed) {
194  // if we have (limited) thread safety, lock things
195 #ifdef FASTJET_HAVE_LIMITED_THREAD_SAFETY
196  // is the lock here really necessary or would a spinlock do better?
197  std::lock_guard<std::mutex> guard(_multiple_number_generation_mutex);
198 #endif
199  // get the seeds
200  get_status(__iseed);
201 
202  // get the numbers
203  for(size_type __i = 0; __i < __n; __i++)
204  __res[__i] = this -> operator()();
205  }
206 
207  /// (re)initialize the random number generator from an array of seeds
208  void randomize(void *__iseed) {
209  int *__new_seed = (int*) __iseed;
210  _M_iseed[0] = __new_seed[0];
211  _M_iseed[1] = __new_seed[1];
212  }
213 
214  void set_status(const std::vector<int> & __iseed) {
215  assert(__iseed.size() >= 2);
216  _M_iseed[0] = __iseed[0];
217  _M_iseed[1] = __iseed[1];
218  }
219 
220  void get_status(std::vector<int> & __iseed) {
221  __iseed.resize(2);
222  __iseed[0] = _M_iseed[0];
223  __iseed[1] = _M_iseed[1];
224  }
225 
226  /// minimum value returned by the generator
227  inline static value_type min() { return 0.0;}
228  /// maximum value returned by the generator
229  inline static value_type max() { return 1.0;}
230 
231  /// print information about the generator to the stream
232  void print_info(std::ostream& __os = std::cout) {
233  __os<<"BasicRandom<double> : "<<_M_iseed[0]<<", "<<_M_iseed[1]<<std::endl;
234  }
235 
236 private:
237  int _M_iseed[2];
238 #ifdef FASTJET_HAVE_LIMITED_THREAD_SAFETY
239  static std::mutex _multiple_number_generation_mutex;
240 #endif
241 };
242 
243 // globally defined random number generator
244 extern BasicRandom<int> _G_random_int;
245 extern BasicRandom<double> _G_random_double;
246 
247 
248 FASTJET_END_NAMESPACE
249 
250 #endif // __FASTJET_BASICRANDOM_HH__
251