The ROme OpTimistic Simulator  3.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
random.c
Go to the documentation of this file.
1 
11 #include <lib/random/random.h>
12 
13 #include <core/intrinsics.h>
14 #include <lib/lib_internal.h>
15 #include <lib/random/xoroshiro.h>
16 
17 #include <math.h>
18 #include <memory.h>
19 
20 void random_lib_lp_init(void)
21 {
22  uint64_t seed = global_config.prng_seed;
23  lp_id_t lid = lp_id_get();
24  struct lib_ctx *ctx = lib_ctx_get();
25  random_init(ctx->rng_s, lid, seed);
26  ctx->unif = NAN;
27 }
28 
29 double Random(void)
30 {
31  struct lib_ctx *ctx = lib_ctx_get();
32  uint64_t u_val = random_u64(ctx->rng_s);
33  if (unlikely(!u_val))
34  return 0.0;
35 
36  double ret = 0.0;
37  unsigned lzs = intrinsics_clz(u_val) + 1;
38  u_val <<= lzs;
39  u_val >>= 12;
40 
41  uint64_t exp = 1023 - lzs;
42  u_val |= exp << 52;
43 
44  memcpy(&ret, &u_val, sizeof(double));
45  return ret;
46 }
47 
48 uint64_t RandomU64(void)
49 {
50  struct lib_ctx *ctx = lib_ctx_get();
51  return random_u64(ctx->rng_s);
52 }
53 
61 double Expent(double mean)
62 {
63  if (unlikely(mean < 0)) {
64  log_log(LOG_WARN, "Passed a negative mean into Expent()");
65  }
66  return -mean * log(1 - Random());
67 }
68 
74 double Normal(void)
75 {
76  struct lib_ctx *ctx = lib_ctx_get();
77  if (isnan(ctx->unif)) {
78  double v1, v2, rsq;
79  do {
80  v1 = 2.0 * Random() - 1.0;
81  v2 = 2.0 * Random() - 1.0;
82  rsq = v1 * v1 + v2 * v2;
83  } while (rsq >= 1.0 || rsq == 0);
84 
85  double fac = sqrt(-2.0 * log(rsq) / rsq);
86 
87  // Perform Box-Muller transformation to get two normal deviates.
88  // Return one and save the other for next time.
89  ctx->unif = v1 * fac;
90  return v2 * fac;
91  } else {
92  // A deviate is already available
93  double ret = ctx->unif;
94  ctx->unif = NAN;
95  return ret;
96  }
97 }
98 
99 int RandomRange(int min, int max)
100 {
101  return (int)floor(Random() * (max - min + 1)) + min;
102 }
103 
104 int RandomRangeNonUniform(int x, int min, int max)
105 {
106  return (((RandomRange(0, x) | RandomRange(min, max))) %
107  (max - min + 1)) + min;
108 }
109 
118 double Gamma(unsigned ia)
119 {
120  if (unlikely(ia < 1)) {
121  log_log(LOG_WARN, "Gamma distribution must have a ia "
122  "value >= 1. Defaulting to 1...");
123  ia = 1;
124  }
125 
126  double x;
127 
128  if (ia < 6) {
129  // Use direct method, adding waiting times
130  x = 1.0;
131  while (ia--)
132  x *= 1 - Random();
133  x = -log(x);
134  } else {
135  double am = ia - 1;
136  double v1, v2, e, y, s;
137  // Use rejection method
138  do {
139  do {
140  do {
141  v1 = Random();
142  v2 = 2.0 * Random() - 1.0;
143  } while (v1 * v1 + v2 * v2 > 1.0);
144 
145  y = v2 / v1;
146  s = sqrt(2.0 * am + 1.0);
147  x = s * y + am;
148  } while (x < 0.0);
149 
150  e = (1.0 + y * y) * exp(am * log(x / am) - s * y);
151  } while (Random() > e);
152  }
153 
154  return x;
155 }
156 
162 double Poisson(void)
163 {
164  return -log(1 - Random());
165 }
166 
176 unsigned Zipf(double skew, unsigned limit)
177 {
178  double b = pow(2., skew - 1.);
179  double x, t;
180  do {
181  x = floor(pow(Random(), -1. / skew - 1.));
182  t = pow(1. + 1. / x, skew - 1.);
183  } while (x > limit || Random() * x * (t - 1.) * b > t * (b - 1.));
184  return x;
185 }
intrinsics_clz
#define intrinsics_clz(x)
Counts the leading zeros in a base 2 number.
Definition: intrinsics.h:47
lib_internal.h
Internal core libraries.
random.h
Random Number Generators.
Expent
double Expent(double mean)
Definition: random.c:61
log_log
#define log_log(lvl,...)
Produces a log.
Definition: log.h:49
Gamma
double Gamma(unsigned ia)
Definition: random.c:118
lib_ctx
Definition: lib.h:17
lp_id_t
uint64_t lp_id_t
Used to uniquely identify LPs in the simulation.
Definition: core.h:75
LOG_WARN
#define LOG_WARN
The logging level reserved to unexpected, non deal breaking conditions.
Definition: log.h:31
Poisson
double Poisson(void)
Definition: random.c:162
Zipf
unsigned Zipf(double skew, unsigned limit)
Definition: random.c:176
xoroshiro.h
Xoroshiro RNG support functions.
unlikely
#define unlikely(exp)
Optimize the branch as likely not taken.
Definition: core.h:59
global_config
struct simulation_configuration global_config
The configuration filled in by init_args_parse()
Definition: init.c:27
intrinsics.h
Easier access to compiler extensions.
Normal
double Normal(void)
Definition: random.c:74
simulation_configuration::prng_seed
uint64_t prng_seed
The seed used to initialize the pseudo random numbers.
Definition: init.h:28