Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2019 Jakub Rydzewski (jr@fizyka.umk.pl). All rights reserved.
3 :
4 : See http://www.maze-code.github.io for more information.
5 :
6 : This file is part of maze.
7 :
8 : maze is free software: you can redistribute it and/or modify it under the
9 : terms of the GNU Lesser General Public License as published by the Free
10 : Software Foundation, either version 3 of the License, or (at your option)
11 : any later version.
12 :
13 : maze is distributed in the hope that it will be useful, but WITHOUT ANY
14 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 : FOR A PARTICULAR PURPOSE.
16 :
17 : See the GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with maze. If not, see <https://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #ifndef __PLUMED_maze_Random_MT_h
23 : #define __PLUMED_maze_Random_MT_h
24 :
25 : /**
26 : * @file Random_MT.h
27 : *
28 : * @author J. Rydzewski (jr@fizyka.umk.pl)
29 : */
30 :
31 : #include "Core.h"
32 :
33 : namespace PLMD {
34 : namespace maze {
35 :
36 : /**
37 : * @class rnd Random_MT.h "maze/Random_MT.h"
38 : *
39 : * @brief Mersenne Twister sampler for random variables.
40 : *
41 : * Supports generating integers, doubles, and std::vectors and PLMD::Vectors
42 : * within a given range.
43 : */
44 : class rnd {
45 : public:
46 : /**
47 : * Initialize MT sampler engine based on std::mt19937_64.
48 : */
49 : static std::mt19937_64& mt_eng();
50 :
51 : /**
52 : * Feed a random seed.
53 : */
54 : static void randomize();
55 :
56 : /**
57 : * Returns a random double from the Cauchy distribution.
58 : *
59 : * @param m mean
60 : * @param s spread
61 : */
62 : static double next_cauchy(double m, double s);
63 :
64 : /**
65 : * Returns a random int from the uniform distribution from a [f, e) range.
66 : *
67 : * @param f begin
68 : * @param e end
69 : */
70 : static int next_int(int f, int e);
71 : static int next_int(int e);
72 :
73 : /**
74 : * Returns a random double from the uniform distribution from a [f, e) range.
75 : */
76 : static double next_double(double f, double e);
77 : static double next_double(double e);
78 : static double next_double();
79 :
80 : /**
81 : * Returns a random vector<double> from the uniform distribution from a [f, e)
82 : * range of length n.
83 : */
84 : static std::vector<double> next_double(double f, double e, std::size_t n);
85 :
86 : /**
87 : * Returns a random PLMD::Vector of length r.
88 : */
89 : static Vector next_plmd_vector();
90 : static Vector next_plmd_vector(double r);
91 :
92 : /**
93 : * Returns a random std::vector of length r.
94 : */
95 : static std::vector<double> next_std_vector();
96 : static std::vector<double> next_std_vector(double r);
97 : };
98 :
99 66 : inline Vector rnd::next_plmd_vector(double r) {
100 66 : return next_plmd_vector() * r;
101 : }
102 :
103 : inline std::vector<double> rnd::next_std_vector(double r) {
104 : double t = next_double() * 2.0 * pi;
105 : double p = next_double() * pi;
106 :
107 : return std::vector<double> {
108 : r * std::sin(p) * std::cos(t),
109 : r * std::sin(t) * std::sin(p),
110 : r * std::cos(p)
111 : };
112 : }
113 :
114 0 : inline std::vector<double> rnd::next_double(double f, double e, size_t n) {
115 0 : std::vector<double> t(n);
116 0 : for (std::size_t i=0; i < n; ++i) {
117 0 : t[i] = next_double(f, e);
118 : }
119 :
120 0 : return t;
121 : }
122 :
123 73 : inline Vector rnd::next_plmd_vector() {
124 73 : double t = next_double() * 2.0 * pi;
125 73 : double p = next_double() * pi;
126 :
127 : return Vector(
128 73 : std::sin(p) * std::cos(t),
129 73 : std::sin(t) * std::sin(p),
130 : std::cos(p)
131 219 : );
132 : }
133 :
134 : inline std::vector<double> rnd::next_std_vector() {
135 : double t = next_double() * 2.0 * pi;
136 : double p = next_double() * pi;
137 :
138 : return std::vector<double> {
139 : std::sin(p) * std::cos(t),
140 : std::sin(t) * std::sin(p),
141 : std::cos(p)
142 : };
143 : }
144 :
145 536 : inline double rnd::next_double() {
146 542 : static std::uniform_real_distribution<double> dist_double(0, 1);
147 : std::uniform_real_distribution<double>::param_type p(0, 1);
148 : dist_double.param(p);
149 :
150 1072 : return dist_double(mt_eng());
151 : }
152 :
153 : inline double rnd::next_double(double e) {
154 246 : return next_double(0, e);
155 : }
156 :
157 246 : inline double rnd::next_double(double f, double e) {
158 249 : static std::uniform_real_distribution<double> dist_double(f, e);
159 : std::uniform_real_distribution<double>::param_type p(f, e);
160 : dist_double.param(p);
161 :
162 492 : return dist_double(mt_eng());
163 : }
164 :
165 331 : inline int rnd::next_int(int e) {
166 333 : static std::uniform_int_distribution<int> dist_int(0, e-1);
167 331 : std::uniform_int_distribution<int>::param_type p(0, e-1);
168 : dist_int.param(p);
169 :
170 662 : return dist_int(mt_eng());
171 : }
172 :
173 3 : inline int rnd::next_int(int f, int e) {
174 5 : static std::uniform_int_distribution<int> dist_int(f, e-1);
175 3 : std::uniform_int_distribution<int>::param_type p(f, e-1);
176 : dist_int.param(p);
177 :
178 6 : return dist_int(mt_eng());
179 : }
180 :
181 108 : inline double rnd::next_cauchy(double m, double s) {
182 110 : static std::cauchy_distribution<double> dist_cauchy(m, s);
183 :
184 216 : return dist_cauchy(mt_eng());
185 : }
186 :
187 1231 : inline std::mt19937_64& rnd::mt_eng() {
188 1238 : static std::mt19937_64 mt{};
189 :
190 1231 : return mt;
191 : }
192 :
193 7 : inline void rnd::randomize() {
194 7 : mt_eng().seed(time(0));
195 7 : }
196 :
197 : } // namespace maze
198 : } // namespace PLMD
199 :
200 : #endif // __PLUMED_maze_Random_MT_h
|