GRASS 8 Programmer's Manual
8.5.0(2026)-8d6ceba290
Toggle main menu visibility
Loading...
Searching...
No Matches
lrand48.c
Go to the documentation of this file.
1
/*!
2
* \file lib/gis/lrand48.c
3
*
4
* \brief GIS Library - Pseudo-random number generation
5
*
6
* (C) 2014 by the GRASS Development Team
7
*
8
* This program is free software under the GNU General Public License
9
* (>=v2). Read the file COPYING that comes with GRASS for details.
10
*
11
* \author Glynn Clements
12
*/
13
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <string.h>
17
#include <errno.h>
18
19
#include <grass/gis.h>
20
#include <grass/glocale.h>
21
22
#ifdef HAVE_GETTIMEOFDAY
23
#include <sys/time.h>
24
#else
25
#include <time.h>
26
#endif
27
28
#include <sys/types.h>
29
#include <unistd.h>
30
31
typedef
unsigned
short
uint16
;
32
typedef
unsigned
int
uint32
;
33
typedef
signed
int
int32
;
34
35
static
uint16
x0, x1, x2;
36
static
const
uint32
a0 = 0xE66D;
37
static
const
uint32
a1 = 0xDEEC;
38
static
const
uint32
a2 = 0x5;
39
40
static
const
uint32
b0 = 0xB;
41
42
static
int
seeded;
43
44
#define LO(x) ((x) & 0xFFFFU)
45
#define HI(x) ((x) >> 16)
46
47
/*!
48
* \brief Seed the pseudo-random number generator
49
*
50
* \param[in] seedval 32-bit integer used to seed the PRNG
51
*/
52
void
G_srand48
(
long
seedval)
53
{
54
uint32
x
= (
uint32
) * (
unsigned
long
*)&seedval;
55
56
x2 = (
uint16
)
HI
(
x
);
57
x1 = (
uint16
)
LO
(
x
);
58
x0 = (
uint16
)0x330E;
59
seeded = 1;
60
}
61
62
/*!
63
* \brief Seed the pseudo-random number generator from the time and PID
64
*
65
* A weak hash of the current time and PID is generated and used to
66
* seed the PRNG
67
*
68
* \return generated seed value passed to G_srand48()
69
*/
70
long
G_srand48_auto
(
void
)
71
{
72
unsigned
long
seed;
73
char
*grass_random_seed = getenv(
"GRASS_RANDOM_SEED"
);
74
75
if
(!grass_random_seed)
76
grass_random_seed = getenv(
"SOURCE_DATE_EPOCH"
);
77
if
(grass_random_seed) {
78
seed = strtoull(grass_random_seed,
NULL
, 10);
79
}
80
else
{
81
seed = (
unsigned
long)getpid();
82
83
#ifdef HAVE_GETTIMEOFDAY
84
{
85
struct
timeval tv;
86
87
if
(gettimeofday(&tv,
NULL
) < 0)
88
G_fatal_error
(_(
"gettimeofday failed: %s"
), strerror(errno));
89
seed += (
unsigned
long)tv.tv_sec;
90
seed += (
unsigned
long)tv.tv_usec;
91
}
92
#else
93
{
94
time_t
t
= time(
NULL
);
95
96
seed += (
unsigned
long)
t
;
97
}
98
#endif
99
}
100
101
G_srand48
((
long
)seed);
102
return
(
long
)seed;
103
}
104
105
static
void
G__next(
void
)
106
{
107
uint32
a0x0 = a0 * x0;
108
uint32
a0x1 = a0 * x1;
109
uint32
a0x2 = a0 * x2;
110
uint32
a1x0 = a1 * x0;
111
uint32
a1x1 = a1 * x1;
112
uint32
a2x0 = a2 * x0;
113
114
uint32
y0 =
LO
(a0x0) + b0;
115
uint32
y1 =
LO
(a0x1) +
LO
(a1x0) +
HI
(a0x0);
116
uint32
y2 =
LO
(a0x2) +
LO
(a1x1) +
LO
(a2x0) +
HI
(a0x1) +
HI
(a1x0);
117
118
if
(!seeded)
119
G_fatal_error
(_(
"Pseudo-random number generator not seeded"
));
120
121
x0 = (
uint16
)
LO
(y0);
122
y1 +=
HI
(y0);
123
x1 = (
uint16
)
LO
(y1);
124
y2 +=
HI
(y1);
125
x2 = (
uint16
)
LO
(y2);
126
}
127
128
/*!
129
* \brief Generate an integer in the range [0, 2^31)
130
*
131
* \return the generated value
132
*/
133
long
G_lrand48
(
void
)
134
{
135
uint32
r
;
136
137
G__next();
138
r
= ((
uint32
)x2 << 15) | ((
uint32
)x1 >> 1);
139
return
(
long
)
r
;
140
}
141
142
/*!
143
* \brief Generate an integer in the range [-2^31, 2^31)
144
*
145
* \return the generated value
146
*/
147
long
G_mrand48
(
void
)
148
{
149
uint32
r
;
150
151
G__next();
152
r
= ((
uint32
)x2 << 16) | ((
uint32
)x1);
153
return
(
long
)(
int32
)
r
;
154
}
155
156
/*!
157
* \brief Generate a floating-point value in the range [0,1)
158
*
159
* \return the generated value
160
*/
161
double
G_drand48
(
void
)
162
{
163
double
r
= 0.0;
164
165
G__next();
166
r
+= x2;
167
r
*= 0x10000;
168
r
+= x1;
169
r
*= 0x10000;
170
r
+= x0;
171
r
/= 281474976710656.0;
/* 2^48 */
172
return
r
;
173
}
174
175
/*
176
177
Test program
178
179
int main(int argc, char **argv)
180
{
181
long s = (argc > 1) ? atol(argv[1]) : 0;
182
int i;
183
184
srand48(s);
185
G_srand48(s);
186
187
for (i = 0; i < 100; i++) {
188
printf("%.50f %.50f\n", drand48(), G_drand48());
189
printf("%lu %lu\n", lrand48(), G_lrand48());
190
printf("%ld %ld\n", mrand48(), G_mrand48());
191
}
192
193
return 0;
194
}
195
196
*/
NULL
#define NULL
Definition
ccmath.h:32
t
double t
Definition
driver/set_window.c:5
r
double r
Definition
driver/set_window.c:5
G_fatal_error
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition
gis/error.c:159
uint16
unsigned short uint16
Definition
lrand48.c:31
uint32
unsigned int uint32
Definition
lrand48.c:32
G_mrand48
long G_mrand48(void)
Generate an integer in the range [-2^31, 2^31).
Definition
lrand48.c:147
G_lrand48
long G_lrand48(void)
Generate an integer in the range [0, 2^31).
Definition
lrand48.c:133
G_srand48_auto
long G_srand48_auto(void)
Seed the pseudo-random number generator from the time and PID.
Definition
lrand48.c:70
int32
signed int int32
Definition
lrand48.c:33
HI
#define HI(x)
Definition
lrand48.c:45
G_srand48
void G_srand48(long seedval)
Seed the pseudo-random number generator.
Definition
lrand48.c:52
LO
#define LO(x)
Definition
lrand48.c:44
G_drand48
double G_drand48(void)
Generate a floating-point value in the range [0,1).
Definition
lrand48.c:161
x
#define x
gis
lrand48.c
Generated on
for GRASS 8 Programmer's Manual by
1.17.0