-
Notifications
You must be signed in to change notification settings - Fork 2
/
random.cxx
135 lines (108 loc) · 2.84 KB
/
random.cxx
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
// random.cpp A collection of Random number generators
// (c) Copyright 1995, Everett F. Carter Jr.
// Permission is granted by the author to use
// this software for any application provided this
// copyright notice is preserved.
// Updated to 2003 C++ standard by Shawn Waldon in 2014
static const char rcsid[] = "@(#)random.c++ 1.10 11:34:07 6/9/95 EFC";
#include <cmath>
#include <ctime>
#include <random.hpp>
#include <errorstream.hpp>
RUniform::RUniform()
{
seed(time(NULL));
}
/* uniform [a, b] random variate generator */
Real RUniform::number(const Real a, const Real b)
{
if (a > b && ostr) {
ErrorStream error("RUniform::number", *ostr);
error.fatal() << "Argument Error: a (" << a << ") > b (" << b << ')'
<< std::endl;
}
return (a + (b - a) * ranf());
}
IUniform::IUniform()
{
seed(time(NULL));
}
/* random integer generator, uniform */
int IUniform::number(const int i, const int n)
{ /* return an integer in i, i+1, ... n */
if (i > n && ostr) {
ErrorStream error("IUniform::number", *ostr);
error.fatal() << "Argument Error: i (" << i << "> n (" << n << ')' << std::endl;
}
return (int)(i + (rani() % (n - i + 1)));
}
Expntl::Expntl()
{
seed(time(NULL));
}
/* negative exponential random variate generator */
Real Expntl::number(const Real x) { return (-x * log(ranf())); }
Erlang::Erlang()
{
seed(time(NULL));
}
/* erlang random variate generator */
Real Erlang::number(const Real x, const Real s)
{
int i, k;
Real z;
if (s > x && ostr) {
ErrorStream error("Erlang::number", *ostr);
error.fatal() << "Argument Error: s (" << s << " > x (" << x << ')' << std::endl;
}
z = x / s;
k = (int)(z * z);
for (i = 0, z = 1.0; i < k; i++) z *= ranf();
return (-(x / k) * log(z));
}
Hyperx::Hyperx()
{
seed(time(NULL));
}
/* hyperexponential random variate generator */
Real Hyperx::number(const Real x, const Real s)
{
Real cv, z, p;
if (s <= x && ostr) {
ErrorStream error("Hyperx::number", *ostr);
error.fatal() << "Argument Error: s (" << s << " not > x (" << x << ')'
<< std::endl;
}
cv = s / x;
z = cv * cv;
p = 0.5 * (1.0 - sqrt((z - 1.0) / (z + 1.0)));
z = (ranf() > p) ? (x / (1.0 - p)) : (x / p);
return (-0.5 * z * log(ranf()));
}
Normal::Normal()
: z2(0.0),
use_z2(1)
{
seed(time(NULL));
}
/* normal random variate generator */
Real Normal::number(const Real x,
const Real s) /* mean x, standard deviation s */
{
Real v1, v2, w, z1;
if (use_z2 && z2 != 0.0) /* use value from previous call */
{
z1 = z2;
z2 = 0.0;
} else {
do {
v1 = 2.0 * ranf() - 1.0;
v2 = 2.0 * ranf() - 1.0;
w = v1 * v1 + v2 * v2;
} while (w >= 1.0);
w = sqrt((-2.0 * log(w)) / w);
z1 = v1 * w;
z2 = v2 * w;
}
return (x + z1 * s);
}