Commit fe39596d86b7cd62b83e728160fcf84ac514f4cd

Authored by Jürgen Knödlseder
1 parent 7956c168

Updated code.

include/GRan.hpp
1 1 /***************************************************************************
2 2 * GRan.hpp - Random number generator class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2011-2013 by Juergen Knoedlseder *
  4 + * copyright (C) 2011-2014 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -71,16 +71,16 @@ protected:
71 71 void free_members(void);
72 72  
73 73 // Protected data members
74   - unsigned long long int m_seed; //!< Random number generator seed
75   - unsigned long long int m_u; //!< u
76   - unsigned long long int m_v; //!< v
77   - unsigned long long int m_w; //!< w
  74 + unsigned long long int m_seed; //!< Random number generator seed
  75 + unsigned long long int m_value1; //!< Value 1
  76 + unsigned long long int m_value2; //!< Value 2
  77 + unsigned long long int m_value3; //!< Value 3
78 78  
79 79 // Poisson cache
80   - double m_oldm;
81   - double m_sq;
82   - double m_alxm;
83   - double m_g;
  80 + double m_old_lambda; //!< Old lambda value
  81 + double m_sqrt_lambda; //!< sqrt(2*lambda)
  82 + double m_log_lambda; //!< log(lambda)
  83 + double m_exp_lambda; //!< exp(-lambda)
84 84 };
85 85  
86 86  
... ...
src/support/GRan.cpp
1 1 /***************************************************************************
2 2 * GRan.cpp - Random number generator class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2011-2013 by Juergen Knoedlseder *
  4 + * copyright (C) 2011-2014 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -202,8 +202,6 @@ void GRan::seed(unsigned long long int seed)
202 202  
203 203 /***********************************************************************//**
204 204 * @brief Return 32-bit random unsigned integer
205   - *
206   - * This method is inspired from Numerical Recipes Third Edition, page 343.
207 205 ***************************************************************************/
208 206 unsigned long int GRan::int32(void)
209 207 {
... ... @@ -214,36 +212,32 @@ unsigned long int GRan::int32(void)
214 212  
215 213 /***********************************************************************//**
216 214 * @brief Return 64-bit random unsigned integer
217   - *
218   - * This method is inspired from Numerical Recipes Third Edition, page 343.
219 215 ***************************************************************************/
220 216 unsigned long long int GRan::int64(void)
221 217 {
222 218 // Update u
223   - m_u = m_u * 2862933555777941757LL + 7046029254386353087LL;
  219 + m_value1 = m_value1 * 2862933555777941757LL + 7046029254386353087LL;
224 220  
225 221 // Shuffle v
226   - m_v ^= m_v >> 17;
227   - m_v ^= m_v << 31;
228   - m_v ^= m_v >> 8;
  222 + m_value2 ^= m_value2 >> 17;
  223 + m_value2 ^= m_value2 << 31;
  224 + m_value2 ^= m_value2 >> 8;
229 225  
230 226 // Update w
231   - m_w = 4294957665U * (m_w & 0xffffffff) + (m_w >> 32);
  227 + m_value3 = 4294957665U * (m_value3 & 0xffffffff) + (m_value3 >> 32);
232 228  
233 229 // Compute x
234   - unsigned long long int x = m_u ^ (m_u << 21);
  230 + unsigned long long int x = m_value1 ^ (m_value1 << 21);
235 231 x ^= x >> 35;
236 232 x ^= x << 4;
237 233  
238 234 // Return random value
239   - return ((x + m_v) ^ m_w);
  235 + return ((x + m_value2) ^ m_value3);
240 236 }
241 237  
242 238  
243 239 /***********************************************************************//**
244 240 * @brief Returns random double precision floating value in range 0 to 1
245   - *
246   - * This method is inspired from Numerical Recipes Third Edition, page 343.
247 241 ***************************************************************************/
248 242 double GRan::uniform(void)
249 243 {
... ... @@ -264,8 +258,6 @@ double GRan::uniform(void)
264 258 * This method may be used to simulate the occurence time of an event, where
265 259 * \f$\lambda\f$ is the mean event rate. Convsersely, \f$1/\lambda\f$ is the
266 260 * mean waiting time between events.
267   - *
268   - * This method is inspired from Numerical Recipes Third Edition, page 362.
269 261 *
270 262 * @todo Check that \f$\lambda>0\f$.
271 263 ***************************************************************************/
... ... @@ -293,51 +285,49 @@ double GRan::exp(const double&amp; lambda)
293 285 *
294 286 * This method may be used to simulate the number of events in case that a
295 287 * given mean number of events is expected.
296   - *
297   - * This method is inspired from Numerical Recipes Third Edition, page 362.
298 288 ***************************************************************************/
299 289 double GRan::poisson(const double& lambda)
300 290 {
301 291 // Declare result
302   - double em;
  292 + double value;
303 293  
304 294 // Use direct method for small numbers ...
305 295 if (lambda < 12.0) {
306   - if (lambda != m_oldm) {
307   - m_oldm = lambda;
308   - m_g = std::exp(-lambda);
  296 + if (lambda != m_old_lambda) {
  297 + m_old_lambda = lambda;
  298 + m_exp_lambda = std::exp(-lambda);
309 299 }
310   - em = -1.0;
311   - double t = 1.0;
  300 + value = -1.0;
  301 + double tmp = 1.0;
312 302 do {
313   - em += 1.0;
314   - t *= uniform();
315   - } while (t > m_g);
  303 + value += 1.0;
  304 + tmp *= uniform();
  305 + } while (tmp > m_exp_lambda);
316 306 } // endif: direct method used
317 307  
318 308 // ... otherwise use rejection method
319 309 else {
320   - double t;
321   - if (lambda != m_oldm) {
322   - m_oldm = lambda;
323   - m_sq = std::sqrt(2.0*lambda);
324   - m_alxm = std::log(lambda);
325   - m_g = lambda * m_alxm - gammalib::gammln(lambda+1.0);
  310 + double tmp;
  311 + if (lambda != m_old_lambda) {
  312 + m_old_lambda = lambda;
  313 + m_sqrt_lambda = std::sqrt(2.0*lambda);
  314 + m_log_lambda = std::log(lambda);
  315 + m_exp_lambda = lambda * m_log_lambda - gammalib::gammln(lambda+1.0);
326 316 }
327 317 do {
328   - double y;
  318 + double factor;
329 319 do {
330   - y = std::tan(gammalib::pi * uniform());
331   - em = m_sq * y + lambda;
332   - } while (em < 0.0);
333   - em = floor(em);
334   - t = 0.9*(1.0+y*y) *
335   - std::exp(em*m_alxm - gammalib::gammln(em+1.0)-m_g);
336   - } while (uniform() > t);
  320 + factor = std::tan(gammalib::pi * uniform());
  321 + value = m_sqrt_lambda * factor + lambda;
  322 + } while (value < 0.0);
  323 + value = floor(value);
  324 + tmp = 0.9*(1.0+factor*factor) *
  325 + std::exp(value*m_log_lambda - gammalib::gammln(value+1.0)-m_exp_lambda);
  326 + } while (uniform() > tmp);
337 327 }
338 328  
339 329 // Return random deviate
340   - return em;
  330 + return value;
341 331 }
342 332  
343 333  
... ... @@ -384,9 +374,9 @@ std::string GRan::print(const GChatter&amp; chatter) const
384 374  
385 375 // Append information
386 376 result.append("\n"+gammalib::parformat("Seed")+gammalib::str(m_seed));
387   - result.append("\n"+gammalib::parformat("u")+gammalib::str(m_u));
388   - result.append("\n"+gammalib::parformat("v")+gammalib::str(m_v));
389   - result.append("\n"+gammalib::parformat("w")+gammalib::str(m_w));
  377 + result.append("\n"+gammalib::parformat("Value 1")+gammalib::str(m_value1));
  378 + result.append("\n"+gammalib::parformat("Value 2")+gammalib::str(m_value2));
  379 + result.append("\n"+gammalib::parformat("Value 3")+gammalib::str(m_value3));
390 380  
391 381 } // endif: chatter was not silent
392 382  
... ... @@ -407,20 +397,20 @@ std::string GRan::print(const GChatter&amp; chatter) const
407 397 void GRan::init_members(unsigned long long int seed)
408 398 {
409 399 // Initialise members
410   - m_seed = seed;
411   - m_v = 4101842887655102017LL;
412   - m_w = 1;
413   - m_oldm = -1.0;
414   - m_sq = 0.0;
415   - m_alxm = 0.0;
416   - m_g = 0.0;
417   -
418   - // Initialise u, v, and w
419   - m_u = m_seed ^ m_v;
  400 + m_seed = seed;
  401 + m_value2 = 4101842887655102017LL;
  402 + m_value3 = 1;
  403 + m_old_lambda = -1.0;
  404 + m_sqrt_lambda = 0.0;
  405 + m_log_lambda = 0.0;
  406 + m_exp_lambda = 0.0;
  407 +
  408 + // Initialise values
  409 + m_value1 = m_seed ^ m_value2;
420 410 int64();
421   - m_v = m_u;
  411 + m_value2 = m_value1;
422 412 int64();
423   - m_w = m_v;
  413 + m_value3 = m_value2;
424 414 int64();
425 415  
426 416 // Return
... ... @@ -436,14 +426,14 @@ void GRan::init_members(unsigned long long int seed)
436 426 void GRan::copy_members(const GRan& ran)
437 427 {
438 428 // Copy members
439   - m_seed = ran.m_seed;
440   - m_u = ran.m_u;
441   - m_v = ran.m_v;
442   - m_w = ran.m_w;
443   - m_oldm = ran.m_oldm;
444   - m_sq = ran.m_sq;
445   - m_alxm = ran.m_alxm;
446   - m_g = ran.m_g;
  429 + m_seed = ran.m_seed;
  430 + m_value1 = ran.m_value1;
  431 + m_value2 = ran.m_value2;
  432 + m_value3 = ran.m_value3;
  433 + m_old_lambda = ran.m_old_lambda;
  434 + m_sqrt_lambda = ran.m_sqrt_lambda;
  435 + m_log_lambda = ran.m_log_lambda;
  436 + m_exp_lambda = ran.m_exp_lambda;
447 437  
448 438 // Return
449 439 return;
... ...