Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/rasqal/libmtwist/mt.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: c; c-basic-offset: 2 -*-
2
 *
3
 * mt.c - Mersenne Twister functions
4
 *
5
 * This is free and unencumbered software released into the public domain.
6
 *
7
 * Anyone is free to copy, modify, publish, use, compile, sell, or
8
 * distribute this software, either in source code form or as a compiled
9
 * binary, for any purpose, commercial or non-commercial, and by any
10
 * means.
11
 *
12
 * In jurisdictions that recognize copyright laws, the author or authors
13
 * of this software dedicate any and all copyright interest in the
14
 * software to the public domain. We make this dedication for the benefit
15
 * of the public at large and to the detriment of our heirs and
16
 * successors. We intend this dedication to be an overt act of
17
 * relinquishment in perpetuity of all present and future rights to this
18
 * software under copyright law.
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26
 * OTHER DEALINGS IN THE SOFTWARE.
27
 *
28
 * For more information, please refer to <http://unlicense.org/>
29
 * 
30
 */
31
32
33
#ifdef MTWIST_CONFIG
34
#include <mtwist_config.h>
35
#endif
36
37
#include <stdio.h>
38
39
#ifdef HAVE_STDLIB_H
40
#include <stdlib.h>
41
#endif
42
43
#ifdef HAVE_STDINT_H
44
/* To get UINT32_C */
45
#define __STDC_CONSTANT_MACROS 1
46
#include <stdint.h>
47
#else
48
/* pessimistic - use an unsigned long */
49
typedef unsigned long uint32_t;
50
#define UINT32_C(v) (v ## UL)
51
#endif
52
53
54
#include <mtwist.h>
55
56
#include <mtwist_internal.h>
57
58
/*
59
 * Mersenne Twister (MT19937) algorithm
60
 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
61
 *
62
 * http://en.wikipedia.org/wiki/Mersenne_twister
63
 *
64
 */
65
66
0
#define MTWIST_UPPER_MASK    UINT32_C(0x80000000)
67
0
#define MTWIST_LOWER_MASK    UINT32_C(0x7FFFFFFF)
68
0
#define MTWIST_FULL_MASK     UINT32_C(0xFFFFFFFF)
69
70
0
#define MTWIST_MATRIX_A      UINT32_C(0x9908B0DF)
71
72
0
#define MTWIST_MIXBITS(u, v) ( ( (u) & MTWIST_UPPER_MASK) | ( (v) & MTWIST_LOWER_MASK) )
73
0
#define MTWIST_TWIST(u, v)  ( (MTWIST_MIXBITS(u, v) >> 1) ^ ( (v) & UINT32_C(1) ? MTWIST_MATRIX_A : UINT32_C(0)) )
74
75
76
/**
77
 * mtwist_new:
78
 *
79
 * Construct a Mersenne Twister object
80
 *
81
 * Return value: new MT object or NULL on failure
82
 */
83
mtwist*
84
mtwist_new(void)
85
0
{
86
0
  mtwist* mt;
87
  
88
0
  mt = (mtwist*)calloc(1, sizeof(*mt));
89
0
  if(!mt)
90
0
    return NULL;
91
  
92
0
  mt->remaining = 0;
93
0
  mt->next = NULL;
94
0
  mt->seeded = 0;
95
96
0
  return mt;
97
0
}
98
99
100
/**
101
 * mtwist_free:
102
 * @mt: mt object
103
 *
104
 * Destroy a Mersenne Twister object
105
 */
106
void
107
mtwist_free(mtwist* mt) 
108
0
{
109
0
  if(mt)
110
0
    free(mt);
111
0
}
112
113
114
/**
115
 * mtwist_init:
116
 * @mt: mt object
117
 * @seed: seed (lower 32 bits used)
118
 *
119
 * Initialise a Mersenne Twister with an unsigned 32 bit int seed
120
 */
121
void
122
mtwist_init(mtwist* mt, unsigned long seed)
123
0
{
124
0
  int i;
125
126
0
  if(!mt)
127
0
    return;
128
  
129
0
  mt->state[0] = (uint32_t)(seed & MTWIST_FULL_MASK);
130
0
  for(i = 1; i < MTWIST_N; i++) {
131
0
    mt->state[i] = (UINT32_C(1812433253) * (mt->state[i - 1] ^ (mt->state[i - 1] >> 30)) + i); 
132
0
    mt->state[i] &= MTWIST_FULL_MASK;
133
0
  }
134
135
0
  mt->remaining = 0;
136
0
  mt->next = NULL;
137
138
0
  mt->seeded = 1;
139
0
}
140
141
142
static void
143
mtwist_update_state(mtwist* mt)
144
0
{
145
0
  int count;
146
0
  uint32_t *p = mt->state;
147
148
0
  for(count = (MTWIST_N - MTWIST_M + 1); --count; p++)
149
0
    *p = p[MTWIST_M] ^ MTWIST_TWIST(p[0], p[1]);
150
151
0
  for(count = MTWIST_M; --count; p++)
152
0
    *p = p[MTWIST_M - MTWIST_N] ^ MTWIST_TWIST(p[0], p[1]);
153
154
0
  *p = p[MTWIST_M - MTWIST_N] ^ MTWIST_TWIST(p[0], mt->state[0]);
155
156
0
  mt->remaining = MTWIST_N;
157
0
  mt->next = mt->state;
158
0
}
159
160
161
/**
162
 * mtwist_u32rand:
163
 * @mt: mt object
164
 *
165
 * Get a random unsigned 32 bit integer from the random number generator
166
 *
167
 * Return value: unsigned long with 32 valid bits
168
 */
169
unsigned long
170
mtwist_u32rand(mtwist* mt)
171
0
{
172
0
  uint32_t r;
173
174
0
  if(!mt)
175
0
    return 0UL;
176
177
0
  if(!mt->seeded)
178
0
    mtwist_init(mt, mtwist_seed_from_system(mt));
179
180
0
  if(!mt->remaining)
181
0
    mtwist_update_state(mt);
182
  
183
0
  r = *mt->next++;
184
0
  mt->remaining--;
185
186
  /* Tempering */
187
0
  r ^= (r >> 11);
188
0
  r ^= (r << 7) & UINT32_C(0x9D2C5680);
189
0
  r ^= (r << 15) & UINT32_C(0xEFC60000);
190
0
  r ^= (r >> 18);
191
192
0
  r &= MTWIST_FULL_MASK;
193
194
0
  return (unsigned long)r;
195
0
}
196
197
198
/**
199
 * mtwist_drand:
200
 * @mt: mt object
201
 *
202
 * Get a random double from the random number generator
203
 *
204
 * Return value: random double in the range 0.0 inclusive to 1.0 exclusive; [0.0, 1.0) */
205
double
206
mtwist_drand(mtwist* mt)
207
0
{
208
0
  unsigned long r;
209
0
  double d;
210
211
0
  if(!mt)
212
0
    return 0.0;
213
214
0
  r = mtwist_u32rand(mt);
215
216
0
  d = r / 4294967296.0; /* 2^32 */
217
218
0
  return d;
219
0
}