ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
random.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_MATH_RANDOM_HPP
2#define VIENNASHE_MATH_RANDOM_HPP
3
4/* ============================================================================
5 Copyright (c) 2011-2022, Institute for Microelectronics,
6 Institute for Analysis and Scientific Computing,
7 TU Wien.
8
9 -----------------
10 ViennaSHE - The Vienna Spherical Harmonics Expansion Boltzmann Solver
11 -----------------
12
13 http://viennashe.sourceforge.net/
14
15 License: MIT (X11), see file LICENSE in the base directory
16=============================================================================== */
17
18// std
19#include <cmath>
20#include <stdio.h>
21#include <stdint.h>
22
23// viennashe
24#include "viennashe/forwards.h"
25#include "viennashe/log/log.hpp"
26
27
32namespace viennashe
33{
34 namespace math
35 {
36
38 template< typename ValueT = double>
40 {
41 public:
43
48 virtual ValueT operator()() = 0;
49 };
50
52 template< typename ValueT = double>
54 {
55 public:
60 void seed(unsigned int s) { std::srand(s); }
61
66 ValueT operator()() { return static_cast<ValueT>(std::rand()*(1.0/RAND_MAX)); }
67 };
68
75 template< typename ValueT = double>
77 {
78 public:
82 merseinne_twister_generator() : index_(N_ + 1), seed_(5489UL) { this->init(); }
83
85 merseinne_twister_generator(unsigned int seed) : index_(N_ + 1), seed_(seed) { this->init(); }
86
91 void seed(unsigned int s) { seed_ = s; }
92
96 ValueT operator()()
97 {
98 const uint32_t HI_ = 0x80000000;
99 const uint32_t LO_ = 0x7fffffff;
100 const uint32_t A_[2] = { 0, 0x9908b0df };
101
102 uint32_t value = 0;
103
104 // Init if not done yet
105 if (index_ == N_+1) this->init();
106
107 // Next state
108 if (index_ >= N_)
109 {
110 uint32_t h = 0;
111 uint32_t i = 0;
112
113 for (i = 0; i < N_-M_; ++i)
114 {
115 h = (y_[i] & HI_) | (y_[i+1] & LO_);
116 y_[i] = y_[i+M_] ^ (h >> 1) ^ A_[h & 1];
117 }
118 for ( ; i < N_-1; ++i)
119 {
120 h = (y_[i] & HI_) | (y_[i+1] & LO_);
121 y_[i] = y_[i+(M_-N_)] ^ (h >> 1) ^ A_[h & 1];
122 }
123
124 h = (y_[N_-1] & HI_) | (y_[0] & LO_);
125 y_[N_-1] = y_[M_-1] ^ (h >> 1) ^ A_[h & 1];
126 index_ = 0;
127 }
128 value = y_[index_++];
129
130 // Tempering
131 value ^= (value >> 11);
132 value ^= (value << 7) & 0x9d2c5680;
133 value ^= (value << 15) & 0xefc60000;
134 value ^= (value >> 18);
135
136 return (static_cast<ValueT>(value)) * (1.0/4294967296.0) /* * 1/2^32 */;
137 }
138
139 private:
140
142 void init()
143 {
144 y_[0] = seed_; // set seed
145 for (uint32_t i = 1; i < N_; ++i)
146 y_[i] = (1812433253UL * (y_[i-1] ^ (y_[i-1] >> 30)) + i);
147 }
148
149 static const uint32_t N_ = 624;
150 static const uint32_t M_ = 397;
151
152 uint32_t index_;
153 uint32_t seed_;
154 uint32_t y_[N_];
155 };
156
157
159 template <typename ResultT = int>
161 {
162 public:
163
171 template<typename RandGeneratorType >
172 ResultT operator()(RandGeneratorType & gen, ResultT from, ResultT to)
173 {
174 return static_cast<ResultT>(gen() * (to - from) + from);
175 }
176
177 }; // uniform_distribution
178
179
181 template <typename RealT = double, typename ResultT = int>
183 {
184 private:
185 RealT mean_; // The mean of the distribution
186 RealT exp_mean_; // Equals std::exp(- mean_); Used for caching
187 public:
188
189 poisson_distribution(RealT const & mean_value)
190 : mean_(mean_value)
191 {
192 this->exp_mean_ = std::exp(- this->mean_);
193 }
194
195 RealT mean() const { return this->mean_; }
196
202 template <typename RandGeneratorType>
203 ResultT operator()(RandGeneratorType & gen)
204 {
205 RealT product = RealT(0);
206 for(ResultT m = 0; ; ++m)
207 {
208 product += std::log(gen());
209 if(product <= -this->mean_)
210 return m;
211 }
212 }
213
214 }; // poisson_distribution
215
216
217 /*
218 * @brief Pseudo-random number generator for normally distributed random numbers
219 * Using the Box-Muller transform
220 * Algorithm from: Numerical Recipes, The Art of Scientific Computing, Third Edition, Page 364/365
221 */
222 template <typename RealT = double, typename ResultT = double>
224 {
225 private:
226 RealT mean_; // The mean value
227 RealT sigma_; // The standard deviation
228 RealT storedvalue_; // For internal caching
229
230 public:
232 RealT const & sigma)
233 : mean_(mean), sigma_(sigma), storedvalue_(0.0) { }
234
235 RealT mean() const { return this->mean_; }
236 RealT sigma() const { return this->sigma_; }
237
243 template<typename RandGeneratorType>
244 ResultT operator()(RandGeneratorType &gen)
245 {
246 double v1, v2, rsq, fac;
247 if (storedvalue_ == 0.0) // We don't have an extra deviate handy, so ...
248 {
249 do
250 {
251 v1 = 2 * gen() - 1.0; // pick two uniform numbers in the square extending
252 v2 = 2 * gen() - 1.0; // from -1 to +1 in each direction
253 rsq = v1*v1 + v2*v2; // see if they are in the unit circle,
254 } while (rsq >= 1.0 || rsq == 0.0); // or try again.
255 fac = std::sqrt(-2.0 * std::log(rsq) / rsq);// Now make the Box-Muller transformation to
256 storedvalue_ = v1 * fac; // get two normal deviates. Return one and
257 return this->mean_ + this->sigma_*v2*fac; // safe the other for next time.
258 }
259 else // We have an extra deviate handy ...
260 {
261 fac = storedvalue_;
262 storedvalue_ = 0.0; // reset
263 return this->mean_ + this->sigma_*fac; // ... so return it.
264 }
265 }
266
267 }; // normal_distribution
268
269
270
271 } // namespace math
272
273} // namespace viennashe
274
275#endif /* VIENNASHE_MATH_RANDOM_HPP */
276
A pseudo-random number generator implementation using the merseinne twister MT 19937 cf....
Definition: random.hpp:77
ValueT operator()()
Returns a pseudo-random number using MT19937. Not const, since the internal state is being changed!
Definition: random.hpp:96
merseinne_twister_generator()
Default CTOR to ensure default constructability.
Definition: random.hpp:82
merseinne_twister_generator(unsigned int seed)
CTOR, which accepts the seed to the generator.
Definition: random.hpp:85
void seed(unsigned int s)
Sets the seed of the pseudo-random number generator.
Definition: random.hpp:91
normal_distribution(RealT const &mean, RealT const &sigma)
Definition: random.hpp:231
ResultT operator()(RandGeneratorType &gen)
Returns a Gaussian distributed random number; Algorithm: Box-Muller.
Definition: random.hpp:244
A poisson (exponential) distribution of random numbers.
Definition: random.hpp:183
ResultT operator()(RandGeneratorType &gen)
Returns a poisson distributed random number.
Definition: random.hpp:203
poisson_distribution(RealT const &mean_value)
Definition: random.hpp:189
The basic interface for pseudo-random number generators.
Definition: random.hpp:40
virtual ValueT operator()()=0
The basic random number generator interface (virtual abstract)
A pseudo-random number generator implementation based on std::rand()
Definition: random.hpp:54
ValueT operator()()
Calls std::rand divides by RAND_MAX and casts to ValueT.
Definition: random.hpp:66
void seed(unsigned int s)
Sets the seed of the pseudo-random number generator (std::srand)
Definition: random.hpp:60
A uniform distribution of random numbers.
Definition: random.hpp:161
ResultT operator()(RandGeneratorType &gen, ResultT from, ResultT to)
Returns a uniformly distributed pseudo-random number.
Definition: random.hpp:172
Contains forward declarations and definition of small classes that must be defined at an early stage.
A logging facility providing fine-grained control over logging in ViennaSHE.
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40