Boost156NormalDistribution.hpp

Go to the documentation of this file.
00001 
00030 /* boost random/normal_distribution.hpp header file
00031  *
00032  * Copyright Jens Maurer 2000-2001
00033  * Copyright Steven Watanabe 2010-2011
00034  * Distributed under the Boost Software License, Version 1.0. (See
00035  * accompanying file LICENSE_1_0.txt or copy at
00036  * http://www.boost.org/LICENSE_1_0.txt)
00037  *
00038  * See http://www.boost.org for most recent version including documentation.
00039  *
00040  * $Id$
00041  *
00042  * Revision history
00043  *  2001-02-18  moved to individual header files
00044  */
00045 
00046 #ifndef BOOST_156_RANDOM_NORMAL_DISTRIBUTION_HPP
00047 #define BOOST_156_RANDOM_NORMAL_DISTRIBUTION_HPP
00048 
00049 #include <boost/config/no_tr1/cmath.hpp>
00050 #include <istream>
00051 #include <iosfwd>
00052 #include <boost/assert.hpp>
00053 #include <boost/limits.hpp>
00054 #include <boost/static_assert.hpp>
00055 #include <boost/integer.hpp>
00056 #include <boost/integer/integer_mask.hpp>
00057 #include <boost/type_traits/is_integral.hpp>
00058 #include <boost/type_traits/make_unsigned.hpp>
00059 #include <boost/random/detail/config.hpp>
00060 
00061 #if BOOST_VERSION < 104700 // Old version
00062 
00063 #include <boost/random/detail/config.hpp>
00064 #include <boost/detail/workaround.hpp>
00065 
00066 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)   \
00067     || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
00068 
00069 #define BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, T, t)                  \
00070     template<class CharT, class Traits>                                 \
00071     friend std::basic_ostream<CharT,Traits>&                            \
00072     operator<<(std::basic_ostream<CharT,Traits>& os, const T& t) {      \
00073         t.print(os, t);                                                 \
00074         return os;                                                      \
00075     }                                                                   \
00076     template<class CharT, class Traits>                                 \
00077     static std::basic_ostream<CharT,Traits>&                            \
00078     print(std::basic_ostream<CharT,Traits>& os, const T& t)
00079 
00080 #define BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, T, t)                  \
00081     template<class CharT, class Traits>                                 \
00082     friend std::basic_istream<CharT,Traits>&                            \
00083     operator>>(std::basic_istream<CharT,Traits>& is, T& t) {            \
00084         t.read(is, t);                                                  \
00085         return is;                                                      \
00086     }                                                                   \
00087     template<class CharT, class Traits>                                 \
00088     static std::basic_istream<CharT,Traits>&                            \
00089     read(std::basic_istream<CharT,Traits>& is, T& t)
00090 
00091 #endif
00092 
00093 #if defined(__BORLANDC__)
00094 
00095 #define BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(T, lhs, rhs)              \
00096     bool operator==(const T& rhs) const                                 \
00097     { return T::is_equal(*this, rhs); }                                 \
00098     static bool is_equal(const T& lhs, const T& rhs)
00099 
00100 #define BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(T)                      \
00101     bool operator!=(const T& rhs) const                                 \
00102     { return !T::is_equal(*this, rhs); }
00103 
00104 #endif
00105 
00106 #ifndef BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR
00107 #define BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, T, t)                  \
00108     template<class CharT, class Traits>                                 \
00109     friend std::basic_ostream<CharT,Traits>&                            \
00110     operator<<(std::basic_ostream<CharT,Traits>& os, const T& t)
00111 #endif
00112 
00113 #ifndef BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR
00114 #define BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, T, t)                  \
00115     template<class CharT, class Traits>                                 \
00116     friend std::basic_istream<CharT,Traits>&                            \
00117     operator>>(std::basic_istream<CharT,Traits>& is, T& t)
00118 #endif
00119 
00120 #ifndef BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR
00121 #define BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(T, lhs, rhs)              \
00122     friend bool operator==(const T& lhs, const T& rhs)
00123 #endif
00124 
00125 #ifndef BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR
00126 #define BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(T)                      \
00127     friend bool operator!=(const T& lhs, const T& rhs)                  \
00128     { return !(lhs == rhs); }
00129 #endif
00130 
00131 #include <boost/pending/integer_log2.hpp>
00132 #else
00133 #include <boost/random/detail/operators.hpp>
00134 #include <boost/random/detail/integer_log2.hpp>
00135 
00136 #endif
00137 
00138 #include <boost/random/uniform_01.hpp>
00139 #include <boost/random/mersenne_twister.hpp>
00140 
00141 #if BOOST_VERSION < 104700
00142 #include <boost/random/uniform_int.hpp>
00144 #else
00145 #include <boost/random/uniform_int_distribution.hpp>
00146 #endif
00147 //#include <boost/random/uniform_int_distribution.hpp>
00148 // Header we had to include after commenting out the one above
00149 
00150 
00151 #include <boost/random/detail/signed_unsigned_tools.hpp>
00152 #include <boost/type_traits/make_unsigned.hpp>
00153 
00154 #include <boost/random/exponential_distribution.hpp>
00155 #include <boost/random/variate_generator.hpp>
00156 
00157 
00158 
00159 namespace boost {
00160 namespace random {
00161 
00162 namespace detail {
00163 
00164 // tables for the ziggurat algorithm
00165 template<class RealType>
00166 struct normal_table {
00167     static const RealType table_x[129];
00168     static const RealType table_y[129];
00169 };
00170 
00171 template<class RealType>
00172 const RealType normal_table<RealType>::table_x[129] = {
00173     3.7130862467403632609, 3.4426198558966521214, 3.2230849845786185446, 3.0832288582142137009,
00174     2.9786962526450169606, 2.8943440070186706210, 2.8231253505459664379, 2.7611693723841538514,
00175     2.7061135731187223371, 2.6564064112581924999, 2.6109722484286132035, 2.5690336259216391328,
00176     2.5300096723854666170, 2.4934545220919507609, 2.4590181774083500943, 2.4264206455302115930,
00177     2.3954342780074673425, 2.3658713701139875435, 2.3375752413355307354, 2.3104136836950021558,
00178     2.2842740596736568056, 2.2590595738653295251, 2.2346863955870569803, 2.2110814088747278106,
00179     2.1881804320720206093, 2.1659267937448407377, 2.1442701823562613518, 2.1231657086697899595,
00180     2.1025731351849988838, 2.0824562379877246441, 2.0627822745039633575, 2.0435215366506694976,
00181     2.0246469733729338782, 2.0061338699589668403, 1.9879595741230607243, 1.9701032608497132242,
00182     1.9525457295488889058, 1.9352692282919002011, 1.9182573008597320303, 1.9014946531003176140,
00183     1.8849670357028692380, 1.8686611409895420085, 1.8525645117230870617, 1.8366654602533840447,
00184     1.8209529965910050740, 1.8054167642140487420, 1.7900469825946189862, 1.7748343955807692457,
00185     1.7597702248942318749, 1.7448461281083765085, 1.7300541605582435350, 1.7153867407081165482,
00186     1.7008366185643009437, 1.6863968467734863258, 1.6720607540918522072, 1.6578219209482075462,
00187     1.6436741568569826489, 1.6296114794646783962, 1.6156280950371329644, 1.6017183802152770587,
00188     1.5878768648844007019, 1.5740982160167497219, 1.5603772223598406870, 1.5467087798535034608,
00189     1.5330878776675560787, 1.5195095847593707806, 1.5059690368565502602, 1.4924614237746154081,
00190     1.4789819769830978546, 1.4655259573357946276, 1.4520886428822164926, 1.4386653166774613138,
00191     1.4252512545068615734, 1.4118417124397602509, 1.3984319141236063517, 1.3850170377251486449,
00192     1.3715922024197322698, 1.3581524543224228739, 1.3446927517457130432, 1.3312079496576765017,
00193     1.3176927832013429910, 1.3041418501204215390, 1.2905495919178731508, 1.2769102735516997175,
00194     1.2632179614460282310, 1.2494664995643337480, 1.2356494832544811749, 1.2217602305309625678,
00195     1.2077917504067576028, 1.1937367078237721994, 1.1795873846544607035, 1.1653356361550469083,
00196     1.1509728421389760651, 1.1364898520030755352, 1.1218769225722540661, 1.1071236475235353980,
00197     1.0922188768965537614, 1.0771506248819376573, 1.0619059636836193998, 1.0464709007525802629,
00198     1.0308302360564555907, 1.0149673952392994716, 0.99886423348064351303, 0.98250080350276038481,
00199     0.96585507938813059489, 0.94890262549791195381, 0.93161619660135381056, 0.91396525100880177644,
00200     0.89591535256623852894, 0.87742742909771569142, 0.85845684317805086354, 0.83895221428120745572,
00201     0.81885390668331772331, 0.79809206062627480454, 0.77658398787614838598, 0.75423066443451007146,
00202     0.73091191062188128150, 0.70647961131360803456, 0.68074791864590421664, 0.65347863871504238702,
00203     0.62435859730908822111, 0.59296294244197797913, 0.55869217837551797140, 0.52065603872514491759,
00204     0.47743783725378787681, 0.42654798630330512490, 0.36287143102841830424, 0.27232086470466385065,
00205     0
00206 };
00207 
00208 template<class RealType>
00209 const RealType normal_table<RealType>::table_y[129] = {
00210     0, 0.0026696290839025035092, 0.0055489952208164705392, 0.0086244844129304709682,
00211     0.011839478657982313715, 0.015167298010672042468, 0.018592102737165812650, 0.022103304616111592615,
00212     0.025693291936149616572, 0.029356317440253829618, 0.033087886146505155566, 0.036884388786968774128,
00213     0.040742868074790604632, 0.044660862200872429800, 0.048636295860284051878, 0.052667401903503169793,
00214     0.056752663481538584188, 0.060890770348566375972, 0.065080585213631873753, 0.069321117394180252601,
00215     0.073611501884754893389, 0.077950982514654714188, 0.082338898242957408243, 0.086774671895542968998,
00216     0.091257800827634710201, 0.09578784912257815216, 0.10036444102954554013, 0.10498725541035453978,
00217     0.10965602101581776100, 0.11437051244988827452, 0.11913054670871858767, 0.12393598020398174246,
00218     0.12878670619710396109, 0.13368265258464764118, 0.13862377998585103702, 0.14361008009193299469,
00219     0.14864157424369696566, 0.15371831220958657066, 0.15884037114093507813, 0.16400785468492774791,
00220     0.16922089223892475176, 0.17447963833240232295, 0.17978427212496211424, 0.18513499701071343216,
00221     0.19053204032091372112, 0.19597565311811041399, 0.20146611007620324118, 0.20700370944187380064,
00222     0.21258877307373610060, 0.21822164655637059599, 0.22390269938713388747, 0.22963232523430270355,
00223     0.23541094226572765600, 0.24123899354775131610, 0.24711694751469673582, 0.25304529850976585934,
00224     0.25902456739871074263, 0.26505530225816194029, 0.27113807914102527343, 0.27727350292189771153,
00225     0.28346220822601251779, 0.28970486044581049771, 0.29600215684985583659, 0.30235482778947976274,
00226     0.30876363800925192282, 0.31522938806815752222, 0.32175291587920862031, 0.32833509837615239609,
00227     0.33497685331697116147, 0.34167914123501368412, 0.34844296754987246935, 0.35526938485154714435,
00228     0.36215949537303321162, 0.36911445366827513952, 0.37613546951445442947, 0.38322381105988364587,
00229     0.39038080824138948916, 0.39760785649804255208, 0.40490642081148835099, 0.41227804010702462062,
00230     0.41972433205403823467, 0.42724699830956239880, 0.43484783025466189638, 0.44252871528024661483,
00231     0.45029164368692696086, 0.45813871627287196483, 0.46607215269457097924, 0.47409430069824960453,
00232     0.48220764633483869062, 0.49041482528932163741, 0.49871863547658432422, 0.50712205108130458951,
00233     0.51562823824987205196, 0.52424057267899279809, 0.53296265938998758838, 0.54179835503172412311,
00234     0.55075179312105527738, 0.55982741271069481791, 0.56902999107472161225, 0.57836468112670231279,
00235     0.58783705444182052571, 0.59745315095181228217, 0.60721953663260488551, 0.61714337082656248870,
00236     0.62723248525781456578, 0.63749547734314487428, 0.64794182111855080873, 0.65858200005865368016,
00237     0.66942766735770616891, 0.68049184100641433355, 0.69178914344603585279, 0.70333609902581741633,
00238     0.71515150742047704368, 0.72725691835450587793, 0.73967724368333814856, 0.75244155918570380145,
00239     0.76558417390923599480, 0.77914608594170316563, 0.79317701178385921053, 0.80773829469612111340,
00240     0.82290721139526200050, 0.83878360531064722379, 0.85550060788506428418, 0.87324304892685358879,
00241     0.89228165080230272301, 0.91304364799203805999, 0.93628268170837107547, 0.96359969315576759960,
00242     1
00243 };
00244 
00245 template<class Engine>
00246 inline typename boost::make_unsigned<typename Engine::result_type>::type
00247 generate_one_digit(Engine& eng, std::size_t bits)
00248 {
00249     typedef typename Engine::result_type base_result;
00250     typedef typename boost::make_unsigned<base_result>::type base_unsigned;
00251 
00252     base_unsigned range =
00253         detail::subtract<base_result>()((eng.max)(), (eng.min)());
00254     base_unsigned y0_mask = (base_unsigned(2) << (bits - 1)) - 1;
00255     base_unsigned y0 = (range + 1) & ~y0_mask;
00256     base_unsigned u;
00257     do {
00258         u = detail::subtract<base_result>()(eng(), (eng.min)());
00259     } while(y0 != 0 && u > base_unsigned(y0 - 1));
00260     return u & y0_mask;
00261 }
00262 
00263 template<class RealType, std::size_t w, class Engine>
00264 std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::true_)
00265 {
00266     typedef typename Engine::result_type base_result;
00267     typedef typename boost::make_unsigned<base_result>::type base_unsigned;
00268 
00269     base_unsigned range =
00270         detail::subtract<base_result>()((eng.max)(), (eng.min)());
00271 
00272     std::size_t m =
00273         (range == (std::numeric_limits<base_unsigned>::max)()) ?
00274             std::numeric_limits<base_unsigned>::digits :
00275 #if BOOST_VERSION < 104700
00276             // Just in the boost namespace
00277             integer_log2(range + 1);
00278 #else
00279             // In the detail namespace
00280             detail::integer_log2(range + 1);
00281 #endif
00282 
00283     int bucket = 0;
00284     // process as many full digits as possible into the int part
00285     for(std::size_t i = 0; i < w/m; ++i) {
00286 #define COVERAGE_IGNORE
00287         base_unsigned u = generate_one_digit(eng, m);
00288         bucket = (bucket << m) | u;
00289 #undef COVERAGE_IGNORE
00290     }
00291     RealType r;
00292 
00293     const std::size_t digits = std::numeric_limits<RealType>::digits;
00294     {
00295         base_unsigned u = generate_one_digit(eng, m);
00296         base_unsigned mask = (base_unsigned(1) << (w%m)) - 1;
00297         bucket = (bucket << (w%m)) | (mask & u);
00298         const RealType mult = RealType(1)/RealType(base_unsigned(1) << (m - w%m));
00299         // zero out unused bits
00300         if (m - w%m > digits) {
00301 #define COVERAGE_IGNORE
00302             u &= ~(base_unsigned(1) << (m - digits));
00303 #undef COVERAGE_IGNORE
00304         }
00305         r = RealType(u >> (w%m)) * mult;
00306     }
00307     for(std::size_t i = m - w%m; i + m < digits; ++i) {
00308 #define COVERAGE_IGNORE
00309         base_unsigned u = generate_one_digit(eng, m);
00310         r += u;
00311         r *= RealType(0.5)/RealType(base_unsigned(1) << (m - 1));
00312 #undef COVERAGE_IGNORE
00313     }
00314     if (m - w%m < digits)
00315     {
00316         const std::size_t remaining = (digits - m + w%m) % m;
00317         base_unsigned u = generate_one_digit(eng, m);
00318         r += u & ((base_unsigned(2) << (remaining - 1)) - 1);
00319         const RealType mult = RealType(0.5)/RealType(base_unsigned(1) << (remaining - 1));
00320         r *= mult;
00321     }
00322     return std::make_pair(r, bucket);
00323 }
00324 
00325 template<class RealType, std::size_t w, class Engine>
00326 inline std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::false_)
00327 {
00328 #if BOOST_VERSION < 104700
00329     int bucket = uniform_int<>(0, (1 << w) - 1)(eng);
00330 #else
00331     int bucket = uniform_int_distribution<>(0, (1 << w) - 1)(eng);
00332 #endif
00333     RealType r = uniform_01<RealType>()(eng);
00334     return std::make_pair(r, bucket);
00335 }
00336 
00337 template<class RealType, std::size_t w, class Engine>
00338 inline std::pair<RealType, int> generate_int_float_pair(Engine& eng)
00339 {
00340     typedef typename Engine::result_type base_result;
00341     return generate_int_float_pair<RealType, w>(eng,
00342         boost::is_integral<base_result>());
00343 }
00344 
00345 template<class RealType = double>
00346 struct unit_normal_distribution
00347 {
00348     template<class Engine>
00349     RealType operator()(Engine& eng) {
00350         const double * const table_x = normal_table<double>::table_x;
00351         const double * const table_y = normal_table<double>::table_y;
00352         for(;;) {
00353             std::pair<RealType, int> vals = generate_int_float_pair<RealType, 8>(eng);
00354             int i = vals.second;
00355             int sign = (i & 1) * 2 - 1;
00356             i = i >> 1;
00357             RealType x = vals.first * RealType(table_x[i]);
00358             if(x < table_x[i + 1]) return x * sign;
00359             if(i == 0) return generate_tail(eng) * sign;
00360             RealType y = RealType(table_y[i]) + uniform_01<RealType>()(eng) * RealType(table_y[i + 1] - table_y[i]);
00361             if (y < f(x)) return x * sign;
00362         }
00363     }
00364     static RealType f(RealType x) {
00365         using std::exp;
00366         return exp(-x*x/2);
00367     }
00368     template<class Engine>
00369     RealType generate_tail(Engine& eng) {
00370         boost::exponential_distribution<RealType> exponential;
00371         boost::variate_generator<Engine& , boost::exponential_distribution<RealType> > var_exponential(eng, exponential);
00372         const RealType tail_start = RealType(normal_table<double>::table_x[1]);
00373 #define COVERAGE_IGNORE
00374         for(;;) {
00375 #undef COVERAGE_IGNORE
00376             RealType x = var_exponential()/tail_start;
00377             RealType y = var_exponential();
00378             if(2*y > x*x) return x + tail_start;
00379         }
00380     }
00381 };
00382 
00383 }
00384 
00385 // deterministic Box-Muller method, uses trigonometric functions
00386 
00396 template<class RealType = double>
00397 class normal_distribution_v156
00398 {
00399 public:
00400     typedef RealType input_type;
00401     typedef RealType result_type;
00402 
00403     class param_type {
00404     public:
00405         typedef normal_distribution_v156 distribution_type;
00406 
00413         explicit param_type(RealType mean_arg = RealType(0.0),
00414                             RealType sigma_arg = RealType(1.0))
00415           : _mean(mean_arg),
00416             _sigma(sigma_arg)
00417         {}
00418 
00420         RealType mean() const { return _mean; }
00421 
00423         RealType sigma() const { return _sigma; }
00424 
00426         BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
00427         { os << parm._mean << " " << parm._sigma ; return os; }
00428 
00430         BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
00431         { is >> parm._mean >> std::ws >> parm._sigma; return is; }
00432 
00434         BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
00435         { return lhs._mean == rhs._mean && lhs._sigma == rhs._sigma; }
00436 
00438         BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
00439 
00440     private:
00441         RealType _mean;
00442         RealType _sigma;
00443     };
00444 
00451     explicit normal_distribution_v156(boost::mt19937& engine_arg,
00452                                       const RealType& mean_arg = RealType(0.0),
00453                                       const RealType& sigma_arg = RealType(1.0)
00454                                       )
00455       : _mean(mean_arg), _sigma(sigma_arg), _engine(engine_arg)
00456     {
00457         BOOST_ASSERT(_sigma >= RealType(0));
00458     }
00459 
00463     explicit normal_distribution_v156(const param_type& parm)
00464       : _mean(parm.mean()), _sigma(parm.sigma())
00465     {}
00466 
00468     RealType mean() const { return _mean; }
00470     RealType sigma() const { return _sigma; }
00471 
00473     RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
00474     { return -std::numeric_limits<RealType>::infinity(); }
00476     RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
00477     { return std::numeric_limits<RealType>::infinity(); }
00478 
00480     param_type param() const { return param_type(_mean, _sigma); }
00482     void param(const param_type& parm)
00483     {
00484         _mean = parm.mean();
00485         _sigma = parm.sigma();
00486     }
00487 
00492     void reset() { }
00493 
00495     template<class Engine>
00496     result_type operator()(Engine& eng)
00497     {
00498         detail::unit_normal_distribution<RealType> impl;
00499 #if BOOST_VERSION < 104700
00500         return impl(_engine) * _sigma + _mean;
00501 #else
00502         return impl(eng) * _sigma + _mean;
00503 #endif
00504     }
00505 
00507     template<class URNG>
00508     result_type operator()(URNG& urng, const param_type& parm)
00509     {
00510         return normal_distribution_v156(parm)(urng);
00511     }
00512 
00514     BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, normal_distribution_v156, nd)
00515     {
00516         os << nd._mean << " " << nd._sigma;
00517         return os;
00518     }
00519 
00521     BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, normal_distribution_v156, nd)
00522     {
00523         is >> std::ws >> nd._mean >> std::ws >> nd._sigma;
00524         return is;
00525     }
00526 
00531     BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(normal_distribution_v156, lhs, rhs)
00532     {
00533         return lhs._mean == rhs._mean && lhs._sigma == rhs._sigma;
00534     }
00535 
00540     BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(normal_distribution_v156)
00541 
00542 private:
00543     RealType _mean, _sigma;
00544     boost::mt19937& _engine;
00545 
00546 };
00547 
00548 } // namespace random
00549 
00550 } // namespace boost
00551 
00552 #endif // BOOST_156_RANDOM_NORMAL_DISTRIBUTION_HPP

Generated by  doxygen 1.6.2