Cayley
Pseudo-Random Bits from Finite Groups
Main.cpp
Go to the documentation of this file.
1 
4 #ifdef _MSC_VER //Windows Visual Studio
5  #include <conio.h>
6 #endif
7 
8 #include "Includes.h"
9 #include "uintx_t.h"
10 #include "Cayley32.h"
11 
12 //function prototypes
13 
14 void init_genrand64(uint64_t seed);
15 uint64_t genrand64_int64(void);
16 uint64_t CPUTimeInNanoseconds();
17 
19 
20 enum class Task{
21  Time, Generate, GenerateEx, GenerateMT, None
22 }; //Task
23 
27 
28 void PrintHelp(){
29  printf("Cayley32: A pseudorandom number generator based on the ");
30  printf("symmetric group S_23.\n");
31  printf("Usage:\ngenerator.exe [-s seed] [-g] [-ge] [-gm] [-h]\n");
32  printf(" -s n: Seed n, a hex number (defaults to fixed value)\n");
33  printf(" -g: Generate infinite Cayley32 pseudorandom bits\n");
34  printf(" -ge: Generate infinite Cayley32e pseudorandom bits\n");
35  printf(" -gm: Generate infinite Mersenne Twister pseudorandom bits\n");
36  printf(" -h: This help.\n");
37  printf("To report run-time: ./generator.exe\n");
38  printf("To test with DieHarder: ");
39  printf("./generator.exe -s 99999 -g | dieharder -g 200 -a\n");
40 } //PrintHelp
41 
49 
50 void GetParams(int argc, char *argv[], uintx_t& seed, Task& t){
51  seed = 999999; //default seed
52  t = Task::Time; //default task
53 
54  for(int i=1; i<argc; i++){
55  std::string s0 = argv[i];
56 
57  if(s0 == "-s")
58  seed = uintx_t(argv[i + 1]);
59 
60  else if(s0 == "-g")
61  t = Task::Generate;
62 
63  else if(s0 == "-ge")
64  t = Task::GenerateEx;
65 
66  else if(s0 == "-gm")
67  t = Task::GenerateMT;
68 
69  else if(s0 == "-h"){
70  t = Task::None;
71  PrintHelp();
72  } //else if
73  } //for
74 } //GetParams
75 
84 
85 template<typename t> void Generate(const t& rnd, uint64_t nBufSize){
86  const FILE* unused = freopen(nullptr, "wb", stdout); //stdout in binary mode
87 
88  uint64_t* buffer = new uint64_t[nBufSize]; //buffer for pseudo-random numbers
89 
90  while(true){ //keep generating bufferfuls of data and throwing it to stdout
91  uint64_t* p = buffer; //output pointer, set to start of buffer
92 
93  for(uint64_t i=0; i<nBufSize; i++) //fill buffer with pseudo-random UINT64s
94  *p++ = rnd(); //generate uint64_t and append to buffer
95 
96  const size_t bytecount = nBufSize*sizeof(uint64_t); //buffer size in bytes
97  fwrite((uint8_t*)buffer, bytecount, 1, stdout); //output buffer as bytes
98  } //while
99 
100  delete [] buffer;
101 } //Generate
102 
109 
110 template<typename t> double Time(const t& rand, uint64_t n){
111  const uint64_t t0 = CPUTimeInNanoseconds(); //start CPU time
112 
113  for(uint32_t i=0; i<n; i++)
114  rand(); //generate uint64_t and throw it away
115 
116  return double(CPUTimeInNanoseconds() - t0)/double(n*sizeof(uint64_t));
117 } //Time
118 
125 
126 void Time(Cayley32* pCayley, uint64_t n){
127  const uint32_t mb = (8*n*sizeof(uint64_t))/1048576LL; //number of Mb
128 
129  printf("Timing the generation of %u Megabits ", mb);
130  printf("by Cayley32 and the Mersenne Twister.\n");
131 
132  const double t0 = Time([&](){pCayley->rand();}, n);
133  printf("Cayley32: %0.2f nanoseconds per bit\n", t0);
134 
135  const double t1 = Time([&](){genrand64_int64();}, n);
136  printf("Mersenne Twister: %0.2f nanoseconds per bit\n", t1);
137 
138  printf("Cayley32 is %0.1f times slower\n", t0/t1);
139 } //Time
140 
146 
147 int main(int argc, char *argv[]){
148  uintx_t seed = 9999999; //default seed
149  Task t = Task::Time; //default task
150 
151  GetParams(argc, argv, seed, t); //get parameters from command line args
152 
153  init_genrand64((uint64_t)seed); //seed Mersenne Twister
154 
155  Cayley32e cayley32e; //new PRNG with pseudorandom generators
156  cayley32e.srand(genrand64_int64); //seed it
157 
158  Cayley32 cayley32; //new PRNG with fixed generators
159  cayley32.srand(seed); //seed it
160 
161  //cayley32.GetGenerator(0).printnum();
162  //cayley32.GetGenerator(1).printnum();
163 
164  const uint32_t nBufSize = 10485760; //buffer size
165 
166  switch(t){ //depending on the task
167  case Task::Time:
168  Time(&cayley32, 33554432);
169 
170  #ifdef _MSC_VER //Windows Visual Studio
171  _cputs("\nHit Almost Any Key to Exit...\n");
172  _getch();
173  #endif
174  break;
175 
176  case Task::Generate: //fixed generators
177  Generate([&](){return cayley32.rand();}, nBufSize);
178  break;
179 
180  case Task::GenerateEx: //pseudo-random generators
181  Generate([&](){return cayley32e.rand();}, nBufSize);
182  break;
183 
184  case Task::GenerateMT: //Mersenne Twister for baseline
185  Generate([&](){return genrand64_int64();}, nBufSize);
186  break;
187  } //switch
188 
189  return 0;
190 } //main
The Cayley PRNG over with fixed generators.
Definition: Cayley32.h:26
void Generate(const t &rnd, uint64_t nBufSize)
Write an infinite number of pseudorandom bits to stdout.
Definition: Main.cpp:85
Useful includes.
void GetParams(int argc, char *argv[], uintx_t &seed, Task &t)
Get generator parameters from argv.
Definition: Main.cpp:50
Task
Task type.
Definition: Main.cpp:20
double Time(const t &rand, uint64_t n)
Time a PRNG.
Definition: Main.cpp:110
int main(int argc, char *argv[])
Main.
Definition: Main.cpp:147
Declaration of the extensible unsigned integer class.
void srand(uintx_t &seed)
Seed the generator.
Definition: Cayley32.cpp:78
Declaration of the Cayley32 pseudo-random number generator.
uint64_t CPUTimeInNanoseconds()
CPU time in nanoseconds.
Definition: CPUtime.cpp:48
The extensible unsigned integer class.
Definition: uintx_t.h:14
void PrintHelp()
Print help.
Definition: Main.cpp:28
virtual void srand(uint64_t(*rnd)(void))
Seed the generator.
Definition: Cayley.cpp:101
The Cayley PRNG over with pseudo-random generators.
Definition: Cayley32.h:14
uint64_t rand()
Generate 64 pseudo-random bits.
Definition: Cayley32.cpp:20