Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
70456494aae1502183d7f4f23a2bb69bd4362fd1
[simgrid.git] / src / xbt / random.cpp
1 /* Copyright (c) 2019. The SimGrid Team. All rights reserved.               */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "xbt/random.hpp"
7 #include "xbt/asserts.h"
8 #include <limits>
9 #include <random>
10
11 namespace simgrid {
12 namespace xbt {
13 namespace random {
14 std::mt19937 mt19937_gen;
15 xbt_random_method current_rng = XBT_RNG_xbt;
16
17 void use_xbt()
18 {
19   current_rng = XBT_RNG_xbt;
20 }
21 void use_std()
22 {
23   current_rng = XBT_RNG_std;
24 }
25
26 int uniform_int(int min, int max)
27 {
28   switch (current_rng) {
29     case XBT_RNG_xbt:
30       return xbt_uniform_int(min, max);
31     case XBT_RNG_std: {
32       std::uniform_int_distribution<> dist(min, max);
33       return dist(mt19937_gen);
34     }
35     default:
36       xbt_assert(false, "The uniform integer distribution is not yet supported for the current RNG.");
37   }
38 }
39
40 int xbt_uniform_int(int min, int max)
41 {
42   unsigned long gmin   = mt19937_gen.min();
43   unsigned long gmax   = mt19937_gen.max();
44   unsigned long grange = gmax - gmin + 1;
45   unsigned long range  = max - min + 1;
46   xbt_assert(
47       min <= max,
48       "The maximum value for the uniform integer distribution must be greater than or equal to the minimum value");
49   xbt_assert(range <= grange, "The current implementation of the uniform integer distribution does not allow range to "
50                               "be higher than mt19937's range");
51   unsigned long mult       = grange / range;
52   unsigned long maxallowed = gmin + (mult + 1) * range - 1;
53   while (true) {
54     unsigned long value = mt19937_gen();
55     if (value > maxallowed) {
56     } else {
57       return value % range + min;
58     }
59   }
60 }
61
62 double uniform_real(double min, double max)
63 {
64   switch (current_rng) {
65     case XBT_RNG_xbt:
66       return xbt_uniform_real(min, max);
67     case XBT_RNG_std: {
68       std::uniform_real_distribution<> dist(min, max);
69       return dist(mt19937_gen);
70     }
71     default:
72       xbt_assert(false, "The uniform real distribution is not yet supported for the current RNG.");
73   }
74 }
75
76 double xbt_uniform_real(double min, double max)
77 {
78   // This reuses Boost's uniform real distribution ideas
79   unsigned long numerator = mt19937_gen() - mt19937_gen.min();
80   unsigned long divisor   = mt19937_gen.max() - mt19937_gen.min();
81   return min + (max - min) * numerator / divisor;
82 }
83
84 double exponential(double lambda)
85 {
86   switch (current_rng) {
87     case XBT_RNG_xbt:
88       return xbt_exponential(lambda);
89     case XBT_RNG_std: {
90       std::exponential_distribution<> dist(lambda);
91       return dist(mt19937_gen);
92     }
93     default:
94       xbt_assert(false, "The exponential distribution is not yet supported for the current RNG.");
95   }
96 }
97
98 double xbt_exponential(double lambda)
99 {
100   return -1 / lambda * log(uniform_real(0, 1));
101 }
102
103 double normal(double mean, double sd)
104 {
105   switch (current_rng) {
106     case XBT_RNG_xbt:
107       return xbt_normal(mean, sd);
108     case XBT_RNG_std: {
109       std::normal_distribution<> dist(mean, sd);
110       return dist(mt19937_gen);
111     }
112     default:
113       xbt_assert(false, "The normal distribution is not yet supported for the curent RNG.");
114   }
115 }
116
117 double xbt_normal(double mean, double sd)
118 {
119   double u1 = 0;
120   while (u1 < std::numeric_limits<double>::min()) {
121     u1 = uniform_real(0, 1);
122   }
123   double u2 = uniform_real(0, 1);
124   double z0 = sqrt(-2.0 * log(u1)) * cos(2 * M_PI * u2);
125   return z0 * sd + mean;
126 }
127
128 void set_mersenne_seed(int seed)
129 {
130   mt19937_gen.seed(seed);
131 }
132
133 } // namespace random
134 } // namespace xbt
135 } // namespace simgrid