14824e7fdSDimitry Andric //===----------------------------------------------------------------------===// 24824e7fdSDimitry Andric // 34824e7fdSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 44824e7fdSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 54824e7fdSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64824e7fdSDimitry Andric // 74824e7fdSDimitry Andric //===----------------------------------------------------------------------===// 84824e7fdSDimitry Andric 94824e7fdSDimitry Andric #ifndef _LIBCPP___RANDOM_NORMAL_DISTRIBUTION_H 104824e7fdSDimitry Andric #define _LIBCPP___RANDOM_NORMAL_DISTRIBUTION_H 114824e7fdSDimitry Andric 124824e7fdSDimitry Andric #include <__config> 1381ad6265SDimitry Andric #include <__random/is_valid.h> 144824e7fdSDimitry Andric #include <__random/uniform_real_distribution.h> 154824e7fdSDimitry Andric #include <cmath> 164824e7fdSDimitry Andric #include <iosfwd> 174824e7fdSDimitry Andric #include <limits> 184824e7fdSDimitry Andric 194824e7fdSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 204824e7fdSDimitry Andric # pragma GCC system_header 214824e7fdSDimitry Andric #endif 224824e7fdSDimitry Andric 234824e7fdSDimitry Andric _LIBCPP_PUSH_MACROS 244824e7fdSDimitry Andric #include <__undef_macros> 254824e7fdSDimitry Andric 264824e7fdSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 274824e7fdSDimitry Andric 284824e7fdSDimitry Andric template <class _RealType = double> 29*cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS normal_distribution { 305f757f3fSDimitry Andric static_assert(__libcpp_random_is_valid_realtype<_RealType>::value, 315f757f3fSDimitry Andric "RealType must be a supported floating-point type"); 325f757f3fSDimitry Andric 334824e7fdSDimitry Andric public: 344824e7fdSDimitry Andric // types 354824e7fdSDimitry Andric typedef _RealType result_type; 364824e7fdSDimitry Andric 37*cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS param_type { 384824e7fdSDimitry Andric result_type __mean_; 394824e7fdSDimitry Andric result_type __stddev_; 40*cb14a3feSDimitry Andric 414824e7fdSDimitry Andric public: 424824e7fdSDimitry Andric typedef normal_distribution distribution_type; 434824e7fdSDimitry Andric 44*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit param_type(result_type __mean = 0, result_type __stddev = 1) 454824e7fdSDimitry Andric : __mean_(__mean), __stddev_(__stddev) {} 464824e7fdSDimitry Andric 47*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type mean() const { return __mean_; } 48*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type stddev() const { return __stddev_; } 494824e7fdSDimitry Andric 50*cb14a3feSDimitry Andric friend _LIBCPP_HIDE_FROM_ABI bool operator==(const param_type& __x, const param_type& __y) { 51*cb14a3feSDimitry Andric return __x.__mean_ == __y.__mean_ && __x.__stddev_ == __y.__stddev_; 52*cb14a3feSDimitry Andric } 53*cb14a3feSDimitry Andric friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const param_type& __x, const param_type& __y) { return !(__x == __y); } 544824e7fdSDimitry Andric }; 554824e7fdSDimitry Andric 564824e7fdSDimitry Andric private: 574824e7fdSDimitry Andric param_type __p_; 58bdd1243dSDimitry Andric result_type __v_; 59bdd1243dSDimitry Andric bool __v_hot_; 604824e7fdSDimitry Andric 614824e7fdSDimitry Andric public: 624824e7fdSDimitry Andric // constructors and reset functions 634824e7fdSDimitry Andric #ifndef _LIBCPP_CXX03_LANG 64*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI normal_distribution() : normal_distribution(0) {} 65*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit normal_distribution(result_type __mean, result_type __stddev = 1) 66bdd1243dSDimitry Andric : __p_(param_type(__mean, __stddev)), __v_hot_(false) {} 674824e7fdSDimitry Andric #else 68*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit normal_distribution(result_type __mean = 0, result_type __stddev = 1) 69bdd1243dSDimitry Andric : __p_(param_type(__mean, __stddev)), __v_hot_(false) {} 704824e7fdSDimitry Andric #endif 71*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit normal_distribution(const param_type& __p) : __p_(__p), __v_hot_(false) {} 72*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void reset() { __v_hot_ = false; } 734824e7fdSDimitry Andric 744824e7fdSDimitry Andric // generating functions 754824e7fdSDimitry Andric template <class _URNG> 76*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g) { 77*cb14a3feSDimitry Andric return (*this)(__g, __p_); 78*cb14a3feSDimitry Andric } 7906c3fb27SDimitry Andric template <class _URNG> 8006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); 814824e7fdSDimitry Andric 824824e7fdSDimitry Andric // property functions 83*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type mean() const { return __p_.mean(); } 84*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type stddev() const { return __p_.stddev(); } 854824e7fdSDimitry Andric 86*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI param_type param() const { return __p_; } 87*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void param(const param_type& __p) { __p_ = __p; } 884824e7fdSDimitry Andric 89*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type min() const { return -numeric_limits<result_type>::infinity(); } 90*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type max() const { return numeric_limits<result_type>::infinity(); } 914824e7fdSDimitry Andric 92*cb14a3feSDimitry Andric friend _LIBCPP_HIDE_FROM_ABI bool operator==(const normal_distribution& __x, const normal_distribution& __y) { 93*cb14a3feSDimitry Andric return __x.__p_ == __y.__p_ && __x.__v_hot_ == __y.__v_hot_ && (!__x.__v_hot_ || __x.__v_ == __y.__v_); 94*cb14a3feSDimitry Andric } 95*cb14a3feSDimitry Andric friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const normal_distribution& __x, const normal_distribution& __y) { 96*cb14a3feSDimitry Andric return !(__x == __y); 97*cb14a3feSDimitry Andric } 984824e7fdSDimitry Andric 994824e7fdSDimitry Andric template <class _CharT, class _Traits, class _RT> 100*cb14a3feSDimitry Andric friend basic_ostream<_CharT, _Traits>& 101*cb14a3feSDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, const normal_distribution<_RT>& __x); 1024824e7fdSDimitry Andric 1034824e7fdSDimitry Andric template <class _CharT, class _Traits, class _RT> 104*cb14a3feSDimitry Andric friend basic_istream<_CharT, _Traits>& 105*cb14a3feSDimitry Andric operator>>(basic_istream<_CharT, _Traits>& __is, normal_distribution<_RT>& __x); 1064824e7fdSDimitry Andric }; 1074824e7fdSDimitry Andric 1084824e7fdSDimitry Andric template <class _RealType> 1094824e7fdSDimitry Andric template <class _URNG> 110*cb14a3feSDimitry Andric _RealType normal_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p) { 11181ad6265SDimitry Andric static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); 11206c3fb27SDimitry Andric result_type __up; 113*cb14a3feSDimitry Andric if (__v_hot_) { 114bdd1243dSDimitry Andric __v_hot_ = false; 11506c3fb27SDimitry Andric __up = __v_; 116*cb14a3feSDimitry Andric } else { 11706c3fb27SDimitry Andric uniform_real_distribution<result_type> __uni(-1, 1); 1184824e7fdSDimitry Andric result_type __u; 1194824e7fdSDimitry Andric result_type __v; 1204824e7fdSDimitry Andric result_type __s; 121*cb14a3feSDimitry Andric do { 12206c3fb27SDimitry Andric __u = __uni(__g); 12306c3fb27SDimitry Andric __v = __uni(__g); 1244824e7fdSDimitry Andric __s = __u * __u + __v * __v; 1254824e7fdSDimitry Andric } while (__s > 1 || __s == 0); 1265f757f3fSDimitry Andric result_type __fp = std::sqrt(-2 * std::log(__s) / __s); 12706c3fb27SDimitry Andric __v_ = __v * __fp; 128bdd1243dSDimitry Andric __v_hot_ = true; 12906c3fb27SDimitry Andric __up = __u * __fp; 1304824e7fdSDimitry Andric } 13106c3fb27SDimitry Andric return __up * __p.stddev() + __p.mean(); 1324824e7fdSDimitry Andric } 1334824e7fdSDimitry Andric 1344824e7fdSDimitry Andric template <class _CharT, class _Traits, class _RT> 135bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 136*cb14a3feSDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, const normal_distribution<_RT>& __x) { 1374824e7fdSDimitry Andric __save_flags<_CharT, _Traits> __lx(__os); 1384824e7fdSDimitry Andric typedef basic_ostream<_CharT, _Traits> _OStream; 139*cb14a3feSDimitry Andric __os.flags(_OStream::dec | _OStream::left | _OStream::fixed | _OStream::scientific); 1404824e7fdSDimitry Andric _CharT __sp = __os.widen(' '); 1414824e7fdSDimitry Andric __os.fill(__sp); 142bdd1243dSDimitry Andric __os << __x.mean() << __sp << __x.stddev() << __sp << __x.__v_hot_; 143bdd1243dSDimitry Andric if (__x.__v_hot_) 144bdd1243dSDimitry Andric __os << __sp << __x.__v_; 1454824e7fdSDimitry Andric return __os; 1464824e7fdSDimitry Andric } 1474824e7fdSDimitry Andric 1484824e7fdSDimitry Andric template <class _CharT, class _Traits, class _RT> 149bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 150*cb14a3feSDimitry Andric operator>>(basic_istream<_CharT, _Traits>& __is, normal_distribution<_RT>& __x) { 1514824e7fdSDimitry Andric typedef normal_distribution<_RT> _Eng; 1524824e7fdSDimitry Andric typedef typename _Eng::result_type result_type; 1534824e7fdSDimitry Andric typedef typename _Eng::param_type param_type; 1544824e7fdSDimitry Andric __save_flags<_CharT, _Traits> __lx(__is); 1554824e7fdSDimitry Andric typedef basic_istream<_CharT, _Traits> _Istream; 1564824e7fdSDimitry Andric __is.flags(_Istream::dec | _Istream::skipws); 1574824e7fdSDimitry Andric result_type __mean; 1584824e7fdSDimitry Andric result_type __stddev; 15906c3fb27SDimitry Andric result_type __vp = 0; 16006c3fb27SDimitry Andric bool __v_hot = false; 16106c3fb27SDimitry Andric __is >> __mean >> __stddev >> __v_hot; 16206c3fb27SDimitry Andric if (__v_hot) 16306c3fb27SDimitry Andric __is >> __vp; 164*cb14a3feSDimitry Andric if (!__is.fail()) { 1654824e7fdSDimitry Andric __x.param(param_type(__mean, __stddev)); 16606c3fb27SDimitry Andric __x.__v_hot_ = __v_hot; 16706c3fb27SDimitry Andric __x.__v_ = __vp; 1684824e7fdSDimitry Andric } 1694824e7fdSDimitry Andric return __is; 1704824e7fdSDimitry Andric } 1714824e7fdSDimitry Andric 1724824e7fdSDimitry Andric _LIBCPP_END_NAMESPACE_STD 1734824e7fdSDimitry Andric 1744824e7fdSDimitry Andric _LIBCPP_POP_MACROS 1754824e7fdSDimitry Andric 1764824e7fdSDimitry Andric #endif // _LIBCPP___RANDOM_NORMAL_DISTRIBUTION_H 177