source: cpp/common/random.h @ 109

Last change on this file since 109 was 109, checked in by sz, 10 years ago

source reorganization (see README)
new feature added: part/joint shapes (see frams/_demos/part_shapes.cpp)

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