Graphviz 12.0.1~dev.20240716.0800
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
74#ifndef RK_DEV_URANDOM
75#define RK_DEV_URANDOM "/dev/urandom"
76#endif
77
78#ifndef RK_DEV_RANDOM
79#define RK_DEV_RANDOM "/dev/random"
80#endif
81
82void
83rk_seed(unsigned long seed, rk_state *state)
84{
85 int pos;
86 seed &= 0xffffffffUL;
87
88 /* Knuth's PRNG as used in the Mersenne Twister reference implementation */
89 for (pos = 0; pos < RK_STATE_LEN; pos++) {
90 state->key[pos] = seed;
91 seed = (1812433253UL * (seed ^ (seed >> 30)) + pos + 1) & 0xffffffffUL;
92 }
93 state->pos = RK_STATE_LEN;
94}
95
96/* Magic Mersenne Twister constants */
97#define N 624
98#define M 397
99#define MATRIX_A 0x9908b0dfUL
100#define UPPER_MASK 0x80000000UL
101#define LOWER_MASK 0x7fffffffUL
102
103/* Slightly optimised reference implementation of the Mersenne Twister */
104unsigned long
106{
107 unsigned long y;
108
109 if (state->pos == RK_STATE_LEN) {
110 int i;
111
112 for (i = 0; i < N - M; i++) {
113 y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
114 state->key[i] = state->key[i+M] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
115 }
116 for (; i < N - 1; i++) {
117 y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
118 state->key[i] = state->key[i+(M-N)] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
119 }
120 y = (state->key[N - 1] & UPPER_MASK) | (state->key[0] & LOWER_MASK);
121 state->key[N - 1] = state->key[M - 1] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
122
123 state->pos = 0;
124 }
125 y = state->key[state->pos++];
126
127 /* Tempering */
128 y ^= (y >> 11);
129 y ^= (y << 7) & 0x9d2c5680UL;
130 y ^= (y << 15) & 0xefc60000UL;
131 y ^= (y >> 18);
132
133 return y;
134}
135
136unsigned long
138{
139#if ULONG_MAX <= 0xffffffffUL
140 return rk_random(state);
141#else
142 return (rk_random(state) << 32) | (rk_random(state));
143#endif
144}
145
146unsigned long
147rk_interval(unsigned long max, rk_state *state)
148{
149 unsigned long mask = max, value;
150
151 if (max == 0) {
152 return 0;
153 }
154 /* Smallest bit mask >= max */
155 mask |= mask >> 1;
156 mask |= mask >> 2;
157 mask |= mask >> 4;
158 mask |= mask >> 8;
159 mask |= mask >> 16;
160#if ULONG_MAX > 0xffffffffUL
161 mask |= mask >> 32;
162#endif
163
164 /* Search a random value in [0..mask] <= max */
165#if ULONG_MAX > 0xffffffffUL
166 if (max <= 0xffffffffUL) {
167 while ((value = (rk_random(state) & mask)) > max);
168 }
169 else {
170 while ((value = (rk_ulong(state) & mask)) > max);
171 }
172#else
173 while ((value = (rk_ulong(state) & mask)) > max);
174#endif
175 return value;
176}
static long seed
Definition exeval.c:1035
static lexstate_t state
Definition htmllex.c:61
#define N
Definition randomkit.c:97
unsigned long rk_interval(unsigned long max, rk_state *state)
Definition randomkit.c:147
#define MATRIX_A
Definition randomkit.c:99
#define UPPER_MASK
Definition randomkit.c:100
#define LOWER_MASK
Definition randomkit.c:101
#define M
Definition randomkit.c:98
unsigned long rk_ulong(rk_state *state)
Definition randomkit.c:137
void rk_seed(unsigned long seed, rk_state *state)
Definition randomkit.c:83
unsigned long rk_random(rk_state *state)
Definition randomkit.c:105
#define RK_STATE_LEN
Definition randomkit.h:61