1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// Copyright (c) 2020-2022 David Sorokin <davsor@mail.ru>, based in Yoshkar-Ola, Russia
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
use std::rc::Rc;
use std::cell::UnsafeCell;
use dvcompute_rand::simulation::generator::primitives::*;
/// The random number generator.
#[repr(C)]
pub struct Generator {
/// The uniform random number generator.
genu: UnsafeCell<GeneratorRepr>,
/// The normal random number generator.
genn: UnsafeCell<GeneratorRepr>,
/// The unique sequence number.
sequence_no: UnsafeCell<u64>
}
/// Specifies the generator type.
#[derive(Clone)]
pub enum GeneratorType {
/// A simple random number generator.
Simple,
/// A simple random number generator with the specified seed.
SimpleWithSeed([u8; 32])
}
impl Generator {
/// Create a new generator.
pub fn new(t: &GeneratorType) -> Generator {
match t {
&GeneratorType::Simple => {
let gen1 = uniform_generator();
let genu = UnsafeCell::new(gen1);
let gen2 = uniform_generator();
let genn = UnsafeCell::new(normal_generator(gen2));
let sequence_no = UnsafeCell::new(0);
Generator {
genu: genu,
genn: genn,
sequence_no: sequence_no
}
},
&GeneratorType::SimpleWithSeed(seed) => {
let gen0 = Rc::new(UnsafeCell::new(uniform_generator_with_seed(seed)));
let genu = {
let gen0 = gen0.clone();
let gen2 = Box::new(move || {
let gen0 = gen0.get();
unsafe { (*gen0).call() }
});
let gen2 = GeneratorRepr::into_repr(gen2);
UnsafeCell::new(gen2)
};
let genn = {
let gen0 = gen0.clone();
let gen2 = Box::new(move || {
let gen0 = gen0.get();
unsafe { (*gen0).call() }
});
let gen2 = GeneratorRepr::into_repr(gen2);
UnsafeCell::new(normal_generator(gen2))
};
let sequence_no = UnsafeCell::new(0);
Generator {
genu: genu,
genn: genn,
sequence_no: sequence_no
}
}
}
}
/// Generate an uniform random number with the specified minimum and maximum.
#[inline]
pub fn random_uniform(&self, min: f64, max: f64) -> f64 {
let gen = self.genu.get();
unsafe {
generate_uniform(&mut *gen, min, max)
}
}
/// Generate an integer uniform random number with the specified minimum and maximum.
#[inline]
pub fn random_int_uniform(&self, min: isize, max: isize) -> isize {
let gen = self.genu.get();
unsafe {
generate_int_uniform(&mut *gen, min, max)
}
}
/// Generate the triangular random number by the specified minimum, median and maximum.
#[inline]
pub fn random_triangular(&self, min: f64, median: f64, max: f64) -> f64 {
let gen = self.genu.get();
unsafe {
generate_triangular(&mut *gen, min, median, max)
}
}
/// Generate a normal random number by the specified generator, mean and deviation.
#[inline]
pub fn random_normal(&self, mu: f64, nu: f64) -> f64 {
let gen = self.genn.get();
unsafe {
generate_normal(&mut *gen, mu, nu)
}
}
/// Generate the lognormal random number derived from a normal distribution with
/// the specified generator, mean and deviation.
#[inline]
pub fn random_log_normal(&self, mu: f64, nu: f64) -> f64 {
let gen = self.genn.get();
unsafe {
generate_log_normal(&mut *gen, mu, nu)
}
}
/// Return the exponential random number with the specified mean.
#[inline]
pub fn random_exponential(&self, mu: f64) -> f64 {
let gen = self.genu.get();
unsafe {
generate_exponential(&mut *gen, mu)
}
}
/// Return the Erlang random number.
#[inline]
pub fn random_erlang(&self, scale: f64, shape: isize) -> f64 {
let gen = self.genu.get();
unsafe {
generate_erlang(&mut *gen, scale, shape)
}
}
/// Generate the Poisson random number with the specified mean.
#[inline]
pub fn random_poisson(&self, mu: f64) -> isize {
let gen = self.genu.get();
unsafe {
generate_poisson(&mut *gen, mu)
}
}
/// Generate a binomial random number with the specified probability and number of trials.
#[inline]
pub fn random_binomial(&self, prob: f64, trials: isize) -> isize {
let gen = self.genu.get();
unsafe {
generate_binomial(&mut *gen, prob, trials)
}
}
/// Generate a random number from the Gamma distribution using Marsaglia and Tsang method.
#[inline]
pub fn random_gamma(&self, kappa: f64, theta: f64) -> f64 {
let genn = self.genn.get();
let genu = self.genu.get();
unsafe {
generate_gamma(&mut *genn, &mut *genu, kappa, theta)
}
}
/// Generate a random number from the Beta distribution.
#[inline]
pub fn random_beta(&self, alpha: f64, beta: f64) -> f64 {
let genn = self.genn.get();
let genu = self.genu.get();
unsafe {
generate_beta(&mut *genn, &mut *genu, alpha, beta)
}
}
/// Generate a random number from the Weibull distribution.
#[inline]
pub fn random_weibull(&self, alpha: f64, beta: f64) -> f64 {
let gen = self.genu.get();
unsafe {
generate_weibull(&mut *gen, alpha, beta)
}
}
/// Generate a random value from the specified discrete distribution.
#[inline]
pub fn random_discrete<'a, T>(&self, dpdf: &'a [(T, f64)]) -> &'a T {
let gen = self.genu.get();
unsafe {
generate_discrete(&mut *gen, dpdf)
}
}
/// Generate a sequence number which can be considered quite unique.
#[inline]
pub fn random_sequence_no(&self) -> u64 {
let gen = self.sequence_no.get();
unsafe {
*gen = (*gen).wrapping_add(1);
*gen
}
}
}