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