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