README: explain further musl-specific tweaks
[rofl0r-df-libgraphics.git] / g_src / random.cpp
blob54cac454faf84a7c7681bfdbd289fdb6448378ff
1 #include "platform.h"
2 #include <string.h>
3 #include <math.h>
4 #include <iosfwd>
5 #include <iostream>
6 #include <ios>
7 #include <streambuf>
8 #include <istream>
9 #include <ostream>
10 #include <iomanip>
11 #include <sstream>
12 #include <cstdlib>
13 #include <fstream>
14 #include <zlib.h>
16 #include "svector.h"
17 using std::string;
19 #include "endian.h"
21 #include "files.h"
23 #include "enabler.h"
25 #include "textlines.h"
27 #include "basics.h"
29 #include "random.h"
31 extern int32_t basic_seed;
32 extern int mt_index[MT_BUFFER_NUM];
33 extern short mt_cur_buffer;
34 extern short mt_virtual_buffer;
35 extern uint32_t mt_buffer[MT_BUFFER_NUM][MT_LEN];
37 //public domain RNG stuff by Michael Brundage
38 //with some modifications by me to handle more buffers
40 void mt_init()
42 mt_cur_buffer=0;
43 mt_virtual_buffer=0;
45 mt_buffer[0][0]=GetTickCount();
46 int i;
47 for(i=1;i<MT_LEN;i++)
49 //2010: better init line from wikipedia, ultimate source unknown
50 mt_buffer[0][i]=1812433253UL * (mt_buffer[0][i-1] ^ (mt_buffer[0][i-1]>>30)) + i;
52 mt_index[0]=MT_LEN*sizeof(uint32_t);
54 int32_t j;
55 for(j=0;j<20;j++)trandom_twist();
58 #define MT_IA 397
59 #define MT_IB (MT_LEN - MT_IA)
60 #define UPPER_MASK 0x80000000
61 #define LOWER_MASK 0x7FFFFFFF
62 #define MATRIX_A 0x9908B0DF
63 #define TWIST(b,i,j) ((b)[i] & UPPER_MASK) | ((b)[j] & LOWER_MASK)
64 #define MAGIC(s) (((s)&1)*MATRIX_A)
66 uint32_t mt_trandom()
68 uint32_t * b = mt_buffer[mt_cur_buffer];
69 int idx = mt_index[mt_cur_buffer];
70 uint32_t s;
71 int i;
73 if (idx == MT_LEN*sizeof(uint32_t))
75 idx = 0;
76 i = 0;
77 for (; i < MT_IB; i++) {
78 s = TWIST(b, i, i+1);
79 b[i] = b[i + MT_IA] ^ (s >> 1) ^ MAGIC(s);
81 for (; i < MT_LEN-1; i++) {
82 s = TWIST(b, i, i+1);
83 b[i] = b[i - MT_IB] ^ (s >> 1) ^ MAGIC(s);
86 s = TWIST(b, MT_LEN-1, 0);
87 b[MT_LEN-1] = b[MT_IA-1] ^ (s >> 1) ^ MAGIC(s);
89 mt_index[mt_cur_buffer] = idx + sizeof(uint32_t);
90 return *(uint32_t *)((unsigned char *)b + idx);
93 void trandom_twist()
95 uint32_t * b = mt_buffer[mt_cur_buffer];
96 uint32_t s;
97 int i;
99 i = 0;
100 for (; i < MT_IB; i++) {
101 s = TWIST(b, i, i+1);
102 b[i] = b[i + MT_IA] ^ (s >> 1) ^ MAGIC(s);
104 for (; i < MT_LEN-1; i++) {
105 s = TWIST(b, i, i+1);
106 b[i] = b[i - MT_IB] ^ (s >> 1) ^ MAGIC(s);
109 s = TWIST(b, MT_LEN-1, 0);
110 b[MT_LEN-1] = b[MT_IA-1] ^ (s >> 1) ^ MAGIC(s);
113 //back to my crap - tarn
114 void pop_trandom_uniform_seed()
116 if(mt_virtual_buffer>0)mt_virtual_buffer--;
117 mt_cur_buffer=mt_virtual_buffer;
118 if(mt_cur_buffer>=MT_BUFFER_NUM)mt_cur_buffer=MT_BUFFER_NUM-1;
121 void push_trandom_uniform_seed(uint32_t newseed)
123 mt_virtual_buffer++;
124 mt_cur_buffer=mt_virtual_buffer;
125 if(mt_cur_buffer>=MT_BUFFER_NUM)
127 mt_cur_buffer=MT_BUFFER_NUM-1;
128 errorlog_string("Random Buffer Overload");
131 short i;
133 uint32_t * b = mt_buffer[mt_cur_buffer];
135 b[0]=newseed;
136 for(i=1;i<MT_LEN;i++)
138 //2010: better init line from wikipedia, ultimate source unknown
139 b[i]=1812433253UL * (b[i-1] ^ (b[i-1]>>30)) + i;
141 mt_index[mt_cur_buffer]=MT_LEN*sizeof(uint32_t);
143 trandom_twist();
146 void push_trandom_double_seed(uint32_t newseed1,uint32_t newseed2)
148 mt_virtual_buffer++;
149 mt_cur_buffer=mt_virtual_buffer;
150 if(mt_cur_buffer>=MT_BUFFER_NUM)
152 mt_cur_buffer=MT_BUFFER_NUM-1;
153 errorlog_string("Random Buffer Overload");
156 short i;
158 uint32_t * b = mt_buffer[mt_cur_buffer];
160 b[0]=newseed1/2+newseed2/2;
161 for(i=0;i<MT_LEN;i++)
163 b[i]=1812433253UL * (b[i-1] ^ (b[i-1]>>30)) + i;
165 mt_index[mt_cur_buffer]=MT_LEN*sizeof(uint32_t);
167 trandom_twist();
170 void push_trandom_triple_seed(uint32_t newseed1,uint32_t newseed2,uint32_t newseed3)
172 mt_virtual_buffer++;
173 mt_cur_buffer=mt_virtual_buffer;
174 if(mt_cur_buffer>=MT_BUFFER_NUM)
176 mt_cur_buffer=MT_BUFFER_NUM-1;
177 errorlog_string("Random Buffer Overload");
180 short i;
182 uint32_t * b = mt_buffer[mt_cur_buffer];
184 b[0]=newseed1/3+newseed2/3+newseed3/3;
185 for(i=0;i<MT_LEN;i++)
187 b[i]=1812433253UL * (b[i-1] ^ (b[i-1]>>30)) + i;
189 mt_index[mt_cur_buffer]=MT_LEN*sizeof(uint32_t);
191 trandom_twist();
194 //picks a random number from 0 to max-1
195 int32_t basic_random(int32_t max)
197 r_num();
199 return (int32_t)((uint32_t)basic_seed/((1073741824UL/(uint32_t)max)+1UL));
202 //sets seed to a random number from 0 to 1 billion
203 void r_num()
205 basic_seed=(int32_t)(((uint32_t)basic_seed*907725UL+99979777UL)%1073741824UL);