TPCCLIB
Loading...
Searching...
No Matches
mertwi.c File Reference

Mersenne Twister MT19937 pseudorandom number generator for TPCCLIB. More...

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include "libtpcmodel.h"

Go to the source code of this file.

Functions

void mertwiInit (MERTWI *mt)
 
uint32_t mertwiSeed32 (void)
 Make uint32_t seed for pseudorandom number generators.
 
uint64_t mertwiSeed64 (void)
 Make uint64_t seed for pseudorandom number generators.
 
void mertwiInitWithSeed64 (MERTWI *mt, uint64_t seed)
 Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number generator using given seed.
 
void mertwiInitByArray64 (MERTWI *mt, uint64_t init_key[], uint64_t key_length)
 Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number generator using given array.
 
uint64_t mertwiRandomInt64 (MERTWI *mt)
 Generate a random number on [0, 2^64-1]-interval using Mersenne Twister MT19937.
 
int64_t mertwiRandomInt63 (MERTWI *mt)
 Generate a random number on [0, 2^63-1]-interval using Mersenne Twister MT19937.
 
double mertwiRandomDouble1 (MERTWI *mt)
 Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1] with uniform distribution using Mersenne Twister MT19937.
 
double mertwiRandomDouble2 (MERTWI *mt)
 Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1) with uniform distribution using Mersenne Twister MT19937.
 
double mertwiRandomDouble3 (MERTWI *mt)
 Generate a 64-bit double precision floating point pseudorandom number in the range of (0,1) with uniform distribution using Mersenne Twister MT19937.
 
int mertwiRandomBetween (MERTWI *mt, unsigned int nr, double *d, double low, double up, int type)
 Fill the given double array with random numbers with uniform distribution between the specified limits.
 
double mertwiRandomExponential (MERTWI *mt, double mean)
 Generate pseudo-random number with exponential distribution and specified mean.
 
double mertwiRandomGaussian (MERTWI *mt)
 Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1] with normal (Gaussian) distribution. using Mersenne Twister MT19937.
 

Detailed Description

Mersenne Twister MT19937 pseudorandom number generator for TPCCLIB.

For more information on the method and original source codes visit https://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/emt.html

Definition in file mertwi.c.

Function Documentation

◆ mertwiInit()

void mertwiInit ( MERTWI * mt)

Prepare data struct Mersenne Twister MT19937 for usage. Do not call any mertwi* functions before calling this function!

Definition at line 23 of file mertwi.c.

25 {
26 mt->n=TPCCLIB_MERTWI_NN; // Length of mt array
27 mt->m=mt->n/2; // N/2
29 mt->um=UINT64_C(0xFFFFFFFF80000000);
30 mt->lm=UINT64_C(0x7FFFFFFF);
31 mt->mti=mt->n+1; // means that mt[] is not initialized
32}
#define TPCCLIB_MERTWI_NN
Definition libtpcmodel.h:41
#define TPCCLIB_MERTWI_A
Definition libtpcmodel.h:43
uint64_t mti
Definition libtpcmodel.h:60
unsigned int m
Definition libtpcmodel.h:50
uint64_t lm
Definition libtpcmodel.h:56
uint64_t a
Definition libtpcmodel.h:52
uint64_t um
Definition libtpcmodel.h:54
unsigned int n
Definition libtpcmodel.h:48

◆ mertwiInitByArray64()

void mertwiInitByArray64 ( MERTWI * mt,
uint64_t init_key[],
uint64_t key_length )

Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number generator using given array.

Call either this or mertwiInitWithSeed64 before generating random numbers with MT19937 using functions.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before this.
See also
mertwiSeed64, mertwiInitWithSeed64, mertwiInit
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator
init_keyThe array for initializing keys
key_lengthLength of initialization array init_key[]

Definition at line 111 of file mertwi.c.

118 {
119 unsigned int i, j;
120 uint64_t k;
121 mertwiInitWithSeed64(mt, UINT64_C(19650218));
122 i=1; j=0; if(mt->n>key_length) k=mt->n; else k=key_length;
123 for(; k; k--) {
124 mt->mt[i] =
125 (mt->mt[i] ^ ((mt->mt[i-1] ^ (mt->mt[i-1]>>62)) * UINT64_C(3935559000370003845)))
126 + init_key[j] + j;
127 i++; j++;
128 if(i>=mt->n) {mt->mt[0]=mt->mt[mt->n-1]; i=1;}
129 if(j>=key_length) j=0;
130 }
131 for(k=mt->n-1; k; k--) {
132 mt->mt[i]=
133 (mt->mt[i] ^ ((mt->mt[i-1] ^ (mt->mt[i-1] >> 62)) * UINT64_C(2862933555777941757)))
134 - i;
135 i++;
136 if(i>=mt->n) {mt->mt[0]=mt->mt[mt->n-1]; i=1;}
137 }
138 mt->mt[0] = UINT64_C(1) << 63; /* MSB is 1; assuring non-zero initial array */
139}
void mertwiInitWithSeed64(MERTWI *mt, uint64_t seed)
Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number ...
Definition mertwi.c:91
uint64_t mt[TPCCLIB_MERTWI_NN]
Definition libtpcmodel.h:58

◆ mertwiInitWithSeed64()

void mertwiInitWithSeed64 ( MERTWI * mt,
uint64_t seed )

Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number generator using given seed.

Call either this or mertwiInitByArray64 before generating random numbers with MT19937 using functions.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before this.
See also
mertwiSeed64, mertwiInitByArray64, mertwiInit
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator
seedSeed, for example from mertwiSeed64()

Definition at line 91 of file mertwi.c.

96 {
97 mt->mt[0]=seed;
98 for(mt->mti=1; mt->mti<mt->n; mt->mti++)
99 mt->mt[mt->mti]=
100 (UINT64_C(6364136223846793005)*(mt->mt[mt->mti-1] ^ (mt->mt[mt->mti-1]>>62)) + mt->mti);
101}

Referenced by mertwiInitByArray64(), and mertwiRandomInt64().

◆ mertwiRandomBetween()

int mertwiRandomBetween ( MERTWI * mt,
unsigned int nr,
double * d,
double low,
double up,
int type )

Fill the given double array with random numbers with uniform distribution between the specified limits.

Applies Mersenne Twister MT19937 pseudorandom number generator. With uniform distribution, the SD=(up-low)/sqrt(12), and CV=(up-low)/(sqrt(3)*(low+up)).

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64, mertwiRandomDouble1
Author
Vesa Oikonen
Returns
0 when successful, otherwise <> 0.
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator
nrNr of values in double array
dPointer to pre-allocated double array
lowLower limit for random values
upUpper limit for random values
typeDistribution: 0=even, 1=square-root transformation

Definition at line 275 of file mertwi.c.

288 {
289 unsigned int i;
290 double dif, v, stl, stu;
291
292 if(nr<1) return(0);
293 if(mt==NULL || d==NULL || type<0 || type>1) return(1);
294
295 dif=up-low; if(dif<0.0) return(2);
296 if(dif==0.0) {
297 for(i=0; i<nr; i++) d[i]=low;
298 return(0);
299 }
300
301 if(type==0) {
302 for(i=0; i<nr; i++) d[i] = mertwiRandomDouble1(mt)*dif + low;
303 } else if(type==1) {
304 stl=copysign(sqrt(fabs(low)),low); if(!isnormal(stl)) stl=0.0;
305 stu=copysign(sqrt(fabs(up)), up); if(!isnormal(stu)) stu=0.0;
306 dif=stu-stl;
307 for(i=0; i<nr; i++) {
308 v=mertwiRandomDouble1(mt)*dif+stl; d[i]=copysign(v*v, v);
309 }
310 }
311
312 return(0);
313}
double mertwiRandomDouble1(MERTWI *mt)
Generate a 64-bit double precision floating point pseudorandom number in the range of [0,...
Definition mertwi.c:218

◆ mertwiRandomDouble1()

double mertwiRandomDouble1 ( MERTWI * mt)

Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1] with uniform distribution using Mersenne Twister MT19937.

With uniform distribution, the SD=(up-low)/sqrt(12), and CV=(up-low)/(sqrt(3)*(low+up)).

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random double value in the range [0,1].
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 218 of file mertwi.c.

221 {
222 return(mertwiRandomInt64(mt) >> 11) * (1.0/9007199254740991.0);
223}
uint64_t mertwiRandomInt64(MERTWI *mt)
Generate a random number on [0, 2^64-1]-interval using Mersenne Twister MT19937.
Definition mertwi.c:152

Referenced by mertwiRandomBetween(), mertwiRandomExponential(), and mertwiRandomGaussian().

◆ mertwiRandomDouble2()

double mertwiRandomDouble2 ( MERTWI * mt)

Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1) with uniform distribution using Mersenne Twister MT19937.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random double value in the range [0,1).
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 235 of file mertwi.c.

238 {
239 return(mertwiRandomInt64(mt) >> 11) * (1.0/9007199254740992.0);
240}

◆ mertwiRandomDouble3()

double mertwiRandomDouble3 ( MERTWI * mt)

Generate a 64-bit double precision floating point pseudorandom number in the range of (0,1) with uniform distribution using Mersenne Twister MT19937.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random double value in the range (0,1).
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 252 of file mertwi.c.

255 {
256 return((mertwiRandomInt64(mt) >> 12) + 0.5) * (1.0/4503599627370496.0);
257}

◆ mertwiRandomExponential()

double mertwiRandomExponential ( MERTWI * mt,
double mean )

Generate pseudo-random number with exponential distribution and specified mean.

Applies Mersenne Twister MT19937 pseudorandom number generator.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64, mertwiRandomDouble1
Returns
Returns the random double value in the range [0,1] with exponential distribution.
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator
meanMean of the exponential distribution

Definition at line 329 of file mertwi.c.

334 {
335 double r;
336 do {r=mertwiRandomDouble1(mt);} while(r==0.0);
337 return(-mean*log(r));
338}
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
Definition pearson.c:341

◆ mertwiRandomGaussian()

double mertwiRandomGaussian ( MERTWI * mt)

Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1] with normal (Gaussian) distribution. using Mersenne Twister MT19937.

Applies Mersenne Twister MT19937 pseudorandom number generator, and the polar form of Box-Müller transform to produce numbers with Gaussian (normal) distribution which has a zero mean and standard deviation of one.

Box GEP, Muller ME. A note on the generation of random normal deviates. Annals of Mathematical Statistics, Volume 29, Issue 2, 1958, 610-611. Available from JSTOR https://www.jstor.org/

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64, mertwiRandomDouble1, mertwiRandomBetween
Returns
Returns the random double value in the range [0,1] with normal distribution.
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 363 of file mertwi.c.

366 {
367 static int ready=0;
368 static double dev;
369 double fac, rsq, a, b;
370
371 /* If we don't have deviate already, then we'll have to make one */
372 if(!ready) {
373 do {
374 a = 2.*mertwiRandomDouble1(mt) - 1.0;
375 b = 2.*mertwiRandomDouble1(mt) - 1.0;
376 rsq = a*a + b*b;
377 } while (rsq>1.0 || rsq==0.0);
378
379 fac = sqrt(-2.0*log(rsq)/rsq);
380 dev=a*fac; ready=1;
381 return(b*fac);
382 } else { /* dev is ready so return it */
383 ready=0;
384 return(dev);
385 }
386}

◆ mertwiRandomInt63()

int64_t mertwiRandomInt63 ( MERTWI * mt)

Generate a random number on [0, 2^63-1]-interval using Mersenne Twister MT19937.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random number with range from 0 to INT64_MAX.
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 197 of file mertwi.c.

200 {
201 return(int64_t)(mertwiRandomInt64(mt) >> 1);
202}

◆ mertwiRandomInt64()

uint64_t mertwiRandomInt64 ( MERTWI * mt)

Generate a random number on [0, 2^64-1]-interval using Mersenne Twister MT19937.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random number with range from 0 to UINT64_MAX.
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 152 of file mertwi.c.

155 {
156 unsigned int i;
157 uint64_t x;
158 static uint64_t mag01[2]={UINT64_C(0), TPCCLIB_MERTWI_A};
159
160 if(mt->mti>=mt->n) { /* generate NN words at one time */
161
162 /* if init_genrand64() has not been called, a default initial seed is used */
163 if(mt->mti==mt->n+1) mertwiInitWithSeed64(mt, UINT64_C(5489));
164
165 for(i=0; i<mt->n-mt->m; i++) {
166 x=(mt->mt[i]&mt->um)|(mt->mt[i+1]&mt->lm);
167 mt->mt[i] = mt->mt[i+mt->m] ^ (x>>1) ^ mag01[(int)(x&UINT64_C(1))];
168 }
169 for(; i<mt->n-1; i++) {
170 x = (mt->mt[i]&mt->um)|(mt->mt[i+1]&mt->lm);
171 mt->mt[i] = mt->mt[i+(mt->m-mt->n)] ^ (x>>1) ^ mag01[(int)(x&UINT64_C(1))];
172 }
173 x = (mt->mt[mt->n-1]&mt->um)|(mt->mt[0]&mt->lm);
174 mt->mt[mt->n-1] = mt->mt[mt->m-1] ^ (x>>1) ^ mag01[(int)(x&UINT64_C(1))];
175 mt->mti=0;
176 }
177 x = mt->mt[mt->mti];
178
179 x ^= (x>>29) & UINT64_C(0x5555555555555555);
180 x ^= (x<<17) & UINT64_C(0x71D67FFFEDA60000);
181 x ^= (x<<37) & UINT64_C(0xFFF7EEE000000000);
182 x ^= (x>>43);
183 mt->mti++;
184
185 return(x);
186}

Referenced by mertwiRandomDouble1(), mertwiRandomDouble2(), mertwiRandomDouble3(), and mertwiRandomInt63().

◆ mertwiSeed32()

uint32_t mertwiSeed32 ( void )

Make uint32_t seed for pseudorandom number generators.

Uses microseconds from the computer clock and process ID to reduce the chance of getting the same seed for simultaneously executing program threads and instances.

Returns
Returns the seed.
See also
mertwiSeed64

Definition at line 43 of file mertwi.c.

44{
45 uint32_t li;
46#if defined HAVE_TIMESPEC_GET
47 struct timespec ts;
48 timespec_get(&ts, TIME_UTC);
49 li=((ts.tv_sec % 10000)*523 ^ ts.tv_nsec*10) ^ ((getpid() % 1000)*983);
50#elif defined HAVE_CLOCK_GETTIME
51 struct timespec ts;
52 clock_gettime(CLOCK_REALTIME, &ts);
53 li=((ts.tv_sec % 10000)*523 ^ ts.tv_nsec*10) ^ ((getpid() % 1000)*983);
54#elif defined HAVE_GETTIMEOFDAY
55 struct timeval tv;
56 gettimeofday(&tv, 0);
57 li=((tv.tv_sec % 10000)*523 ^ tv.tv_usec*13) ^ ((getpid() % 1000)*983);
58#else
59 li=(unsigned int)time(NULL)+(unsigned int)getpid();
60#endif
61 li+=(uint32_t)rand();
62 return(li);
63}

Referenced by mertwiSeed64().

◆ mertwiSeed64()

uint64_t mertwiSeed64 ( void )

Make uint64_t seed for pseudorandom number generators.

Uses microseconds from the computer clock and process ID to reduce the chance of getting the same seed for simultaneously executing program threads and instances.

Returns
Returns the seed.
See also
mertwiSeed32

Definition at line 72 of file mertwi.c.

73{
74 uint32_t li;
75 uint64_t lli;
76 lli=li=mertwiSeed32();
77 lli=li; lli<<=32; lli+=li;
78 return(lli);
79}
uint32_t mertwiSeed32(void)
Make uint32_t seed for pseudorandom number generators.
Definition mertwi.c:43