source: cpp/common/random.h @ 122

Last change on this file since 122 was 122, checked in by sz, 6 years ago

(c)opyright information added

  • Property svn:eol-style set to native
File size: 2.4 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "nonstd.h" //LONGLONG
6#include <time.h> //time()
7#ifdef MULTITHREADED
8#include "threads.h"
9#endif
10#ifdef LINUX
11#include <unistd.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#endif
15
16//adapted from
17//http://en.wikipedia.org/wiki/Mersenne_twister#Pseudocode
18//http://my.opera.com/metrallik/blog/2013/04/19/c-class-for-random-generation-with-mersenne-twister-method
19
20class RandomGenerator
21{
22private:
23        static const unsigned int length=624;
24        static const unsigned int bitMask_32=0xffffffff;
25        static const unsigned int bitPow_31=1<<31;
26        static const unsigned int MAXVALUE=0xffffffff;
27        unsigned int counter; //only used in randomize(). uninitialized is OK
28#ifdef MULTITHREADED
29        pthread_mutex_t lock;
30#endif
31        unsigned int *mt;
32        unsigned int idx;
33public:
34
35        RandomGenerator(unsigned int seed)
36        {
37#ifdef MULTITHREADED
38                pthread_mutex_init(&lock,NULL);
39#endif
40                mt=new unsigned int[length];
41                setSeed(seed);
42        }
43
44        inline void setSeed(unsigned int seed)
45        {
46#ifdef MULTITHREADED
47                pthread_mutex_lock(&lock);
48#endif
49                idx=0;
50                mt[0]=seed;
51                for(unsigned int i=1;i<length;i++)
52                        mt[i]=(1812433253*(mt[i-1]^(mt[i-1]>>30))+i)&bitMask_32;
53#ifdef MULTITHREADED
54                pthread_mutex_unlock(&lock);
55#endif
56        }
57
58        inline unsigned int randomize()
59        {
60                unsigned int seed;
61#ifdef LINUX
62                int fd=open("/dev/urandom",O_RDONLY);
63                if (fd>=0)
64                {
65                        read(fd,&seed,sizeof(seed));
66                        close(fd);
67                }
68                else
69#endif
70                {
71                        counter++;
72                        seed=time(NULL);              //time (seconds)
73                        seed^=counter;                //incremented value, possibly randomly initialized
74                        seed^=(unsigned int)&counter; //memory address
75                }
76                setSeed(seed);
77                return seed;
78        }
79
80        inline unsigned int getUint32()
81        {
82#ifdef MULTITHREADED
83                pthread_mutex_lock(&lock);
84#endif
85                if (idx==0) gen();
86                unsigned int y=mt[idx];
87                idx=(idx+1)%length;
88#ifdef MULTITHREADED
89                pthread_mutex_unlock(&lock);
90#endif
91                y^= y>>11;
92                y^=(y<< 7)&2636928640U;
93                y^=(y<<15)&4022730752U;
94                y^= y>>18;
95                return y;
96        }
97
98        inline double getDouble() // [0,1)
99        {
100                return double(getUint32())/((LONGLONG)(MAXVALUE)+1);
101        }
102
103        inline void gen()
104        {
105                for(unsigned int i=0;i<length;i++)
106                {
107                        unsigned int y=(mt[i]&bitPow_31)+(mt[(i+1)%length]&(bitPow_31-1));
108                        mt[i]=mt[(i+397)%length]^(y>>1);
109                        if(y%2) mt[i]^=2567483615U;
110                }
111                return;
112        }
113
114        ~RandomGenerator()
115        {
116                delete[] mt;
117        }
118};
119
Note: See TracBrowser for help on using the repository browser.