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_EXPONENTIAL_DISTRIBUTION_H
10 #define _LIBCPP___RANDOM_EXPONENTIAL_DISTRIBUTION_H
11 
12 #include <__config>
13 #include <__random/generate_canonical.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 exponential_distribution
30 {
31 public:
32     // types
33     typedef _RealType result_type;
34 
35     class _LIBCPP_TEMPLATE_VIS param_type
36     {
37         result_type __lambda_;
38     public:
39         typedef exponential_distribution distribution_type;
40 
41         _LIBCPP_INLINE_VISIBILITY
42         explicit param_type(result_type __lambda = 1) : __lambda_(__lambda) {}
43 
44         _LIBCPP_INLINE_VISIBILITY
45         result_type lambda() const {return __lambda_;}
46 
47         friend _LIBCPP_INLINE_VISIBILITY
48             bool operator==(const param_type& __x, const param_type& __y)
49             {return __x.__lambda_ == __y.__lambda_;}
50         friend _LIBCPP_INLINE_VISIBILITY
51             bool operator!=(const param_type& __x, const param_type& __y)
52             {return !(__x == __y);}
53     };
54 
55 private:
56     param_type __p_;
57 
58 public:
59     // constructors and reset functions
60 #ifndef _LIBCPP_CXX03_LANG
61     _LIBCPP_INLINE_VISIBILITY
62     exponential_distribution() : exponential_distribution(1) {}
63     _LIBCPP_INLINE_VISIBILITY
64     explicit exponential_distribution(result_type __lambda)
65         : __p_(param_type(__lambda)) {}
66 #else
67     _LIBCPP_INLINE_VISIBILITY
68     explicit exponential_distribution(result_type __lambda = 1)
69         : __p_(param_type(__lambda)) {}
70 #endif
71     _LIBCPP_INLINE_VISIBILITY
72     explicit exponential_distribution(const param_type& __p) : __p_(__p) {}
73     _LIBCPP_INLINE_VISIBILITY
74     void reset() {}
75 
76     // generating functions
77     template<class _URNG>
78         _LIBCPP_INLINE_VISIBILITY
79         result_type operator()(_URNG& __g)
80         {return (*this)(__g, __p_);}
81     template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p);
82 
83     // property functions
84     _LIBCPP_INLINE_VISIBILITY
85     result_type lambda() const {return __p_.lambda();}
86 
87     _LIBCPP_INLINE_VISIBILITY
88     param_type param() const {return __p_;}
89     _LIBCPP_INLINE_VISIBILITY
90     void param(const param_type& __p) {__p_ = __p;}
91 
92     _LIBCPP_INLINE_VISIBILITY
93     result_type min() const {return 0;}
94     _LIBCPP_INLINE_VISIBILITY
95     result_type max() const {return numeric_limits<result_type>::infinity();}
96 
97     friend _LIBCPP_INLINE_VISIBILITY
98         bool operator==(const exponential_distribution& __x,
99                         const exponential_distribution& __y)
100         {return __x.__p_ == __y.__p_;}
101     friend _LIBCPP_INLINE_VISIBILITY
102         bool operator!=(const exponential_distribution& __x,
103                         const exponential_distribution& __y)
104         {return !(__x == __y);}
105 };
106 
107 template <class _RealType>
108 template<class _URNG>
109 _RealType
110 exponential_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p)
111 {
112     return -_VSTD::log
113                   (
114                       result_type(1) -
115                       _VSTD::generate_canonical<result_type,
116                                        numeric_limits<result_type>::digits>(__g)
117                   )
118                   / __p.lambda();
119 }
120 
121 template <class _CharT, class _Traits, class _RealType>
122 basic_ostream<_CharT, _Traits>&
123 operator<<(basic_ostream<_CharT, _Traits>& __os,
124            const exponential_distribution<_RealType>& __x)
125 {
126     __save_flags<_CharT, _Traits> __lx(__os);
127     typedef basic_ostream<_CharT, _Traits> _OStream;
128     __os.flags(_OStream::dec | _OStream::left | _OStream::fixed |
129                _OStream::scientific);
130     return __os << __x.lambda();
131 }
132 
133 template <class _CharT, class _Traits, class _RealType>
134 basic_istream<_CharT, _Traits>&
135 operator>>(basic_istream<_CharT, _Traits>& __is,
136            exponential_distribution<_RealType>& __x)
137 {
138     typedef exponential_distribution<_RealType> _Eng;
139     typedef typename _Eng::result_type result_type;
140     typedef typename _Eng::param_type param_type;
141     __save_flags<_CharT, _Traits> __lx(__is);
142     typedef basic_istream<_CharT, _Traits> _Istream;
143     __is.flags(_Istream::dec | _Istream::skipws);
144     result_type __lambda;
145     __is >> __lambda;
146     if (!__is.fail())
147         __x.param(param_type(__lambda));
148     return __is;
149 }
150 
151 _LIBCPP_END_NAMESPACE_STD
152 
153 _LIBCPP_POP_MACROS
154 
155 #endif // _LIBCPP___RANDOM_EXPONENTIAL_DISTRIBUTION_H
156