Ticket #1437: normal_distribution.hpp

File normal_distribution.hpp, 3.2 KB (added by m.bannerman@…, 15 years ago)

Improved normal_distribution.hpp

Line 
1/* boost random/normal_distribution.hpp header file
2 *
3 * Copyright Jens Maurer 2000-2001
4 * Copyright Marcus Bannerman 2007
5 * Distributed under the Boost Software License, Version 1.0. (See
6 * accompanying file LICENSE_1_0.txt or copy at
7 * http://www.boost.org/LICENSE_1_0.txt)
8 *
9 * See http://www.boost.org for most recent version including documentation.
10 *
11 * $Id: normal_distribution.hpp,v 1.20 2004/07/27 03:43:32 dgregor Exp $
12 *
13 * Revision history
14 * 2001-02-18 moved to individual header files
15 * 2007-11-10 M.B. Changed to the outward cartesian form of the Box-Muller
16 * transform.
17 */
18
19#ifndef BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP
20#define BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP
21
22#include <cmath>
23#include <cassert>
24#include <iostream>
25#include <boost/limits.hpp>
26#include <boost/static_assert.hpp>
27
28namespace boost {
29
30// deterministic polar method, uses trigonometric functions
31template<class RealType = double>
32class normal_distribution
33{
34public:
35 typedef RealType input_type;
36 typedef RealType result_type;
37
38#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300)
39 BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer);
40#endif
41
42 explicit normal_distribution(const result_type& mean = result_type(0),
43 const result_type& sigma = result_type(1))
44 : _mean(mean), _sigma(sigma), _valid(false)
45 {
46 assert(sigma >= result_type(0));
47 }
48
49 // compiler-generated copy constructor is NOT fine, need to purge cache
50 normal_distribution(const normal_distribution& other)
51 : _mean(other._mean), _sigma(other._sigma), _valid(false)
52 {}
53
54 // compiler-generated copy ctor and assignment operator are fine
55
56 RealType mean() const { return _mean; }
57 RealType sigma() const { return _sigma; }
58
59 void reset() { _valid = false; }
60
61 template<class Engine>
62 result_type operator()(Engine& eng)
63 {
64#ifndef BOOST_NO_STDC_NAMESPACE
65 // allow for Koenig lookup
66 using std::sqrt; using std::log;
67#endif
68 if(!_valid) {
69 do
70 {
71 _r1 = 2.0 * eng() - 1.0;
72 _r2 = 2.0 * eng() - 1.0;
73 _sq = _r1 *_r1 + _r2 *_r2;
74 } while ((_sq > 1.0) || (_sq == 0.0));
75
76 _sq = sqrt(-2 * log(1.0-_sq)/_sq);
77 _r1 *= _sq;
78 _r2 *= _sq;
79 _valid = true;
80 } else
81 _valid = false;
82
83 return (_valid ? _r1 : _r2) * _sigma + _mean;
84 }
85
86#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
87 template<class CharT, class Traits>
88 friend std::basic_ostream<CharT,Traits>&
89 operator<<(std::basic_ostream<CharT,Traits>& os, const normal_distribution& nd)
90 {
91 os << nd._mean << " " << nd._sigma << " "
92 << nd._valid << " " << " " << nd._r1 << " "
93 << nd._r2;
94 return os;
95 }
96
97 template<class CharT, class Traits>
98 friend std::basic_istream<CharT,Traits>&
99 operator>>(std::basic_istream<CharT,Traits>& is, normal_distribution& nd)
100 {
101 is >> std::ws >> nd._mean >> std::ws >> nd._sigma
102 >> std::ws >> nd._valid >> std::ws >> nd._r1
103 >> std::ws >> nd._r2;
104 return is;
105 }
106#endif
107private:
108 result_type _mean, _sigma;
109 result_type _r1, _r2, _sq;
110 bool _valid;
111};
112
113} // namespace boost
114
115#endif // BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP