xref: /freebsd/contrib/llvm-project/libcxx/include/__random/normal_distribution.h (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef _LIBCPP___RANDOM_NORMAL_DISTRIBUTION_H
10 #define _LIBCPP___RANDOM_NORMAL_DISTRIBUTION_H
11 
12 #include <__config>
13 #include <__random/uniform_real_distribution.h>
14 #include <cmath>
15 #include <iosfwd>
16 #include <limits>
17 
18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19 #pragma GCC system_header
20 #endif
21 
22 _LIBCPP_PUSH_MACROS
23 #include <__undef_macros>
24 
25 _LIBCPP_BEGIN_NAMESPACE_STD
26 
27 template<class _RealType = double>
28 class _LIBCPP_TEMPLATE_VIS normal_distribution
29 {
30 public:
31     // types
32     typedef _RealType result_type;
33 
34     class _LIBCPP_TEMPLATE_VIS param_type
35     {
36         result_type __mean_;
37         result_type __stddev_;
38     public:
39         typedef normal_distribution distribution_type;
40 
41         _LIBCPP_INLINE_VISIBILITY
42         explicit param_type(result_type __mean = 0, result_type __stddev = 1)
43             : __mean_(__mean), __stddev_(__stddev) {}
44 
45         _LIBCPP_INLINE_VISIBILITY
46         result_type mean() const {return __mean_;}
47         _LIBCPP_INLINE_VISIBILITY
48         result_type stddev() const {return __stddev_;}
49 
50         friend _LIBCPP_INLINE_VISIBILITY
51             bool operator==(const param_type& __x, const param_type& __y)
52             {return __x.__mean_ == __y.__mean_ && __x.__stddev_ == __y.__stddev_;}
53         friend _LIBCPP_INLINE_VISIBILITY
54             bool operator!=(const param_type& __x, const param_type& __y)
55             {return !(__x == __y);}
56     };
57 
58 private:
59     param_type __p_;
60     result_type _V_;
61     bool _V_hot_;
62 
63 public:
64     // constructors and reset functions
65 #ifndef _LIBCPP_CXX03_LANG
66     _LIBCPP_INLINE_VISIBILITY
67     normal_distribution() : normal_distribution(0) {}
68     _LIBCPP_INLINE_VISIBILITY
69     explicit normal_distribution(result_type __mean, result_type __stddev = 1)
70         : __p_(param_type(__mean, __stddev)), _V_hot_(false) {}
71 #else
72     _LIBCPP_INLINE_VISIBILITY
73     explicit normal_distribution(result_type __mean = 0,
74                                  result_type __stddev = 1)
75         : __p_(param_type(__mean, __stddev)), _V_hot_(false) {}
76 #endif
77     _LIBCPP_INLINE_VISIBILITY
78     explicit normal_distribution(const param_type& __p)
79         : __p_(__p), _V_hot_(false) {}
80     _LIBCPP_INLINE_VISIBILITY
81     void reset() {_V_hot_ = false;}
82 
83     // generating functions
84     template<class _URNG>
85         _LIBCPP_INLINE_VISIBILITY
86         result_type operator()(_URNG& __g)
87         {return (*this)(__g, __p_);}
88     template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p);
89 
90     // property functions
91     _LIBCPP_INLINE_VISIBILITY
92     result_type mean() const {return __p_.mean();}
93     _LIBCPP_INLINE_VISIBILITY
94     result_type stddev() const {return __p_.stddev();}
95 
96     _LIBCPP_INLINE_VISIBILITY
97     param_type param() const {return __p_;}
98     _LIBCPP_INLINE_VISIBILITY
99     void param(const param_type& __p) {__p_ = __p;}
100 
101     _LIBCPP_INLINE_VISIBILITY
102     result_type min() const {return -numeric_limits<result_type>::infinity();}
103     _LIBCPP_INLINE_VISIBILITY
104     result_type max() const {return numeric_limits<result_type>::infinity();}
105 
106     friend _LIBCPP_INLINE_VISIBILITY
107         bool operator==(const normal_distribution& __x,
108                         const normal_distribution& __y)
109         {return __x.__p_ == __y.__p_ && __x._V_hot_ == __y._V_hot_ &&
110                 (!__x._V_hot_ || __x._V_ == __y._V_);}
111     friend _LIBCPP_INLINE_VISIBILITY
112         bool operator!=(const normal_distribution& __x,
113                         const normal_distribution& __y)
114         {return !(__x == __y);}
115 
116     template <class _CharT, class _Traits, class _RT>
117     friend
118     basic_ostream<_CharT, _Traits>&
119     operator<<(basic_ostream<_CharT, _Traits>& __os,
120                const normal_distribution<_RT>& __x);
121 
122     template <class _CharT, class _Traits, class _RT>
123     friend
124     basic_istream<_CharT, _Traits>&
125     operator>>(basic_istream<_CharT, _Traits>& __is,
126                normal_distribution<_RT>& __x);
127 };
128 
129 template <class _RealType>
130 template<class _URNG>
131 _RealType
132 normal_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p)
133 {
134     result_type _Up;
135     if (_V_hot_)
136     {
137         _V_hot_ = false;
138         _Up = _V_;
139     }
140     else
141     {
142         uniform_real_distribution<result_type> _Uni(-1, 1);
143         result_type __u;
144         result_type __v;
145         result_type __s;
146         do
147         {
148             __u = _Uni(__g);
149             __v = _Uni(__g);
150             __s = __u * __u + __v * __v;
151         } while (__s > 1 || __s == 0);
152         result_type _Fp = _VSTD::sqrt(-2 * _VSTD::log(__s) / __s);
153         _V_ = __v * _Fp;
154         _V_hot_ = true;
155         _Up = __u * _Fp;
156     }
157     return _Up * __p.stddev() + __p.mean();
158 }
159 
160 template <class _CharT, class _Traits, class _RT>
161 basic_ostream<_CharT, _Traits>&
162 operator<<(basic_ostream<_CharT, _Traits>& __os,
163            const normal_distribution<_RT>& __x)
164 {
165     __save_flags<_CharT, _Traits> __lx(__os);
166     typedef basic_ostream<_CharT, _Traits> _OStream;
167     __os.flags(_OStream::dec | _OStream::left | _OStream::fixed |
168                _OStream::scientific);
169     _CharT __sp = __os.widen(' ');
170     __os.fill(__sp);
171     __os << __x.mean() << __sp << __x.stddev() << __sp << __x._V_hot_;
172     if (__x._V_hot_)
173         __os << __sp << __x._V_;
174     return __os;
175 }
176 
177 template <class _CharT, class _Traits, class _RT>
178 basic_istream<_CharT, _Traits>&
179 operator>>(basic_istream<_CharT, _Traits>& __is,
180            normal_distribution<_RT>& __x)
181 {
182     typedef normal_distribution<_RT> _Eng;
183     typedef typename _Eng::result_type result_type;
184     typedef typename _Eng::param_type param_type;
185     __save_flags<_CharT, _Traits> __lx(__is);
186     typedef basic_istream<_CharT, _Traits> _Istream;
187     __is.flags(_Istream::dec | _Istream::skipws);
188     result_type __mean;
189     result_type __stddev;
190     result_type _Vp = 0;
191     bool _V_hot = false;
192     __is >> __mean >> __stddev >> _V_hot;
193     if (_V_hot)
194         __is >> _Vp;
195     if (!__is.fail())
196     {
197         __x.param(param_type(__mean, __stddev));
198         __x._V_hot_ = _V_hot;
199         __x._V_ = _Vp;
200     }
201     return __is;
202 }
203 
204 _LIBCPP_END_NAMESPACE_STD
205 
206 _LIBCPP_POP_MACROS
207 
208 #endif // _LIBCPP___RANDOM_NORMAL_DISTRIBUTION_H
209