Ticket #12099: scratch.cpp

File scratch.cpp, 20.5 KB (added by Steven Watanabe, 7 years ago)

Source for the tables used by boost::random::normal_distribution

Line 
1#include <boost/random/mersenne_twister.hpp>
2#include <boost/random/gamma_distribution.hpp>
3#include <boost/random/gamma_distribution_new.hpp>
4#include <boost/math/special_functions/erf.hpp>
5#include <boost/multiprecision/cpp_dec_float.hpp>
6#include <boost/timer.hpp>
7#include <iostream>
8#include <random>
9
10volatile double val;
11
12template<class RealType>
13struct exponential_table {
14 static const RealType table_x[];
15 static const RealType table_y[];
16};
17
18template<class RealType>
19const RealType exponential_table<RealType>::table_x[] = {
20 8.697117470131049714, 7.697117470131049714, 6.9410336293772123602, 6.4783784938325698538,
21 6.1441646657724730491, 5.8821443157953997963, 5.6664101674540337371, 5.4828906275260628694,
22 5.3230905057543986131, 5.1814872813015010392, 5.0542884899813047117, 4.9387770859012514838,
23 4.8329397410251125881, 4.7352429966017412526, 4.6444918854200854873, 4.5597370617073515513,
24 4.4802117465284221949, 4.4052876934735729805, 4.3344436803172730116, 4.2672424802773661873,
25 4.2033137137351843802, 4.1423408656640511251, 4.0840513104082974638, 4.0282085446479365106,
26 3.9746060666737884793, 3.9230625001354895926, 3.8734176703995089983, 3.8255294185223367372,
27 3.7792709924116678992, 3.734528894039797535, 3.6912010902374189454, 3.6491955157608538478,
28 3.6084288131289096339, 3.5688252656483374051, 3.5303158891293438633, 3.4928376547740601814,
29 3.4563328211327607625, 3.4207483572511205323, 3.3860354424603017887, 3.3521490309001100106,
30 3.3190474709707487166, 3.2866921715990692095, 3.2550473085704501813, 3.2240795652862645207,
31 3.1937579032122407483, 3.164053358025973458, 3.1349388580844407393, 3.106389062339824666,
32 3.0783802152540905188, 3.0508900166154554479, 3.0238975044556767713, 2.9973829495161306949,
33 2.9713277599210896472, 2.9457143948950456386, 2.9205262865127406647, 2.8957477686001416838,
34 2.8713640120155362592, 2.8473609656351888266, 2.8237253024500354905, 2.8004443702507381944,
35 2.7775061464397572041, 2.754899196562345365, 2.7326126361947007411, 2.7106360958679293686,
36 2.6889596887418041593, 2.6675739807732670816, 2.6464699631518093905, 2.6256390267977886123,
37 2.6050729387408355373, 2.5847638202141406911, 2.5647041263169053687, 2.5448866271118700928,
38 2.5253043900378279427, 2.5059507635285939648, 2.4868193617402096807, 2.4679040502973649846,
39 2.4491989329782498908, 2.4306983392644199088, 2.4123968126888708336, 2.3942890999214583288,
40 2.3763701405361408194, 2.3586350574093374601, 2.3410791477030346875, 2.3236978743901964559,
41 2.3064868582835798692, 2.2894418705322694265, 2.2725588255531546952, 2.2558337743672190441,
42 2.2392628983129087111, 2.2228425031110364013, 2.2065690132576635755, 2.1904389667232199235,
43 2.1744490099377744673, 2.1585958930438856781, 2.1428764653998416425, 2.1272876713173679737,
44 2.1118265460190418108, 2.0964902118017147637, 2.0812758743932248696, 2.0661808194905755036,
45 2.0512024094685848641, 2.0363380802487695916, 2.021585338318926077, 2.0069417578945183144,
46 1.9924049782135764992, 1.9779727009573602295, 1.9636426877895480401, 1.9494127580071845659,
47 1.9352807862970511135, 1.9212447005915276767, 1.9073024800183871196, 1.8934521529393077332,
48 1.8796917950722108462, 1.8660195276928275962, 1.8524335159111751661, 1.838931967018879398,
49 1.8255131289035192212, 1.8121752885263901413, 1.7989167704602903934, 1.7857359354841254047,
50 1.7726311792313049959, 1.7596009308890742369, 1.7466436519460739352, 1.7337578349855711926,
51 1.7209420025219350428, 1.7081947058780575683, 1.6955145241015377061, 1.6829000629175537544,
52 1.6703499537164519163, 1.6578628525741725325, 1.6454374393037234057, 1.6330724165359912048,
53 1.6207665088282577216, 1.6085184617988580769, 1.5963270412864831349, 1.5841910325326886695,
54 1.572109239386229481, 1.5600804835278879161, 1.548103603714513307, 1.5361774550410318943,
55 1.524300908219226005, 1.5124728488721167573, 1.5006921768428164936, 1.4889578055167456003,
56 1.4772686611561334579, 1.4656236822457450411, 1.4540218188487932264, 1.4424620319720121876,
57 1.4309432929388794104, 1.4194645827699828254, 1.4080248915695353509, 1.396623217917041711,
58 1.3852585682631217189, 1.3739299563284902176, 1.3626364025050864742, 1.3513769332583349176,
59 1.3401505805295045843, 1.328956381137116322, 1.317793376176324548, 1.3066606104151739482,
60 1.295557131686600721, 1.284481990275012545, 1.2734342382962410994, 1.2624129290696153434,
61 1.2514171164808525098, 1.2404458543344064544, 1.2294981956938491599, 1.2185731922087903071,
62 1.207669893426761283, 1.1967873460884031665, 1.1859245934042023557, 1.1750806743109117687,
63 1.1642546227056790397, 1.1534454666557748056, 1.1426522275816728928, 1.1318739194110786733,
64 1.1211095477013306083, 1.1103581087274114281, 1.0996185885325976575, 1.0888899619385472598,
65 1.0781711915113727024, 1.067461226479968153, 1.0567590016025518414, 1.0460634359770445503,
66 1.0353734317905289496, 1.0246878730026178052, 1.0140056239570971074, 1.0033255279156973717,
67 0.99264640550727647009, 0.98196705308506317914, 0.97128624098390397896, 0.96060271166866709917,
68 0.9499151777640765994, 0.93922231995526297952, 0.92852278474721113999, 0.91781518207004493915,
69 0.907098082715691006, 0.89637001558989069006, 0.88562946476175228052, 0.87487486629102585352,
70 0.86410460481100519511, 0.85331700984237406386, 0.84251035181036928333, 0.83168283773427388393,
71 0.8208326065544125229, 0.8099577240574190662, 0.79905617735548788109, 0.78812586886949324977,
72 0.77716460975913043936, 0.76617011273543541328, 0.75513998418198289808, 0.74407171550050873971,
73 0.73296267358436604916, 0.72181009030875689912, 0.71061105090965570413, 0.69936248110323266174,
74 0.68806113277374858613, 0.67670356802952337911, 0.66528614139267855405, 0.65380497984766565353,
75 0.64225596042453703448, 0.63063468493349100113, 0.61893645139487678178, 0.60715622162030085137,
76 0.59528858429150359384, 0.58332771274877027785, 0.57126731653258903915, 0.55910058551154127652,
77 0.5468201251633111255, 0.53441788123716615385, 0.52188505159213564105, 0.50921198244365495319,
78 0.49638804551867159754, 0.48340149165346224782, 0.47023927508216945338, 0.45688684093142071279,
79 0.44332786607355296305, 0.42954394022541129589, 0.415514169600357001, 0.40121467889627836229,
80 0.38661797794112021568, 0.37169214532991786118, 0.35639976025839443721, 0.34069648106484979674,
81 0.32452911701691008547, 0.30783295467493287307, 0.29052795549123115167, 0.27251318547846547924,
82 0.25365836338591284433, 0.23379048305967553619, 0.21267151063096745264, 0.18995868962243277774,
83 0.16512762256418831796, 0.1373049809400138042, 0.10483850756582017915, 0.063852163815003480173,
84 0,
85};
86
87template<class RealType>
88const RealType exponential_table<RealType>::table_y[] = {
89 0, 0.00045413435384149675545, 0.00096726928232717452884, 0.0015362997803015723824,
90 0.0021459677437189061793, 0.002788798793574075964, 0.0034602647778369039855, 0.0041572951208337952532,
91 0.0048776559835423925804, 0.005619642207205483171, 0.0063819059373191794422, 0.0071633531836349841425,
92 0.0079630774380170392396, 0.0087803149858089752347, 0.0096144136425022094101, 0.010464810181029979488,
93 0.011331013597834597488, 0.012212592426255380661, 0.01310916493125499107, 0.014020391403181937334,
94 0.014945968011691148079, 0.01588562183997316249, 0.016839106826039946359, 0.017806200410911360563,
95 0.018786700744696029497, 0.019780424338009741737, 0.020787204072578117603, 0.021806887504283582125,
96 0.022839335406385238829, 0.023884420511558170348, 0.024942026419731782971, 0.026012046645134218076,
97 0.027094383780955798424, 0.028188948763978634421, 0.029295660224637394015, 0.030414443910466605492,
98 0.031545232172893605499, 0.032687963508959533317, 0.033842582150874329031, 0.035009037697397411067,
99 0.036187284781931419754, 0.037377282772959360128, 0.038578995503074859626, 0.03979239102337412267,
100 0.041017441380414820816, 0.042254122413316231413, 0.043502413568888183301, 0.044762297732943280694,
101 0.046033761076175166762, 0.047316792913181548703, 0.048611385573379494401, 0.049917534282706374944,
102 0.05123523705512627983, 0.052564494593071689595, 0.053905310196046085104, 0.055257689676697038322,
103 0.056621641283742874438, 0.057997175631200659098, 0.059384305633420264487, 0.060783046445479636051,
104 0.06219341540854099615, 0.063615431999807331076, 0.065049117786753755036, 0.066494496385339779043,
105 0.06795159342193660777, 0.069420436498728751675, 0.070901055162371828426, 0.072393480875708743023,
106 0.073897746992364746308, 0.075413888734058408453, 0.0769419431704805101, 0.078481949201606426042,
107 0.080033947542319910023, 0.08159798070923742093, 0.083174093009632380354, 0.084762330532368125386,
108 0.086362741140756912277, 0.0879753744672702193, 0.089600281910032864534, 0.091237516631040162057,
109 0.092887133556043546523, 0.094549189376055853718, 0.096223742550432800103, 0.097910853311492199618,
110 0.099610583670637128826, 0.10132299742595363588, 0.10304816017125771553, 0.10478613930657016928,
111 0.10653700405000166218, 0.10830082545103379867, 0.11007767640518539026, 0.11186763167005629731,
112 0.11367076788274431301, 0.11548716357863353664, 0.11731689921155557057, 0.11916005717532768467,
113 0.12101672182667483729, 0.12288697950954513498, 0.12477091858083096578, 0.12666862943751066518,
114 0.1285802045452281787, 0.13050573846833078225, 0.13244532790138752023, 0.13439907170221363078,
115 0.13636707092642885841, 0.13834942886358021406, 0.1403462510748624421, 0.14235764543247220043,
116 0.14438372216063476473, 0.14642459387834493787, 0.14848037564386679222, 0.15055118500103990354,
117 0.15263714202744286154, 0.15473836938446807312, 0.15685499236936522013, 0.15898713896931420572,
118 0.16113493991759203183, 0.16329852875190180795, 0.16547804187493600915, 0.16767361861725019322,
119 0.16988540130252766513, 0.172113535315320057, 0.17435816917135348788, 0.17661945459049489581,
120 0.17889754657247831241, 0.18119260347549629488, 0.1835047870977674615, 0.18583426276219711495,
121 0.18818119940425430485, 0.19054576966319540013, 0.19292814997677133873, 0.19532852067956322315,
122 0.19774706610509886464, 0.20018397469191127727, 0.2026394390937090193, 0.2051136562938377088,
123 0.20760682772422204205, 0.21011915938898825914, 0.21265086199297827522, 0.21520215107537867786,
124 0.21777324714870053264, 0.2203643758433594972, 0.2229757680581201805, 0.22560766011668406495,
125 0.22826029393071670664, 0.23093391716962742173, 0.23362878343743333945, 0.23634515245705964715,
126 0.23908329026244917002, 0.24184346939887722761, 0.24462596913189210901, 0.24743107566532763894,
127 0.25025908236886230967, 0.25311029001562948171, 0.25598500703041538015, 0.25888354974901621678,
128 0.26180624268936295243, 0.26475341883506220209, 0.26772541993204481808, 0.27072259679906003167,
129 0.27374530965280298302, 0.27679392844851734458, 0.2798688332369728992, 0.2829704145387807601,
130 0.28609907373707684673, 0.28925522348967773308, 0.29243928816189258772, 0.29565170428126120948,
131 0.29889292101558177099, 0.30216340067569352897, 0.30546361924459023541, 0.30879406693456016794,
132 0.31215524877417956945, 0.31554768522712893632, 0.31897191284495723773, 0.32242848495608914289,
133 0.32591797239355619822, 0.32944096426413633091, 0.33299806876180896713, 0.33658991402867758144,
134 0.3402171490667800456, 0.3438804447045024301, 0.34758049462163698567, 0.35131801643748334681,
135 0.35509375286678745925, 0.35890847294874976196, 0.36276297335481777335, 0.3666580797815141489,
136 0.37059464843514599421, 0.37457356761590215193, 0.37859575940958081092, 0.38266218149600982112,
137 0.38677382908413768115, 0.39093173698479710717, 0.39513698183329015336, 0.39939068447523107877,
138 0.40369401253053026739, 0.40804818315203238238, 0.41245446599716116772, 0.41691418643300289465,
139 0.42142872899761659635, 0.42599954114303435739, 0.43062813728845883923, 0.43531610321563659758,
140 0.44006510084235387501, 0.44487687341454851593, 0.44975325116275498919, 0.45469615747461548049,
141 0.45970761564213768669, 0.46478975625042618067, 0.46994482528395999841, 0.47517519303737738299,
142 0.48048336393045423016, 0.48587198734188493564, 0.491343869594032555, 0.49690198724154955294,
143 0.50254950184134769289, 0.50828977641064283495, 0.51412639381474855788, 0.52006317736823356823,
144 0.52610421398361972602, 0.53225388026304326945, 0.5385168720028618659, 0.54489823767243963663,
145 0.55140341654064131685, 0.5580382822625874814, 0.56480919291240022434, 0.57172304866482579008,
146 0.57878735860284503057, 0.58601031847726802755, 0.59340090169173341521, 0.60096896636523224742,
147 0.60872538207962206507, 0.61668218091520762326, 0.62485273870366592605, 0.63325199421436607968,
148 0.64189671642726607018, 0.65080583341457104881, 0.66000084107899974178, 0.66950631673192477684,
149 0.67935057226476538741, 0.6895664961170779889, 0.70019265508278816709, 0.71127476080507597882,
150 0.72286765959357200702, 0.7350380924314235153, 0.74786862198519510742, 0.76146338884989624862,
151 0.77595685204011559675, 0.79152763697249565519, 0.80842165152300838005, 0.82699329664305033399,
152 0.84778550062398962096, 0.87170433238120363669, 0.900469929925746438, 0.93814368086217467916,
153 1,
154};
155
156template<class RealType = double>
157struct unit_exponential_distribution {
158 template<class Engine>
159 RealType operator()(Engine& eng) {
160 const RealType * const table_x = exponential_table<RealType>::table_x;
161 const RealType * const table_y = exponential_table<RealType>::table_y;
162 for(;;) {
163 std::pair<RealType, int> values = boost::random::detail::generate_int_float_pair<RealType, 8>(eng);
164 int i = values.second;
165 RealType x = values.first * table_x[i];
166 if(x < table_x[i + 1]) return x;
167 if(i == 0) return table_x[1] + operator()(eng);
168 RealType y = table_y[i] + boost::random::uniform_01<RealType>()(eng) * (table_y[i + 1] - table_y[i]);
169 if (log(y) < -x) {
170 return x;
171 }
172 }
173 }
174};
175
176#if 1
177
178// f(x) must be a decreasing function whose value is in [low, high]
179template<class F, class RealType>
180RealType invert(const F& f, RealType x, RealType low, RealType high) {
181 RealType lowv = f(low);
182 RealType highv = f(high);
183 RealType mid = low + (high - low) / 2;
184 RealType midv = f(mid);
185
186 while(low != mid && high != mid) {
187 // std::cout << "f(" << low << ")=" << lowv << ", f(" << mid << ")=" << midv << ", f(" << high << ")=" << highv << std::endl;
188 if(highv > x) {
189 return high;
190 }
191 if(lowv < x) {
192 return low;
193 }
194 if (midv < x) {
195 high = mid;
196 highv = midv;
197 } else {
198 low = mid;
199 lowv = midv;
200 }
201 mid = low + (high - low) / 2;
202 midv = f(mid);
203 }
204 return mid;
205}
206
207template<class RealType, int N>
208struct ziggurat_table {
209 RealType x[N + 1];
210 RealType y[N + 1];
211
212 template<class F>
213 void fill(F f, RealType guess_x1, RealType tail) {
214 y[0] = 0;
215 x[1] = guess_x1;
216 y[1] = f(x[1]);
217 RealType a = x[1] * y[1] + tail;
218 x[0] = a / y[1];
219 for(int i = 1; i < N; ++i) {
220 //std::cout << "i=" << i << std::endl;
221 y[i + 1] = a / x[i] + y[i];
222 x[i + 1] = invert(f, y[i + 1], RealType(0), guess_x1);
223 }
224 }
225};
226
227int count = 0;
228
229template<class RealType, int N, class F, class FTail>
230struct finder {
231 RealType operator()(RealType x0) const {
232 //if (++count % 2 == 0) {
233 // std::cout << "on " << count << std::endl;
234 //}
235 std::cout << x0 << std::endl;
236 ziggurat_table<RealType, N> table;
237 table.fill(f, x0, ftail(x0));
238 return table.y[N];
239 }
240 F f;
241 FTail ftail;
242};
243
244struct unnormalized_normal {
245 template<class RealType>
246 RealType operator()(RealType x) const {
247 return exp(-x*x/2);
248 }
249};
250
251struct unnormalized_normal_tail {
252 template<class RealType>
253 RealType operator()(RealType x) const {
254 return boost::math::constants::root_half_pi<RealType>()*
255 boost::math::erfc(x*boost::math::constants::one_div_root_two<RealType>());
256 }
257};
258
259struct unnormalized_exponential {
260 template<class RealType>
261 RealType operator()(RealType x) const {
262 return exp(-x);
263 }
264};
265
266struct unnormalized_exponential_tail {
267 template<class RealType>
268 RealType operator()(RealType x) const {
269 return exp(-x);
270 }
271};
272
273template<class RealType>
274RealType invert(const unnormalized_exponential& f, RealType x, RealType low, RealType high) {
275 if (x < RealType(0))
276 return high;
277 if (x > f(low)) return low;
278 return std::max(std::min(RealType(-log(x)), high), low);
279}
280
281static const int table_size = 256;
282
283template<class RealType>
284void print_table(RealType low, RealType high) {
285 // finder<RealType, 64, unnormalized_normal, unnormalized_normal_tail> f;
286 finder<RealType, table_size, unnormalized_exponential, unnormalized_exponential_tail> f;
287 std::cout << std::setprecision(50);
288 RealType x0 = invert(f, f.f(RealType(0.0)), low, high);
289 std::cout << std::setprecision(20) << x0 << std::endl;
290 std::cout << std::setprecision(20) << f(x0) << std::endl;
291 ziggurat_table<RealType, table_size> table;
292 table.fill(f.f, x0, f.ftail(x0));
293 std::cout << "x: ";
294 for(int i = 0; i <= table_size; ++i) {
295 if(i % 4 == 0) std::cout << "\n ";
296 else std::cout << " ";
297 std::cout << table.x[i];
298 std::cout << ",";
299 }
300 std::cout << "\ny: ";
301 for(int i = 0; i <= table_size; ++i) {
302 if(i % 4 == 0) std::cout << "\n ";
303 else std::cout << " ";
304 std::cout << table.y[i];
305 std::cout << ",";
306 }
307 std::cout << std::endl;
308}
309
310#endif
311
312int main() {
313#if 0
314 {
315 boost::mt19937 gen;
316 boost::random::gamma_distribution<> dist(2.5);
317 boost::timer timer;
318 for(int i = 0; i < 100000000; ++i)
319 val = dist(gen);
320 std::cout << timer.elapsed() << std::endl;
321 }
322 {
323 boost::mt19937 gen;
324 boost::random::gamma_distribution_new<> dist(2.5);
325 boost::timer timer;
326 for(int i = 0; i < 100000000; ++i)
327 val = dist(gen);
328 std::cout << timer.elapsed() << std::endl;
329 }
330 {
331 boost::mt19937 gen;
332 std::gamma_distribution<> dist(2.5);
333 boost::timer timer;
334 for(int i = 0; i < 100000000; ++i)
335 val = dist(gen);
336 std::cout << timer.elapsed() << std::endl;
337 }
338#endif
339#if 0
340 {
341 boost::mt19937 gen;
342 boost::random::normal_distribution<float> dist;
343 boost::timer timer;
344 for(int i = 0; i < 100000000; ++i)
345 val = dist(gen);
346 std::cout << timer.elapsed() << std::endl;
347 }
348 {
349 boost::mt19937 gen;
350 unit_normal_distribution<float> dist;
351 boost::timer timer;
352 for(int i = 0; i < 100000000; ++i)
353 val = dist(gen);
354 std::cout << timer.elapsed() << std::endl;
355 }
356 {
357 boost::mt19937 gen;
358 std::normal_distribution<float> dist;
359 boost::timer timer;
360 for(int i = 0; i < 100000000; ++i)
361 val = dist(gen);
362 std::cout << timer.elapsed() << std::endl;
363 }
364#endif
365#if 1
366 {
367 boost::mt19937 gen;
368 boost::random::exponential_distribution<> dist;
369 boost::timer timer;
370 for(int i = 0; i < 100000000; ++i)
371 val = dist(gen);
372 std::cout << timer.elapsed() << std::endl;
373 }
374 {
375 boost::mt19937 gen;
376 boost::random::detail::unit_exponential_distribution<> dist;
377 boost::timer timer;
378 for(int i = 0; i < 100000000; ++i)
379 val = dist(gen);
380 std::cout << timer.elapsed() << std::endl;
381 }
382 {
383 boost::mt19937 gen;
384 unit_exponential_distribution<> dist;
385 boost::timer timer;
386 for(int i = 0; i < 100000000; ++i)
387 val = dist(gen);
388 std::cout << timer.elapsed() << std::endl;
389 }
390 {
391 boost::mt19937 gen;
392 std::exponential_distribution<> dist;
393 boost::timer timer;
394 for(int i = 0; i < 100000000; ++i)
395 val = dist(gen);
396 std::cout << timer.elapsed() << std::endl;
397 }
398#endif
399#if 0
400 boost::multiprecision::cpp_dec_float_50 low(6);
401 boost::multiprecision::cpp_dec_float_50 high(8);
402 print_table(low, high);
403 //print_table(3.0, 10.0);
404#endif
405}