bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef ABSL_RANDOM_POISSON_DISTRIBUTION_H_
16 #define ABSL_RANDOM_POISSON_DISTRIBUTION_H_
17 
18 #include <cassert>
19 #include <cmath>
20 #include <istream>
21 #include <limits>
22 #include <ostream>
23 #include <type_traits>
24 
25 #include "absl/random/internal/fast_uniform_bits.h"
26 #include "absl/random/internal/fastmath.h"
27 #include "absl/random/internal/generate_real.h"
28 #include "absl/random/internal/iostream_state_saver.h"
29 
30 namespace absl {
32 
33 // absl::poisson_distribution:
34 // Generates discrete variates conforming to a Poisson distribution.
35 // p(n) = (mean^n / n!) exp(-mean)
36 //
37 // Depending on the parameter, the distribution selects one of the following
38 // algorithms:
39 // * The standard algorithm, attributed to Knuth, extended using a split method
40 // for larger values
41 // * The "Ratio of Uniforms as a convenient method for sampling from classical
42 // discrete distributions", Stadlober, 1989.
43 // http://www.sciencedirect.com/science/article/pii/0377042790903495
44 //
45 // NOTE: param_type.mean() is a double, which permits values larger than
46 // poisson_distribution<IntType>::max(), however this should be avoided and
47 // the distribution results are limited to the max() value.
48 //
49 // The goals of this implementation are to provide good performance while still
50 // beig thread-safe: This limits the implementation to not using lgamma provided
51 // by <math.h>.
52 //
53 template <typename IntType = int>
54 class poisson_distribution {
55  public:
56  using result_type = IntType;
57 
58  class param_type {
59  public:
61  explicit param_type(double mean = 1.0);
62 
63  double mean() const { return mean_; }
64 
65  friend bool operator==(const param_type& a, const param_type& b) {
66  return a.mean_ == b.mean_;
67  }
68 
69  friend bool operator!=(const param_type& a, const param_type& b) {
70  return !(a == b);
71  }
72 
73  private:
74  friend class poisson_distribution;
75 
76  double mean_;
77  double emu_; // e ^ -mean_
78  double lmu_; // ln(mean_)
79  double s_;
80  double log_k_;
81  int split_;
82 
84  "Class-template absl::poisson_distribution<> must be "
85  "parameterized using an integral type.");
86  };
87 
89 
90  explicit poisson_distribution(double mean) : param_(mean) {}
91 
92  explicit poisson_distribution(const param_type& p) : param_(p) {}
93 
94  void reset() {}
95 
96  // generating functions
97  template <typename URBG>
98  result_type operator()(URBG& g) { // NOLINT(runtime/references)
99  return (*this)(g, param_);
100  }
101 
102  template <typename URBG>
103  result_type operator()(URBG& g, // NOLINT(runtime/references)
104  const param_type& p);
105 
106  param_type param() const { return param_; }
107  void param(const param_type& p) { param_ = p; }
108 
109  result_type(min)() const { return 0; }
111 
112  double mean() const { return param_.mean(); }
113 
114  friend bool operator==(const poisson_distribution& a,
115  const poisson_distribution& b) {
116  return a.param_ == b.param_;
117  }
118  friend bool operator!=(const poisson_distribution& a,
119  const poisson_distribution& b) {
120  return a.param_ != b.param_;
121  }
122 
123  private:
124  param_type param_;
126 };
127 
128 // -----------------------------------------------------------------------------
129 // Implementation details follow
130 // -----------------------------------------------------------------------------
131 
132 template <typename IntType>
134  : mean_(mean), split_(0) {
135  assert(mean >= 0);
137  // As a defensive measure, avoid large values of the mean. The rejection
138  // algorithm used does not support very large values well. It my be worth
139  // changing algorithms to better deal with these cases.
140  assert(mean <= 1e10);
141  if (mean_ < 10) {
142  // For small lambda, use the knuth method.
143  split_ = 1;
144  emu_ = std::exp(-mean_);
145  } else if (mean_ <= 50) {
146  // Use split-knuth method.
147  split_ = 1 + static_cast<int>(mean_ / 10.0);
148  emu_ = std::exp(-mean_ / static_cast<double>(split_));
149  } else {
150  // Use ratio of uniforms method.
151  constexpr double k2E = 0.7357588823428846;
152  constexpr double kSA = 0.4494580810294493;
153 
154  lmu_ = std::log(mean_);
155  double a = mean_ + 0.5;
156  s_ = kSA + std::sqrt(k2E * a);
157  const double mode = std::ceil(mean_) - 1;
159  }
160 }
161 
162 template <typename IntType>
163 template <typename URBG>
166  URBG& g, // NOLINT(runtime/references)
167  const param_type& p) {
168  using random_internal::GeneratePositiveTag;
170  using random_internal::GenerateSignedTag;
171 
172  if (p.split_ != 0) {
173  // Use Knuth's algorithm with range splitting to avoid floating-point
174  // errors. Knuth's algorithm is: Ui is a sequence of uniform variates on
175  // (0,1); return the number of variates required for product(Ui) <
176  // exp(-lambda).
177  //
178  // The expected number of variates required for Knuth's method can be
179  // computed as follows:
180  // The expected value of U is 0.5, so solving for 0.5^n < exp(-lambda) gives
181  // the expected number of uniform variates
182  // required for a given lambda, which is:
183  // lambda = [2, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17]
184  // n = [3, 8, 13, 15, 16, 18, 19, 21, 22, 24, 25]
185  //
186  result_type n = 0;
187  for (int split = p.split_; split > 0; --split) {
188  double r = 1.0;
189  do {
190  r *= GenerateRealFromBits<double, GeneratePositiveTag, true>(
191  fast_u64_(g)); // U(-1, 0)
192  ++n;
193  } while (r > p.emu_);
194  --n;
195  }
196  return n;
197  }
198 
199  // Use ratio of uniforms method.
200  //
201  // Let u ~ Uniform(0, 1), v ~ Uniform(-1, 1),
202  // a = lambda + 1/2,
203  // s = 1.5 - sqrt(3/e) + sqrt(2(lambda + 1/2)/e),
204  // x = s * v/u + a.
205  // P(floor(x) = k | u^2 < f(floor(x))/k), where
206  // f(m) = lambda^m exp(-lambda)/ m!, for 0 <= m, and f(m) = 0 otherwise,
207  // and k = max(f).
208  const double a = p.mean_ + 0.5;
209  for (;;) {
210  const double u = GenerateRealFromBits<double, GeneratePositiveTag, false>(
211  fast_u64_(g)); // U(0, 1)
212  const double v = GenerateRealFromBits<double, GenerateSignedTag, false>(
213  fast_u64_(g)); // U(-1, 1)
214 
215  const double x = std::floor(p.s_ * v / u + a);
216  if (x < 0) continue; // f(negative) = 0
217  const double rhs = x * p.lmu_;
218  // clang-format off
219  double s = (x <= 1.0) ? 0.0
220  : (x == 2.0) ? 0.693147180559945
222  // clang-format on
223  const double lhs = 2.0 * std::log(u) + p.log_k_ + s;
224  if (lhs < rhs) {
225  return x > (max)() ? (max)()
226  : static_cast<result_type>(x); // f(x)/k >= u^2
227  }
228  }
229 }
230 
231 template <typename CharT, typename Traits, typename IntType>
232 std::basic_ostream<CharT, Traits>& operator<<(
233  std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
234  const poisson_distribution<IntType>& x) {
237  os << x.mean();
238  return os;
239 }
240 
241 template <typename CharT, typename Traits, typename IntType>
242 std::basic_istream<CharT, Traits>& operator>>(
243  std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
244  poisson_distribution<IntType>& x) { // NOLINT(runtime/references)
245  using param_type = typename poisson_distribution<IntType>::param_type;
246 
248  double mean = random_internal::read_floating_point<double>(is);
249  if (!is.fail()) {
250  x.param(param_type(mean));
251  }
252  return is;
253 }
254 
256 } // namespace absl
257 
258 #endif // ABSL_RANDOM_POISSON_DISTRIBUTION_H_
absl::poisson_distribution::param_type::mean_
double mean_
Definition: abseil-cpp/absl/random/poisson_distribution.h:77
absl::random_internal::make_istream_state_saver
istream_state_saver< std::basic_istream< CharT, Traits > > make_istream_state_saver(std::basic_istream< CharT, Traits > &is, std::ios_base::fmtflags flags=std::ios_base::dec|std::ios_base::scientific|std::ios_base::skipws)
Definition: abseil-cpp/absl/random/internal/iostream_state_saver.h:149
absl::poisson_distribution::param
param_type param() const
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:106
absl::operator<<
ABSL_NAMESPACE_BEGIN std::ostream & operator<<(std::ostream &os, absl::LogSeverity s)
Definition: abseil-cpp/absl/base/log_severity.cc:24
absl::poisson_distribution::poisson_distribution
poisson_distribution(const param_type &p)
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:92
absl::poisson_distribution::poisson_distribution
poisson_distribution()
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:88
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
mode
const char int mode
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
absl::FormatConversionChar::s
@ s
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
xds_manager.p
p
Definition: xds_manager.py:60
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::poisson_distribution::param_type::param_type
param_type(double mean=1.0)
Definition: abseil-cpp/absl/random/poisson_distribution.h:134
absl::random_internal::GenerateRealFromBits
RealType GenerateRealFromBits(uint64_t bits, int exp_bias=0)
Definition: abseil-cpp/absl/random/internal/generate_real.h:70
absl::poisson_distribution
Definition: abseil-cpp/absl/random/poisson_distribution.h:55
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::poisson_distribution::param_type::poisson_distribution
friend class poisson_distribution
Definition: abseil-cpp/absl/random/poisson_distribution.h:75
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
absl::poisson_distribution::param_type::split_
int split_
Definition: abseil-cpp/absl/random/poisson_distribution.h:82
absl::poisson_distribution::operator()
result_type operator()(URBG &g)
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:98
absl::poisson_distribution::param_type::mean
double mean() const
Definition: abseil-cpp/absl/random/poisson_distribution.h:64
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
result_type
const typedef int * result_type
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:4325
absl::poisson_distribution::result_type
IntType result_type
Definition: abseil-cpp/absl/random/poisson_distribution.h:57
absl::poisson_distribution::max
result_type() max() const
Definition: abseil-cpp/absl/random/poisson_distribution.h:111
absl::poisson_distribution::param_type::operator!=
friend bool operator!=(const param_type &a, const param_type &b)
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:69
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
g
struct @717 g
absl::poisson_distribution::param_type::operator==
friend bool operator==(const param_type &a, const param_type &b)
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:65
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
absl::poisson_distribution::param_
param_type param_
Definition: abseil-cpp/absl/random/poisson_distribution.h:125
absl::poisson_distribution::param_type::s_
double s_
Definition: abseil-cpp/absl/random/poisson_distribution.h:80
absl::poisson_distribution::poisson_distribution
poisson_distribution(double mean)
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:90
absl::poisson_distribution::param_type::lmu_
double lmu_
Definition: abseil-cpp/absl/random/poisson_distribution.h:79
value
const char * value
Definition: hpack_parser_table.cc:165
absl::poisson_distribution::operator==
friend bool operator==(const poisson_distribution &a, const poisson_distribution &b)
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:114
absl::poisson_distribution::param_type
Definition: abseil-cpp/absl/random/poisson_distribution.h:59
absl::poisson_distribution::min
result_type() min() const
Definition: abseil-cpp/absl/random/poisson_distribution.h:110
absl::operator>>
constexpr uint128 operator>>(uint128 lhs, int amount)
Definition: abseil-cpp/absl/numeric/int128.h:917
absl::poisson_distribution::param_type::emu_
double emu_
Definition: abseil-cpp/absl/random/poisson_distribution.h:78
absl::poisson_distribution::reset
void reset()
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:94
absl::poisson_distribution::operator!=
friend bool operator!=(const poisson_distribution &a, const poisson_distribution &b)
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:118
fix_build_deps.r
r
Definition: fix_build_deps.py:491
absl::random_internal::StirlingLogFactorial
double StirlingLogFactorial(double n)
Definition: abseil-cpp/absl/random/internal/fastmath.h:43
log
bool log
Definition: abseil-cpp/absl/synchronization/mutex.cc:310
absl::poisson_distribution::fast_u64_
random_internal::FastUniformBits< uint64_t > fast_u64_
Definition: abseil-cpp/absl/random/poisson_distribution.h:126
absl::poisson_distribution::mean
double mean() const
Definition: abseil-cpp/absl/random/poisson_distribution.h:113
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::poisson_distribution::param
void param(const param_type &p)
Definition: bloaty/third_party/abseil-cpp/absl/random/poisson_distribution.h:107
absl::random_internal::make_ostream_state_saver
ostream_state_saver< std::basic_ostream< CharT, Traits > > make_ostream_state_saver(std::basic_ostream< CharT, Traits > &os, std::ios_base::fmtflags flags=std::ios_base::dec|std::ios_base::left|std::ios_base::scientific)
Definition: abseil-cpp/absl/random/internal/iostream_state_saver.h:82
split
static void split(const char *s, char ***ss, size_t *ns)
Definition: debug/trace.cc:111
absl::random_internal::stream_precision_helper< double >::kPrecision
static constexpr int kPrecision
Definition: abseil-cpp/absl/random/internal/iostream_state_saver.h:121
absl::poisson_distribution::param_type::log_k_
double log_k_
Definition: abseil-cpp/absl/random/poisson_distribution.h:81
absl::random_internal::FastUniformBits< uint64_t >
s_
std::string s_
Definition: abseil-cpp/absl/container/btree_test.cc:1031


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:44