PostGIS  3.0.6dev-r@@SVN_REVISION@@
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 
39 static unsigned char _lwrandom_seed_set = 0;
40 static 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. */
47 void
48 lwrandom_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 */
65 void
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 }
73 int32_t
74 _lwrandom_get_seed(size_t idx)
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  */
93 double
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
int value
Definition: genraster.py:62