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_NEGATIVE_BINOMIAL_DISTRIBUTION_H 10 #define _LIBCPP___RANDOM_NEGATIVE_BINOMIAL_DISTRIBUTION_H 11 12 #include <__config> 13 #include <__random/bernoulli_distribution.h> 14 #include <__random/gamma_distribution.h> 15 #include <__random/poisson_distribution.h> 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 _IntType = int> 29 class _LIBCPP_TEMPLATE_VIS negative_binomial_distribution 30 { 31 public: 32 // types 33 typedef _IntType result_type; 34 35 class _LIBCPP_TEMPLATE_VIS param_type 36 { 37 result_type __k_; 38 double __p_; 39 public: 40 typedef negative_binomial_distribution distribution_type; 41 42 _LIBCPP_INLINE_VISIBILITY 43 explicit param_type(result_type __k = 1, double __p = 0.5) 44 : __k_(__k), __p_(__p) {} 45 46 _LIBCPP_INLINE_VISIBILITY 47 result_type k() const {return __k_;} 48 _LIBCPP_INLINE_VISIBILITY 49 double p() const {return __p_;} 50 51 friend _LIBCPP_INLINE_VISIBILITY 52 bool operator==(const param_type& __x, const param_type& __y) 53 {return __x.__k_ == __y.__k_ && __x.__p_ == __y.__p_;} 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 62 public: 63 // constructor and reset functions 64 #ifndef _LIBCPP_CXX03_LANG 65 _LIBCPP_INLINE_VISIBILITY 66 negative_binomial_distribution() : negative_binomial_distribution(1) {} 67 _LIBCPP_INLINE_VISIBILITY 68 explicit negative_binomial_distribution(result_type __k, double __p = 0.5) 69 : __p_(__k, __p) {} 70 #else 71 _LIBCPP_INLINE_VISIBILITY 72 explicit negative_binomial_distribution(result_type __k = 1, 73 double __p = 0.5) 74 : __p_(__k, __p) {} 75 #endif 76 _LIBCPP_INLINE_VISIBILITY 77 explicit negative_binomial_distribution(const param_type& __p) : __p_(__p) {} 78 _LIBCPP_INLINE_VISIBILITY 79 void reset() {} 80 81 // generating functions 82 template<class _URNG> 83 _LIBCPP_INLINE_VISIBILITY 84 result_type operator()(_URNG& __g) 85 {return (*this)(__g, __p_);} 86 template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); 87 88 // property functions 89 _LIBCPP_INLINE_VISIBILITY 90 result_type k() const {return __p_.k();} 91 _LIBCPP_INLINE_VISIBILITY 92 double p() const {return __p_.p();} 93 94 _LIBCPP_INLINE_VISIBILITY 95 param_type param() const {return __p_;} 96 _LIBCPP_INLINE_VISIBILITY 97 void param(const param_type& __p) {__p_ = __p;} 98 99 _LIBCPP_INLINE_VISIBILITY 100 result_type min() const {return 0;} 101 _LIBCPP_INLINE_VISIBILITY 102 result_type max() const {return numeric_limits<result_type>::max();} 103 104 friend _LIBCPP_INLINE_VISIBILITY 105 bool operator==(const negative_binomial_distribution& __x, 106 const negative_binomial_distribution& __y) 107 {return __x.__p_ == __y.__p_;} 108 friend _LIBCPP_INLINE_VISIBILITY 109 bool operator!=(const negative_binomial_distribution& __x, 110 const negative_binomial_distribution& __y) 111 {return !(__x == __y);} 112 }; 113 114 template <class _IntType> 115 template<class _URNG> 116 _IntType 117 negative_binomial_distribution<_IntType>::operator()(_URNG& __urng, const param_type& __pr) 118 { 119 result_type __k = __pr.k(); 120 double __p = __pr.p(); 121 if (__k <= 21 * __p) 122 { 123 bernoulli_distribution __gen(__p); 124 result_type __f = 0; 125 result_type __s = 0; 126 while (__s < __k) 127 { 128 if (__gen(__urng)) 129 ++__s; 130 else 131 ++__f; 132 } 133 return __f; 134 } 135 return poisson_distribution<result_type>(gamma_distribution<double> 136 (__k, (1-__p)/__p)(__urng))(__urng); 137 } 138 139 template <class _CharT, class _Traits, class _IntType> 140 basic_ostream<_CharT, _Traits>& 141 operator<<(basic_ostream<_CharT, _Traits>& __os, 142 const negative_binomial_distribution<_IntType>& __x) 143 { 144 __save_flags<_CharT, _Traits> __lx(__os); 145 typedef basic_ostream<_CharT, _Traits> _OStream; 146 __os.flags(_OStream::dec | _OStream::left | _OStream::fixed | 147 _OStream::scientific); 148 _CharT __sp = __os.widen(' '); 149 __os.fill(__sp); 150 return __os << __x.k() << __sp << __x.p(); 151 } 152 153 template <class _CharT, class _Traits, class _IntType> 154 basic_istream<_CharT, _Traits>& 155 operator>>(basic_istream<_CharT, _Traits>& __is, 156 negative_binomial_distribution<_IntType>& __x) 157 { 158 typedef negative_binomial_distribution<_IntType> _Eng; 159 typedef typename _Eng::result_type result_type; 160 typedef typename _Eng::param_type param_type; 161 __save_flags<_CharT, _Traits> __lx(__is); 162 typedef basic_istream<_CharT, _Traits> _Istream; 163 __is.flags(_Istream::dec | _Istream::skipws); 164 result_type __k; 165 double __p; 166 __is >> __k >> __p; 167 if (!__is.fail()) 168 __x.param(param_type(__k, __p)); 169 return __is; 170 } 171 172 _LIBCPP_END_NAMESPACE_STD 173 174 _LIBCPP_POP_MACROS 175 176 #endif // _LIBCPP___RANDOM_NEGATIVE_BINOMIAL_DISTRIBUTION_H 177