File indexing completed on 2025-01-18 09:27:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_
0016 #define ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_
0017
0018 #include <cassert>
0019 #include <cmath>
0020 #include <istream>
0021 #include <limits>
0022 #include <type_traits>
0023
0024 #include "absl/meta/type_traits.h"
0025 #include "absl/random/internal/fast_uniform_bits.h"
0026 #include "absl/random/internal/generate_real.h"
0027 #include "absl/random/internal/iostream_state_saver.h"
0028
0029 namespace absl {
0030 ABSL_NAMESPACE_BEGIN
0031
0032
0033
0034
0035 template <typename RealType = double>
0036 class exponential_distribution {
0037 public:
0038 using result_type = RealType;
0039
0040 class param_type {
0041 public:
0042 using distribution_type = exponential_distribution;
0043
0044 explicit param_type(result_type lambda = 1) : lambda_(lambda) {
0045 assert(lambda > 0);
0046 neg_inv_lambda_ = -result_type(1) / lambda_;
0047 }
0048
0049 result_type lambda() const { return lambda_; }
0050
0051 friend bool operator==(const param_type& a, const param_type& b) {
0052 return a.lambda_ == b.lambda_;
0053 }
0054
0055 friend bool operator!=(const param_type& a, const param_type& b) {
0056 return !(a == b);
0057 }
0058
0059 private:
0060 friend class exponential_distribution;
0061
0062 result_type lambda_;
0063 result_type neg_inv_lambda_;
0064
0065 static_assert(
0066 std::is_floating_point<RealType>::value,
0067 "Class-template absl::exponential_distribution<> must be parameterized "
0068 "using a floating-point type.");
0069 };
0070
0071 exponential_distribution() : exponential_distribution(1) {}
0072
0073 explicit exponential_distribution(result_type lambda) : param_(lambda) {}
0074
0075 explicit exponential_distribution(const param_type& p) : param_(p) {}
0076
0077 void reset() {}
0078
0079
0080 template <typename URBG>
0081 result_type operator()(URBG& g) {
0082 return (*this)(g, param_);
0083 }
0084
0085 template <typename URBG>
0086 result_type operator()(URBG& g,
0087 const param_type& p);
0088
0089 param_type param() const { return param_; }
0090 void param(const param_type& p) { param_ = p; }
0091
0092 result_type(min)() const { return 0; }
0093 result_type(max)() const {
0094 return std::numeric_limits<result_type>::infinity();
0095 }
0096
0097 result_type lambda() const { return param_.lambda(); }
0098
0099 friend bool operator==(const exponential_distribution& a,
0100 const exponential_distribution& b) {
0101 return a.param_ == b.param_;
0102 }
0103 friend bool operator!=(const exponential_distribution& a,
0104 const exponential_distribution& b) {
0105 return a.param_ != b.param_;
0106 }
0107
0108 private:
0109 param_type param_;
0110 random_internal::FastUniformBits<uint64_t> fast_u64_;
0111 };
0112
0113
0114
0115
0116
0117 template <typename RealType>
0118 template <typename URBG>
0119 typename exponential_distribution<RealType>::result_type
0120 exponential_distribution<RealType>::operator()(
0121 URBG& g,
0122 const param_type& p) {
0123 using random_internal::GenerateNegativeTag;
0124 using random_internal::GenerateRealFromBits;
0125 using real_type =
0126 absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
0127
0128 const result_type u = GenerateRealFromBits<real_type, GenerateNegativeTag,
0129 false>(fast_u64_(g));
0130
0131
0132
0133 return p.neg_inv_lambda_ * std::log1p(u);
0134 }
0135
0136 template <typename CharT, typename Traits, typename RealType>
0137 std::basic_ostream<CharT, Traits>& operator<<(
0138 std::basic_ostream<CharT, Traits>& os,
0139 const exponential_distribution<RealType>& x) {
0140 auto saver = random_internal::make_ostream_state_saver(os);
0141 os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);
0142 os << x.lambda();
0143 return os;
0144 }
0145
0146 template <typename CharT, typename Traits, typename RealType>
0147 std::basic_istream<CharT, Traits>& operator>>(
0148 std::basic_istream<CharT, Traits>& is,
0149 exponential_distribution<RealType>& x) {
0150 using result_type = typename exponential_distribution<RealType>::result_type;
0151 using param_type = typename exponential_distribution<RealType>::param_type;
0152 result_type lambda;
0153
0154 auto saver = random_internal::make_istream_state_saver(is);
0155 lambda = random_internal::read_floating_point<result_type>(is);
0156 if (!is.fail()) {
0157 x.param(param_type(lambda));
0158 }
0159 return is;
0160 }
0161
0162 ABSL_NAMESPACE_END
0163 }
0164
0165 #endif