Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
randomkit.c
Go to the documentation of this file.
1/* Random kit 1.3 */
2
3/*
4 * Copyright (c) 2003-2005, Jean-Sebastien Roy (js@jeannot.org)
5 *
6 * The rk_random and rk_seed functions algorithms and the original design of
7 * the Mersenne Twister RNG:
8 *
9 * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * 3. The names of its contributors may not be used to endorse or promote
24 * products derived from this software without specific prior written
25 * permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
31 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 *
39 * Original algorithm for the implementation of rk_interval function from
40 * Richard J. Wagner's implementation of the Mersenne Twister RNG, optimised by
41 * Magnus Jonsson.
42 *
43 * Constants used in the rk_double implementation by Isaku Wada.
44 *
45 * Permission is hereby granted, free of charge, to any person obtaining a
46 * copy of this software and associated documentation files (the
47 * "Software"), to deal in the Software without restriction, including
48 * without limitation the rights to use, copy, modify, merge, publish,
49 * distribute, sublicense, and/or sell copies of the Software, and to
50 * permit persons to whom the Software is furnished to do so, subject to
51 * the following conditions:
52 *
53 * The above copyright notice and this permission notice shall be included
54 * in all copies or substantial portions of the Software.
55 *
56 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
57 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
58 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
59 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
60 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
61 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
62 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
63 */
64
65#include <stddef.h>
66#include <stdio.h>
67#include <stdlib.h>
68#include <errno.h>
69#include <limits.h>
70#include <math.h>
71
72#include <neatogen/randomkit.h>
73
74void
75rk_seed(unsigned long seed, rk_state *state)
76{
77 int pos;
78 seed &= 0xffffffffUL;
79
80 /* Knuth's PRNG as used in the Mersenne Twister reference implementation */
81 for (pos = 0; pos < RK_STATE_LEN; pos++) {
82 state->key[pos] = seed;
83 seed = (1812433253UL * (seed ^ (seed >> 30)) + pos + 1) & 0xffffffffUL;
84 }
85 state->pos = RK_STATE_LEN;
86}
87
88/* Magic Mersenne Twister constants */
89#define N 624
90#define M 397
91#define MATRIX_A 0x9908b0dfUL
92#define UPPER_MASK 0x80000000UL
93#define LOWER_MASK 0x7fffffffUL
94
95/* Slightly optimised reference implementation of the Mersenne Twister */
96unsigned long
98{
99 unsigned long y;
100
101 if (state->pos == RK_STATE_LEN) {
102 int i;
103
104 for (i = 0; i < N - M; i++) {
105 y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
106 state->key[i] = state->key[i+M] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
107 }
108 for (; i < N - 1; i++) {
109 y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
110 state->key[i] = state->key[i+(M-N)] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
111 }
112 y = (state->key[N - 1] & UPPER_MASK) | (state->key[0] & LOWER_MASK);
113 state->key[N - 1] = state->key[M - 1] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
114
115 state->pos = 0;
116 }
117 y = state->key[state->pos++];
118
119 /* Tempering */
120 y ^= (y >> 11);
121 y ^= (y << 7) & 0x9d2c5680UL;
122 y ^= (y << 15) & 0xefc60000UL;
123 y ^= (y >> 18);
124
125 return y;
126}
127
129static unsigned long rk_ulong(rk_state *state) {
130#if ULONG_MAX <= 0xffffffffUL
131 return rk_random(state);
132#else
133 return (rk_random(state) << 32) | (rk_random(state));
134#endif
135}
136
137unsigned long
138rk_interval(unsigned long max, rk_state *state)
139{
140 unsigned long mask = max, value;
141
142 if (max == 0) {
143 return 0;
144 }
145 /* Smallest bit mask >= max */
146 mask |= mask >> 1;
147 mask |= mask >> 2;
148 mask |= mask >> 4;
149 mask |= mask >> 8;
150 mask |= mask >> 16;
151#if ULONG_MAX > 0xffffffffUL
152 mask |= mask >> 32;
153#endif
154
155 /* Search a random value in [0..mask] <= max */
156#if ULONG_MAX > 0xffffffffUL
157 if (max <= 0xffffffffUL) {
158 while ((value = (rk_random(state) & mask)) > max);
159 }
160 else {
161 while ((value = (rk_ulong(state) & mask)) > max);
162 }
163#else
164 while ((value = (rk_ulong(state) & mask)) > max);
165#endif
166 return value;
167}
static long seed
Definition exeval.c:1035
#define N
Definition randomkit.c:89
unsigned long rk_interval(unsigned long max, rk_state *state)
Definition randomkit.c:138
#define MATRIX_A
Definition randomkit.c:91
#define UPPER_MASK
Definition randomkit.c:92
#define LOWER_MASK
Definition randomkit.c:93
#define M
Definition randomkit.c:90
static unsigned long rk_ulong(rk_state *state)
returns a random unsigned long between 0 and ULONG_MAX inclusive
Definition randomkit.c:129
void rk_seed(unsigned long seed, rk_state *state)
Definition randomkit.c:75
unsigned long rk_random(rk_state *state)
Definition randomkit.c:97
#define RK_STATE_LEN
Definition randomkit.h:61
unsigned long key[RK_STATE_LEN]
Definition randomkit.h:65