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