PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwrandom.c
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * PostGIS - Spatial Types for PostgreSQL
4 * http://postgis.net
5 *
6 * PostGIS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * PostGIS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **********************************************************************
20 *
21 * Copyright 2019 Mike Taves
22 *
23 **********************************************************************/
24
25#include "lwrandom.h"
26
27#include <stdlib.h>
28#include <stdint.h>
29#include <stddef.h>
30#include <time.h>
31
32#ifdef _WIN32
33#include <process.h>
34#define getpid _getpid
35#else
36#include <unistd.h>
37#endif
38
39static unsigned char _lwrandom_seed_set = 0;
40static int32_t _lwrandom_seed[3] = {0x330e, 0xabcd, 0x1234};
41
42/*
43 * Set seed for a random number generator.
44 * Repeatable numbers are generated with seed values >= 1.
45 * When seed is zero and has not previously been set, it is based on
46 * Unix time (seconds) and process ID. */
47void
48lwrandom_set_seed(int32_t seed)
49{
50 if (seed == 0)
51 {
52 if (_lwrandom_seed_set == 0)
53 seed = (unsigned int)time(NULL) + (unsigned int)getpid() - 0xbadd;
54 else
55 return;
56 }
57 /* s1 value between 1 and 2147483562 */
58 _lwrandom_seed[1] = (((int64_t)seed + 0xfeed) % 2147483562) + 1;
59 /* s2 value between 1 and 2147483398 */
60 _lwrandom_seed[2] = ((((int64_t)seed + 0xdefeb) << 5) % 2147483398) + 1;
62}
63
64/* for low-level external debugging */
65void
66_lwrandom_set_seeds(int32_t s1, int32_t s2)
67{
68 /* _lwrandom_seed[0] not used */
69 _lwrandom_seed[1] = s1;
70 _lwrandom_seed[2] = s2;
72}
73int32_t
75{
76 return _lwrandom_seed[idx];
77}
78
79/*
80 * Generate a random floating-point value.
81 * Values are uniformly distributed between 0 and 1.
82 *
83 * Authors:
84 * Pierre L'Ecuyer (1988), see source code in Figure 3.
85 * C version by John Burkardt, modified by Mike Taves.
86 *
87 * Reference:
88 * Pierre L'Ecuyer,
89 * Efficient and Portable Combined Random Number Generators,
90 * Communications of the ACM, Volume 31, Number 6, June 1988,
91 * pages 742-751. doi:10.1145/62959.62969
92 */
93double
95{
96 double value;
97 int32_t k;
98 int32_t z;
99 int32_t *s1 = &_lwrandom_seed[1];
100 int32_t *s2 = &_lwrandom_seed[2];
101
102 k = *s1 / 53668;
103 *s1 = 40014 * (*s1 - k * 53668) - k * 12211;
104 if (*s1 < 0)
105 *s1 += 2147483563;
106
107 k = *s2 / 52774;
108 *s2 = 40692 * (*s2 - k * 52774) - k * 3791;
109 if (*s2 < 0)
110 *s2 += 2147483399;
111
112 z = *s1 - *s2;
113 if (z < 1)
114 z += 2147483562;
115
116 value = (double)(z) / 2147483563.0;
117
118 return value;
119}
void _lwrandom_set_seeds(int32_t s1, int32_t s2)
Definition lwrandom.c:66
static int32_t _lwrandom_seed[3]
Definition lwrandom.c:40
void lwrandom_set_seed(int32_t seed)
Definition lwrandom.c:48
int32_t _lwrandom_get_seed(size_t idx)
Definition lwrandom.c:74
static unsigned char _lwrandom_seed_set
Definition lwrandom.c:39
double lwrandom_uniform(void)
Definition lwrandom.c:94