Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/random/normal_distribution.hpp @ 101:c530137014c0
Update Boost headers (1.58.0)
author | Chris Cannam |
---|---|
date | Mon, 07 Sep 2015 11:12:49 +0100 |
parents | 2665513ce2d3 |
children |
comparison
equal
deleted
inserted
replaced
100:793467b5e61c | 101:c530137014c0 |
---|---|
6 * accompanying file LICENSE_1_0.txt or copy at | 6 * accompanying file LICENSE_1_0.txt or copy at |
7 * http://www.boost.org/LICENSE_1_0.txt) | 7 * http://www.boost.org/LICENSE_1_0.txt) |
8 * | 8 * |
9 * See http://www.boost.org for most recent version including documentation. | 9 * See http://www.boost.org for most recent version including documentation. |
10 * | 10 * |
11 * $Id: normal_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ | 11 * $Id$ |
12 * | 12 * |
13 * Revision history | 13 * Revision history |
14 * 2001-02-18 moved to individual header files | 14 * 2001-02-18 moved to individual header files |
15 */ | 15 */ |
16 | 16 |
21 #include <istream> | 21 #include <istream> |
22 #include <iosfwd> | 22 #include <iosfwd> |
23 #include <boost/assert.hpp> | 23 #include <boost/assert.hpp> |
24 #include <boost/limits.hpp> | 24 #include <boost/limits.hpp> |
25 #include <boost/static_assert.hpp> | 25 #include <boost/static_assert.hpp> |
26 #include <boost/integer.hpp> | |
27 #include <boost/integer/integer_mask.hpp> | |
28 #include <boost/type_traits/is_integral.hpp> | |
29 #include <boost/type_traits/make_unsigned.hpp> | |
26 #include <boost/random/detail/config.hpp> | 30 #include <boost/random/detail/config.hpp> |
27 #include <boost/random/detail/operators.hpp> | 31 #include <boost/random/detail/operators.hpp> |
32 #include <boost/random/detail/integer_log2.hpp> | |
28 #include <boost/random/uniform_01.hpp> | 33 #include <boost/random/uniform_01.hpp> |
34 #include <boost/random/uniform_int_distribution.hpp> | |
35 #include <boost/random/exponential_distribution.hpp> | |
36 #include <boost/mpl/bool.hpp> | |
29 | 37 |
30 namespace boost { | 38 namespace boost { |
31 namespace random { | 39 namespace random { |
40 | |
41 namespace detail { | |
42 | |
43 // tables for the ziggurat algorithm | |
44 template<class RealType> | |
45 struct normal_table { | |
46 static const RealType table_x[129]; | |
47 static const RealType table_y[129]; | |
48 }; | |
49 | |
50 template<class RealType> | |
51 const RealType normal_table<RealType>::table_x[129] = { | |
52 3.7130862467403632609, 3.4426198558966521214, 3.2230849845786185446, 3.0832288582142137009, | |
53 2.9786962526450169606, 2.8943440070186706210, 2.8231253505459664379, 2.7611693723841538514, | |
54 2.7061135731187223371, 2.6564064112581924999, 2.6109722484286132035, 2.5690336259216391328, | |
55 2.5300096723854666170, 2.4934545220919507609, 2.4590181774083500943, 2.4264206455302115930, | |
56 2.3954342780074673425, 2.3658713701139875435, 2.3375752413355307354, 2.3104136836950021558, | |
57 2.2842740596736568056, 2.2590595738653295251, 2.2346863955870569803, 2.2110814088747278106, | |
58 2.1881804320720206093, 2.1659267937448407377, 2.1442701823562613518, 2.1231657086697899595, | |
59 2.1025731351849988838, 2.0824562379877246441, 2.0627822745039633575, 2.0435215366506694976, | |
60 2.0246469733729338782, 2.0061338699589668403, 1.9879595741230607243, 1.9701032608497132242, | |
61 1.9525457295488889058, 1.9352692282919002011, 1.9182573008597320303, 1.9014946531003176140, | |
62 1.8849670357028692380, 1.8686611409895420085, 1.8525645117230870617, 1.8366654602533840447, | |
63 1.8209529965910050740, 1.8054167642140487420, 1.7900469825946189862, 1.7748343955807692457, | |
64 1.7597702248942318749, 1.7448461281083765085, 1.7300541605582435350, 1.7153867407081165482, | |
65 1.7008366185643009437, 1.6863968467734863258, 1.6720607540918522072, 1.6578219209482075462, | |
66 1.6436741568569826489, 1.6296114794646783962, 1.6156280950371329644, 1.6017183802152770587, | |
67 1.5878768648844007019, 1.5740982160167497219, 1.5603772223598406870, 1.5467087798535034608, | |
68 1.5330878776675560787, 1.5195095847593707806, 1.5059690368565502602, 1.4924614237746154081, | |
69 1.4789819769830978546, 1.4655259573357946276, 1.4520886428822164926, 1.4386653166774613138, | |
70 1.4252512545068615734, 1.4118417124397602509, 1.3984319141236063517, 1.3850170377251486449, | |
71 1.3715922024197322698, 1.3581524543224228739, 1.3446927517457130432, 1.3312079496576765017, | |
72 1.3176927832013429910, 1.3041418501204215390, 1.2905495919178731508, 1.2769102735516997175, | |
73 1.2632179614460282310, 1.2494664995643337480, 1.2356494832544811749, 1.2217602305309625678, | |
74 1.2077917504067576028, 1.1937367078237721994, 1.1795873846544607035, 1.1653356361550469083, | |
75 1.1509728421389760651, 1.1364898520030755352, 1.1218769225722540661, 1.1071236475235353980, | |
76 1.0922188768965537614, 1.0771506248819376573, 1.0619059636836193998, 1.0464709007525802629, | |
77 1.0308302360564555907, 1.0149673952392994716, 0.99886423348064351303, 0.98250080350276038481, | |
78 0.96585507938813059489, 0.94890262549791195381, 0.93161619660135381056, 0.91396525100880177644, | |
79 0.89591535256623852894, 0.87742742909771569142, 0.85845684317805086354, 0.83895221428120745572, | |
80 0.81885390668331772331, 0.79809206062627480454, 0.77658398787614838598, 0.75423066443451007146, | |
81 0.73091191062188128150, 0.70647961131360803456, 0.68074791864590421664, 0.65347863871504238702, | |
82 0.62435859730908822111, 0.59296294244197797913, 0.55869217837551797140, 0.52065603872514491759, | |
83 0.47743783725378787681, 0.42654798630330512490, 0.36287143102841830424, 0.27232086470466385065, | |
84 0 | |
85 }; | |
86 | |
87 template<class RealType> | |
88 const RealType normal_table<RealType>::table_y[129] = { | |
89 0, 0.0026696290839025035092, 0.0055489952208164705392, 0.0086244844129304709682, | |
90 0.011839478657982313715, 0.015167298010672042468, 0.018592102737165812650, 0.022103304616111592615, | |
91 0.025693291936149616572, 0.029356317440253829618, 0.033087886146505155566, 0.036884388786968774128, | |
92 0.040742868074790604632, 0.044660862200872429800, 0.048636295860284051878, 0.052667401903503169793, | |
93 0.056752663481538584188, 0.060890770348566375972, 0.065080585213631873753, 0.069321117394180252601, | |
94 0.073611501884754893389, 0.077950982514654714188, 0.082338898242957408243, 0.086774671895542968998, | |
95 0.091257800827634710201, 0.09578784912257815216, 0.10036444102954554013, 0.10498725541035453978, | |
96 0.10965602101581776100, 0.11437051244988827452, 0.11913054670871858767, 0.12393598020398174246, | |
97 0.12878670619710396109, 0.13368265258464764118, 0.13862377998585103702, 0.14361008009193299469, | |
98 0.14864157424369696566, 0.15371831220958657066, 0.15884037114093507813, 0.16400785468492774791, | |
99 0.16922089223892475176, 0.17447963833240232295, 0.17978427212496211424, 0.18513499701071343216, | |
100 0.19053204032091372112, 0.19597565311811041399, 0.20146611007620324118, 0.20700370944187380064, | |
101 0.21258877307373610060, 0.21822164655637059599, 0.22390269938713388747, 0.22963232523430270355, | |
102 0.23541094226572765600, 0.24123899354775131610, 0.24711694751469673582, 0.25304529850976585934, | |
103 0.25902456739871074263, 0.26505530225816194029, 0.27113807914102527343, 0.27727350292189771153, | |
104 0.28346220822601251779, 0.28970486044581049771, 0.29600215684985583659, 0.30235482778947976274, | |
105 0.30876363800925192282, 0.31522938806815752222, 0.32175291587920862031, 0.32833509837615239609, | |
106 0.33497685331697116147, 0.34167914123501368412, 0.34844296754987246935, 0.35526938485154714435, | |
107 0.36215949537303321162, 0.36911445366827513952, 0.37613546951445442947, 0.38322381105988364587, | |
108 0.39038080824138948916, 0.39760785649804255208, 0.40490642081148835099, 0.41227804010702462062, | |
109 0.41972433205403823467, 0.42724699830956239880, 0.43484783025466189638, 0.44252871528024661483, | |
110 0.45029164368692696086, 0.45813871627287196483, 0.46607215269457097924, 0.47409430069824960453, | |
111 0.48220764633483869062, 0.49041482528932163741, 0.49871863547658432422, 0.50712205108130458951, | |
112 0.51562823824987205196, 0.52424057267899279809, 0.53296265938998758838, 0.54179835503172412311, | |
113 0.55075179312105527738, 0.55982741271069481791, 0.56902999107472161225, 0.57836468112670231279, | |
114 0.58783705444182052571, 0.59745315095181228217, 0.60721953663260488551, 0.61714337082656248870, | |
115 0.62723248525781456578, 0.63749547734314487428, 0.64794182111855080873, 0.65858200005865368016, | |
116 0.66942766735770616891, 0.68049184100641433355, 0.69178914344603585279, 0.70333609902581741633, | |
117 0.71515150742047704368, 0.72725691835450587793, 0.73967724368333814856, 0.75244155918570380145, | |
118 0.76558417390923599480, 0.77914608594170316563, 0.79317701178385921053, 0.80773829469612111340, | |
119 0.82290721139526200050, 0.83878360531064722379, 0.85550060788506428418, 0.87324304892685358879, | |
120 0.89228165080230272301, 0.91304364799203805999, 0.93628268170837107547, 0.96359969315576759960, | |
121 1 | |
122 }; | |
123 | |
124 template<class Engine> | |
125 inline typename boost::make_unsigned<typename Engine::result_type>::type | |
126 generate_one_digit(Engine& eng, std::size_t bits) | |
127 { | |
128 typedef typename Engine::result_type base_result; | |
129 typedef typename boost::make_unsigned<base_result>::type base_unsigned; | |
130 | |
131 base_unsigned range = | |
132 detail::subtract<base_result>()((eng.max)(), (eng.min)()); | |
133 base_unsigned y0_mask = (base_unsigned(2) << (bits - 1)) - 1; | |
134 base_unsigned y0 = (range + 1) & ~y0_mask; | |
135 base_unsigned u; | |
136 do { | |
137 u = detail::subtract<base_result>()(eng(), (eng.min)()); | |
138 } while(y0 != 0 && u > base_unsigned(y0 - 1)); | |
139 return u & y0_mask; | |
140 } | |
141 | |
142 template<class RealType, std::size_t w, class Engine> | |
143 std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::true_) | |
144 { | |
145 typedef typename Engine::result_type base_result; | |
146 typedef typename boost::make_unsigned<base_result>::type base_unsigned; | |
147 | |
148 base_unsigned range = | |
149 detail::subtract<base_result>()((eng.max)(), (eng.min)()); | |
150 | |
151 std::size_t m = | |
152 (range == (std::numeric_limits<base_unsigned>::max)()) ? | |
153 std::numeric_limits<base_unsigned>::digits : | |
154 detail::integer_log2(range + 1); | |
155 | |
156 int bucket = 0; | |
157 // process as many full digits as possible into the int part | |
158 for(std::size_t i = 0; i < w/m; ++i) { | |
159 base_unsigned u = generate_one_digit(eng, m); | |
160 bucket = (bucket << m) | u; | |
161 } | |
162 RealType r; | |
163 | |
164 const std::size_t digits = std::numeric_limits<RealType>::digits; | |
165 { | |
166 base_unsigned u = generate_one_digit(eng, m); | |
167 base_unsigned mask = (base_unsigned(1) << (w%m)) - 1; | |
168 bucket = (bucket << (w%m)) | (mask & u); | |
169 const RealType mult = RealType(1)/RealType(base_unsigned(1) << (m - w%m)); | |
170 // zero out unused bits | |
171 if (m - w%m > digits) { | |
172 u &= ~(base_unsigned(1) << (m - digits)); | |
173 } | |
174 r = RealType(u >> (w%m)) * mult; | |
175 } | |
176 for(std::size_t i = m - w%m; i + m < digits; ++i) { | |
177 base_unsigned u = generate_one_digit(eng, m); | |
178 r += u; | |
179 r *= RealType(0.5)/RealType(base_unsigned(1) << (m - 1)); | |
180 } | |
181 if (m - w%m < digits) | |
182 { | |
183 const std::size_t remaining = (digits - m + w%m) % m; | |
184 base_unsigned u = generate_one_digit(eng, m); | |
185 r += u & ((base_unsigned(2) << (remaining - 1)) - 1); | |
186 const RealType mult = RealType(0.5)/RealType(base_unsigned(1) << (remaining - 1)); | |
187 r *= mult; | |
188 } | |
189 return std::make_pair(r, bucket); | |
190 } | |
191 | |
192 template<class RealType, std::size_t w, class Engine> | |
193 inline std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::false_) | |
194 { | |
195 int bucket = uniform_int_distribution<>(0, (1 << w) - 1)(eng); | |
196 RealType r = uniform_01<RealType>()(eng); | |
197 return std::make_pair(r, bucket); | |
198 } | |
199 | |
200 template<class RealType, std::size_t w, class Engine> | |
201 inline std::pair<RealType, int> generate_int_float_pair(Engine& eng) | |
202 { | |
203 typedef typename Engine::result_type base_result; | |
204 return generate_int_float_pair<RealType, w>(eng, | |
205 boost::is_integral<base_result>()); | |
206 } | |
207 | |
208 template<class RealType = double> | |
209 struct unit_normal_distribution | |
210 { | |
211 template<class Engine> | |
212 RealType operator()(Engine& eng) { | |
213 const double * const table_x = normal_table<double>::table_x; | |
214 const double * const table_y = normal_table<double>::table_y; | |
215 for(;;) { | |
216 std::pair<RealType, int> vals = generate_int_float_pair<RealType, 8>(eng); | |
217 int i = vals.second; | |
218 int sign = (i & 1) * 2 - 1; | |
219 i = i >> 1; | |
220 RealType x = vals.first * RealType(table_x[i]); | |
221 if(x < table_x[i + 1]) return x * sign; | |
222 if(i == 0) return generate_tail(eng) * sign; | |
223 RealType y = RealType(table_y[i]) + uniform_01<RealType>()(eng) * RealType(table_y[i + 1] - table_y[i]); | |
224 if (y < f(x)) return x * sign; | |
225 } | |
226 } | |
227 static RealType f(RealType x) { | |
228 using std::exp; | |
229 return exp(-x*x/2); | |
230 } | |
231 template<class Engine> | |
232 RealType generate_tail(Engine& eng) { | |
233 boost::random::exponential_distribution<RealType> exponential; | |
234 const RealType tail_start = RealType(normal_table<double>::table_x[1]); | |
235 for(;;) { | |
236 RealType x = exponential(eng)/tail_start; | |
237 RealType y = exponential(eng); | |
238 if(2*y > x*x) return x + tail_start; | |
239 } | |
240 } | |
241 }; | |
242 | |
243 } | |
32 | 244 |
33 // deterministic Box-Muller method, uses trigonometric functions | 245 // deterministic Box-Muller method, uses trigonometric functions |
34 | 246 |
35 /** | 247 /** |
36 * Instantiations of class template normal_distribution model a | 248 * Instantiations of class template normal_distribution model a |
37 * \random_distribution. Such a distribution produces random numbers | 249 * \random_distribution. Such a distribution produces random numbers |
38 * @c x distributed with probability density function | 250 * @c x distributed with probability density function |
39 * \f$\displaystyle p(x) = | 251 * \f$\displaystyle p(x) = |
40 * \frac{1}{\sqrt{2\pi\sigma}} e^{-\frac{(x-\mu)^2}{2\sigma^2}} | 252 * \frac{1}{\sqrt{2\pi}\sigma} e^{-\frac{(x-\mu)^2}{2\sigma^2}} |
41 * \f$, | 253 * \f$, |
42 * where mean and sigma are the parameters of the distribution. | 254 * where mean and sigma are the parameters of the distribution. |
43 */ | 255 */ |
44 template<class RealType = double> | 256 template<class RealType = double> |
45 class normal_distribution | 257 class normal_distribution |
96 * | 308 * |
97 * Requires: sigma >= 0 | 309 * Requires: sigma >= 0 |
98 */ | 310 */ |
99 explicit normal_distribution(const RealType& mean_arg = RealType(0.0), | 311 explicit normal_distribution(const RealType& mean_arg = RealType(0.0), |
100 const RealType& sigma_arg = RealType(1.0)) | 312 const RealType& sigma_arg = RealType(1.0)) |
101 : _mean(mean_arg), _sigma(sigma_arg), | 313 : _mean(mean_arg), _sigma(sigma_arg) |
102 _r1(0), _r2(0), _cached_rho(0), _valid(false) | |
103 { | 314 { |
104 BOOST_ASSERT(_sigma >= RealType(0)); | 315 BOOST_ASSERT(_sigma >= RealType(0)); |
105 } | 316 } |
106 | 317 |
107 /** | 318 /** |
108 * Constructs a @c normal_distribution object from its parameters. | 319 * Constructs a @c normal_distribution object from its parameters. |
109 */ | 320 */ |
110 explicit normal_distribution(const param_type& parm) | 321 explicit normal_distribution(const param_type& parm) |
111 : _mean(parm.mean()), _sigma(parm.sigma()), | 322 : _mean(parm.mean()), _sigma(parm.sigma()) |
112 _r1(0), _r2(0), _cached_rho(0), _valid(false) | |
113 {} | 323 {} |
114 | 324 |
115 /** Returns the mean of the distribution. */ | 325 /** Returns the mean of the distribution. */ |
116 RealType mean() const { return _mean; } | 326 RealType mean() const { return _mean; } |
117 /** Returns the standard deviation of the distribution. */ | 327 /** Returns the standard deviation of the distribution. */ |
129 /** Sets the parameters of the distribution. */ | 339 /** Sets the parameters of the distribution. */ |
130 void param(const param_type& parm) | 340 void param(const param_type& parm) |
131 { | 341 { |
132 _mean = parm.mean(); | 342 _mean = parm.mean(); |
133 _sigma = parm.sigma(); | 343 _sigma = parm.sigma(); |
134 _valid = false; | |
135 } | 344 } |
136 | 345 |
137 /** | 346 /** |
138 * Effects: Subsequent uses of the distribution do not depend | 347 * Effects: Subsequent uses of the distribution do not depend |
139 * on values produced by any engine prior to invoking reset. | 348 * on values produced by any engine prior to invoking reset. |
140 */ | 349 */ |
141 void reset() { _valid = false; } | 350 void reset() { } |
142 | 351 |
143 /** Returns a normal variate. */ | 352 /** Returns a normal variate. */ |
144 template<class Engine> | 353 template<class Engine> |
145 result_type operator()(Engine& eng) | 354 result_type operator()(Engine& eng) |
146 { | 355 { |
147 using std::sqrt; | 356 detail::unit_normal_distribution<RealType> impl; |
148 using std::log; | 357 return impl(eng) * _sigma + _mean; |
149 using std::sin; | |
150 using std::cos; | |
151 | |
152 if(!_valid) { | |
153 _r1 = boost::uniform_01<RealType>()(eng); | |
154 _r2 = boost::uniform_01<RealType>()(eng); | |
155 _cached_rho = sqrt(-result_type(2) * log(result_type(1)-_r2)); | |
156 _valid = true; | |
157 } else { | |
158 _valid = false; | |
159 } | |
160 // Can we have a boost::mathconst please? | |
161 const result_type pi = result_type(3.14159265358979323846); | |
162 | |
163 return _cached_rho * (_valid ? | |
164 cos(result_type(2)*pi*_r1) : | |
165 sin(result_type(2)*pi*_r1)) | |
166 * _sigma + _mean; | |
167 } | 358 } |
168 | 359 |
169 /** Returns a normal variate with parameters specified by @c param. */ | 360 /** Returns a normal variate with parameters specified by @c param. */ |
170 template<class URNG> | 361 template<class URNG> |
171 result_type operator()(URNG& urng, const param_type& parm) | 362 result_type operator()(URNG& urng, const param_type& parm) |
174 } | 365 } |
175 | 366 |
176 /** Writes a @c normal_distribution to a @c std::ostream. */ | 367 /** Writes a @c normal_distribution to a @c std::ostream. */ |
177 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, normal_distribution, nd) | 368 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, normal_distribution, nd) |
178 { | 369 { |
179 os << nd._mean << " " << nd._sigma << " " | 370 os << nd._mean << " " << nd._sigma; |
180 << nd._valid << " " << nd._cached_rho << " " << nd._r1; | |
181 return os; | 371 return os; |
182 } | 372 } |
183 | 373 |
184 /** Reads a @c normal_distribution from a @c std::istream. */ | 374 /** Reads a @c normal_distribution from a @c std::istream. */ |
185 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, normal_distribution, nd) | 375 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, normal_distribution, nd) |
186 { | 376 { |
187 is >> std::ws >> nd._mean >> std::ws >> nd._sigma | 377 is >> std::ws >> nd._mean >> std::ws >> nd._sigma; |
188 >> std::ws >> nd._valid >> std::ws >> nd._cached_rho | |
189 >> std::ws >> nd._r1; | |
190 return is; | 378 return is; |
191 } | 379 } |
192 | 380 |
193 /** | 381 /** |
194 * Returns true if the two instances of @c normal_distribution will | 382 * Returns true if the two instances of @c normal_distribution will |
195 * return identical sequences of values given equal generators. | 383 * return identical sequences of values given equal generators. |
196 */ | 384 */ |
197 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(normal_distribution, lhs, rhs) | 385 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(normal_distribution, lhs, rhs) |
198 { | 386 { |
199 return lhs._mean == rhs._mean && lhs._sigma == rhs._sigma | 387 return lhs._mean == rhs._mean && lhs._sigma == rhs._sigma; |
200 && lhs._valid == rhs._valid | |
201 && (!lhs._valid || (lhs._r1 == rhs._r1 && lhs._r2 == rhs._r2)); | |
202 } | 388 } |
203 | 389 |
204 /** | 390 /** |
205 * Returns true if the two instances of @c normal_distribution will | 391 * Returns true if the two instances of @c normal_distribution will |
206 * return different sequences of values given equal generators. | 392 * return different sequences of values given equal generators. |
207 */ | 393 */ |
208 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(normal_distribution) | 394 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(normal_distribution) |
209 | 395 |
210 private: | 396 private: |
211 RealType _mean, _sigma; | 397 RealType _mean, _sigma; |
212 RealType _r1, _r2, _cached_rho; | |
213 bool _valid; | |
214 | 398 |
215 }; | 399 }; |
216 | 400 |
217 } // namespace random | 401 } // namespace random |
218 | 402 |