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) 44 : __mean_(__mean), __stddev_(__stddev) {} 45 46 _LIBCPP_INLINE_VISIBILITY 47 result_type mean() const {return __mean_;} 48 _LIBCPP_INLINE_VISIBILITY 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 68 normal_distribution() : normal_distribution(0) {} 69 _LIBCPP_INLINE_VISIBILITY 70 explicit normal_distribution(result_type __mean, result_type __stddev = 1) 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 79 explicit normal_distribution(const param_type& __p) 80 : __p_(__p), _V_hot_(false) {} 81 _LIBCPP_INLINE_VISIBILITY 82 void reset() {_V_hot_ = false;} 83 84 // generating functions 85 template<class _URNG> 86 _LIBCPP_INLINE_VISIBILITY 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 93 result_type mean() const {return __p_.mean();} 94 _LIBCPP_INLINE_VISIBILITY 95 result_type stddev() const {return __p_.stddev();} 96 97 _LIBCPP_INLINE_VISIBILITY 98 param_type param() const {return __p_;} 99 _LIBCPP_INLINE_VISIBILITY 100 void param(const param_type& __p) {__p_ = __p;} 101 102 _LIBCPP_INLINE_VISIBILITY 103 result_type min() const {return -numeric_limits<result_type>::infinity();} 104 _LIBCPP_INLINE_VISIBILITY 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 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 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 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