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