Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
3b2962fb85b91983767e33bb4d5aa8940450d9de
[simgrid.git] / src / xbt / random.cpp
1 /* Copyright (c) 2019-2020. 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 <memory>
10 #include <string>
11
12 namespace simgrid {
13 namespace xbt {
14 namespace random {
15
16 int StdRandom::uniform_int(int min, int max)
17 {
18   std::uniform_int_distribution<> dist(min, max);
19   return dist(mt19937_gen);
20 }
21
22 double StdRandom::uniform_real(double min, double max)
23 {
24   std::uniform_real_distribution<> dist(min, max);
25   return dist(mt19937_gen);
26 }
27
28 double StdRandom::exponential(double lambda)
29 {
30   std::exponential_distribution<> dist(lambda);
31   return dist(mt19937_gen);
32 }
33
34 double StdRandom::normal(double mean, double sd)
35 {
36   std::normal_distribution<> dist(mean, sd);
37   return dist(mt19937_gen);
38 }
39
40 int XbtRandom::uniform_int(int min, int max)
41 {
42   unsigned long range  = max - min + 1;
43   xbt_assert(min <= max,
44              "The minimum value for the uniform integer distribution must not be greater than the maximum value");
45   xbt_assert(range > 0, "Overflow in the uniform integer distribution, please use a smaller range.");
46   unsigned long value;
47   do {
48     value = mt19937_gen();
49   } while (value >= decltype(mt19937_gen)::max() - decltype(mt19937_gen)::max() % range);
50   return value % range + min;
51 }
52
53 double XbtRandom::uniform_real(double min, double max)
54 {
55   // This reuses Boost's uniform real distribution ideas
56   constexpr unsigned long divisor = decltype(mt19937_gen)::max() - decltype(mt19937_gen)::min();
57   unsigned long numerator;
58   do {
59     numerator = mt19937_gen() - decltype(mt19937_gen)::min();
60   } while (numerator == divisor);
61   return min + (max - min) * numerator / divisor;
62 }
63
64 double XbtRandom::exponential(double lambda)
65 {
66   return -1.0 / lambda * log(uniform_real(0.0, 1.0));
67 }
68
69 double XbtRandom::normal(double mean, double sd)
70 {
71   double u1;
72   do {
73     u1 = uniform_real(0.0, 1.0);
74   } while (u1 < std::numeric_limits<double>::min());
75   double u2 = uniform_real(0.0, 1.0);
76   double z0 = sqrt(-2.0 * log(u1)) * cos(2.0 * M_PI * u2);
77   return z0 * sd + mean;
78 }
79
80 static std::unique_ptr<Random> default_random(new XbtRandom);
81
82 void set_implem_xbt()
83 {
84   default_random.reset(new XbtRandom);
85 }
86 void set_implem_std()
87 {
88   default_random.reset(new StdRandom);
89 }
90
91 void set_mersenne_seed(int seed)
92 {
93   default_random->set_seed(seed);
94 }
95
96 void read_mersenne_state(std::string filename)
97 {
98   default_random->read_state(filename);
99 }
100
101 void write_mersenne_state(std::string filename)
102 {
103   default_random->write_state(filename);
104 }
105
106 int uniform_int(int min, int max)
107 {
108   return default_random->uniform_int(min, max);
109 }
110
111 double uniform_real(double min, double max)
112 {
113   return default_random->uniform_real(min, max);
114 }
115
116 double exponential(double lambda)
117 {
118   return default_random->exponential(lambda);
119 }
120
121 double normal(double mean, double sd)
122 {
123   return default_random->normal(mean, sd);
124 }
125
126 } // namespace random
127 } // namespace xbt
128 } // namespace simgrid