abseil-cpp/absl/random/distributions.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 // -----------------------------------------------------------------------------
16 // File: distributions.h
17 // -----------------------------------------------------------------------------
18 //
19 // This header defines functions representing distributions, which you use in
20 // combination with an Abseil random bit generator to produce random values
21 // according to the rules of that distribution.
22 //
23 // The Abseil random library defines the following distributions within this
24 // file:
25 //
26 // * `absl::Uniform` for uniform (constant) distributions having constant
27 // probability
28 // * `absl::Bernoulli` for discrete distributions having exactly two outcomes
29 // * `absl::Beta` for continuous distributions parameterized through two
30 // free parameters
31 // * `absl::Exponential` for discrete distributions of events occurring
32 // continuously and independently at a constant average rate
33 // * `absl::Gaussian` (also known as "normal distributions") for continuous
34 // distributions using an associated quadratic function
35 // * `absl::LogUniform` for continuous uniform distributions where the log
36 // to the given base of all values is uniform
37 // * `absl::Poisson` for discrete probability distributions that express the
38 // probability of a given number of events occurring within a fixed interval
39 // * `absl::Zipf` for discrete probability distributions commonly used for
40 // modelling of rare events
41 //
42 // Prefer use of these distribution function classes over manual construction of
43 // your own distribution classes, as it allows library maintainers greater
44 // flexibility to change the underlying implementation in the future.
45 
46 #ifndef ABSL_RANDOM_DISTRIBUTIONS_H_
47 #define ABSL_RANDOM_DISTRIBUTIONS_H_
48 
49 #include <algorithm>
50 #include <cmath>
51 #include <limits>
52 #include <random>
53 #include <type_traits>
54 
55 #include "absl/base/internal/inline_variable.h"
56 #include "absl/random/bernoulli_distribution.h"
57 #include "absl/random/beta_distribution.h"
58 #include "absl/random/exponential_distribution.h"
59 #include "absl/random/gaussian_distribution.h"
60 #include "absl/random/internal/distribution_caller.h" // IWYU pragma: export
61 #include "absl/random/internal/uniform_helper.h" // IWYU pragma: export
62 #include "absl/random/log_uniform_int_distribution.h"
63 #include "absl/random/poisson_distribution.h"
64 #include "absl/random/uniform_int_distribution.h"
65 #include "absl/random/uniform_real_distribution.h"
66 #include "absl/random/zipf_distribution.h"
67 
68 namespace absl {
70 
71 ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosedClosed,
72  {});
73 ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosed, {});
74 ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedOpenTag, IntervalClosedOpen, {});
75 ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpenOpen, {});
76 ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpen, {});
77 ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenClosedTag, IntervalOpenClosed, {});
78 
79 // -----------------------------------------------------------------------------
80 // absl::Uniform<T>(tag, bitgen, lo, hi)
81 // -----------------------------------------------------------------------------
82 //
83 // `absl::Uniform()` produces random values of type `T` uniformly distributed in
84 // a defined interval {lo, hi}. The interval `tag` defines the type of interval
85 // which should be one of the following possible values:
86 //
87 // * `absl::IntervalOpenOpen`
88 // * `absl::IntervalOpenClosed`
89 // * `absl::IntervalClosedOpen`
90 // * `absl::IntervalClosedClosed`
91 //
92 // where "open" refers to an exclusive value (excluded) from the output, while
93 // "closed" refers to an inclusive value (included) from the output.
94 //
95 // In the absence of an explicit return type `T`, `absl::Uniform()` will deduce
96 // the return type based on the provided endpoint arguments {A lo, B hi}.
97 // Given these endpoints, one of {A, B} will be chosen as the return type, if
98 // a type can be implicitly converted into the other in a lossless way. The
99 // lack of any such implicit conversion between {A, B} will produce a
100 // compile-time error
101 //
102 // See https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)
103 //
104 // Example:
105 //
106 // absl::BitGen bitgen;
107 //
108 // // Produce a random float value between 0.0 and 1.0, inclusive
109 // auto x = absl::Uniform(absl::IntervalClosedClosed, bitgen, 0.0f, 1.0f);
110 //
111 // // The most common interval of `absl::IntervalClosedOpen` is available by
112 // // default:
113 //
114 // auto x = absl::Uniform(bitgen, 0.0f, 1.0f);
115 //
116 // // Return-types are typically inferred from the arguments, however callers
117 // // can optionally provide an explicit return-type to the template.
118 //
119 // auto x = absl::Uniform<float>(bitgen, 0, 1);
120 //
121 template <typename R = void, typename TagType, typename URBG>
123 Uniform(TagType tag,
124  URBG&& urbg, // NOLINT(runtime/references)
125  R lo, R hi) {
126  using gen_t = absl::decay_t<URBG>;
127  using distribution_t = random_internal::UniformDistributionWrapper<R>;
128 
131  if (!random_internal::is_uniform_range_valid(a, b)) return lo;
132 
134  distribution_t>(&urbg, tag, lo, hi);
135 }
136 
137 // absl::Uniform<T>(bitgen, lo, hi)
138 //
139 // Overload of `Uniform()` using the default closed-open interval of [lo, hi),
140 // and returning values of type `T`
141 template <typename R = void, typename URBG>
143 Uniform(URBG&& urbg, // NOLINT(runtime/references)
144  R lo, R hi) {
145  using gen_t = absl::decay_t<URBG>;
146  using distribution_t = random_internal::UniformDistributionWrapper<R>;
147  constexpr auto tag = absl::IntervalClosedOpen;
148 
151  if (!random_internal::is_uniform_range_valid(a, b)) return lo;
152 
154  distribution_t>(&urbg, lo, hi);
155 }
156 
157 // absl::Uniform(tag, bitgen, lo, hi)
158 //
159 // Overload of `Uniform()` using different (but compatible) lo, hi types. Note
160 // that a compile-error will result if the return type cannot be deduced
161 // correctly from the passed types.
162 template <typename R = void, typename TagType, typename URBG, typename A,
163  typename B>
165  random_internal::uniform_inferred_return_t<A, B>>
166 Uniform(TagType tag,
167  URBG&& urbg, // NOLINT(runtime/references)
168  A lo, B hi) {
169  using gen_t = absl::decay_t<URBG>;
170  using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
172 
173  auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);
174  auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);
175  if (!random_internal::is_uniform_range_valid(a, b)) return lo;
176 
178  distribution_t>(&urbg, tag, static_cast<return_t>(lo),
179  static_cast<return_t>(hi));
180 }
181 
182 // absl::Uniform(bitgen, lo, hi)
183 //
184 // Overload of `Uniform()` using different (but compatible) lo, hi types and the
185 // default closed-open interval of [lo, hi). Note that a compile-error will
186 // result if the return type cannot be deduced correctly from the passed types.
187 template <typename R = void, typename URBG, typename A, typename B>
189  random_internal::uniform_inferred_return_t<A, B>>
190 Uniform(URBG&& urbg, // NOLINT(runtime/references)
191  A lo, B hi) {
192  using gen_t = absl::decay_t<URBG>;
193  using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
195 
196  constexpr auto tag = absl::IntervalClosedOpen;
197  auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);
198  auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);
199  if (!random_internal::is_uniform_range_valid(a, b)) return lo;
200 
202  distribution_t>(&urbg, static_cast<return_t>(lo),
203  static_cast<return_t>(hi));
204 }
205 
206 // absl::Uniform<unsigned T>(bitgen)
207 //
208 // Overload of Uniform() using the minimum and maximum values of a given type
209 // `T` (which must be unsigned), returning a value of type `unsigned T`
210 template <typename R, typename URBG>
212 Uniform(URBG&& urbg) { // NOLINT(runtime/references)
213  using gen_t = absl::decay_t<URBG>;
214  using distribution_t = random_internal::UniformDistributionWrapper<R>;
215 
217  distribution_t>(&urbg);
218 }
219 
220 // -----------------------------------------------------------------------------
221 // absl::Bernoulli(bitgen, p)
222 // -----------------------------------------------------------------------------
223 //
224 // `absl::Bernoulli` produces a random boolean value, with probability `p`
225 // (where 0.0 <= p <= 1.0) equaling `true`.
226 //
227 // Prefer `absl::Bernoulli` to produce boolean values over other alternatives
228 // such as comparing an `absl::Uniform()` value to a specific output.
229 //
230 // See https://en.wikipedia.org/wiki/Bernoulli_distribution
231 //
232 // Example:
233 //
234 // absl::BitGen bitgen;
235 // ...
236 // if (absl::Bernoulli(bitgen, 1.0/3721.0)) {
237 // std::cout << "Asteroid field navigation successful.";
238 // }
239 //
240 template <typename URBG>
241 bool Bernoulli(URBG&& urbg, // NOLINT(runtime/references)
242  double p) {
243  using gen_t = absl::decay_t<URBG>;
244  using distribution_t = absl::bernoulli_distribution;
245 
247  distribution_t>(&urbg, p);
248 }
249 
250 // -----------------------------------------------------------------------------
251 // absl::Beta<T>(bitgen, alpha, beta)
252 // -----------------------------------------------------------------------------
253 //
254 // `absl::Beta` produces a floating point number distributed in the closed
255 // interval [0,1] and parameterized by two values `alpha` and `beta` as per a
256 // Beta distribution. `T` must be a floating point type, but may be inferred
257 // from the types of `alpha` and `beta`.
258 //
259 // See https://en.wikipedia.org/wiki/Beta_distribution.
260 //
261 // Example:
262 //
263 // absl::BitGen bitgen;
264 // ...
265 // double sample = absl::Beta(bitgen, 3.0, 2.0);
266 //
267 template <typename RealType, typename URBG>
268 RealType Beta(URBG&& urbg, // NOLINT(runtime/references)
269  RealType alpha, RealType beta) {
270  static_assert(
272  "Template-argument 'RealType' must be a floating-point type, in "
273  "absl::Beta<RealType, URBG>(...)");
274 
275  using gen_t = absl::decay_t<URBG>;
276  using distribution_t = typename absl::beta_distribution<RealType>;
277 
279  distribution_t>(&urbg, alpha, beta);
280 }
281 
282 // -----------------------------------------------------------------------------
283 // absl::Exponential<T>(bitgen, lambda = 1)
284 // -----------------------------------------------------------------------------
285 //
286 // `absl::Exponential` produces a floating point number representing the
287 // distance (time) between two consecutive events in a point process of events
288 // occurring continuously and independently at a constant average rate. `T` must
289 // be a floating point type, but may be inferred from the type of `lambda`.
290 //
291 // See https://en.wikipedia.org/wiki/Exponential_distribution.
292 //
293 // Example:
294 //
295 // absl::BitGen bitgen;
296 // ...
297 // double call_length = absl::Exponential(bitgen, 7.0);
298 //
299 template <typename RealType, typename URBG>
300 RealType Exponential(URBG&& urbg, // NOLINT(runtime/references)
301  RealType lambda = 1) {
302  static_assert(
304  "Template-argument 'RealType' must be a floating-point type, in "
305  "absl::Exponential<RealType, URBG>(...)");
306 
307  using gen_t = absl::decay_t<URBG>;
308  using distribution_t = typename absl::exponential_distribution<RealType>;
309 
311  distribution_t>(&urbg, lambda);
312 }
313 
314 // -----------------------------------------------------------------------------
315 // absl::Gaussian<T>(bitgen, mean = 0, stddev = 1)
316 // -----------------------------------------------------------------------------
317 //
318 // `absl::Gaussian` produces a floating point number selected from the Gaussian
319 // (ie. "Normal") distribution. `T` must be a floating point type, but may be
320 // inferred from the types of `mean` and `stddev`.
321 //
322 // See https://en.wikipedia.org/wiki/Normal_distribution
323 //
324 // Example:
325 //
326 // absl::BitGen bitgen;
327 // ...
328 // double giraffe_height = absl::Gaussian(bitgen, 16.3, 3.3);
329 //
330 template <typename RealType, typename URBG>
331 RealType Gaussian(URBG&& urbg, // NOLINT(runtime/references)
332  RealType mean = 0, RealType stddev = 1) {
333  static_assert(
335  "Template-argument 'RealType' must be a floating-point type, in "
336  "absl::Gaussian<RealType, URBG>(...)");
337 
338  using gen_t = absl::decay_t<URBG>;
339  using distribution_t = typename absl::gaussian_distribution<RealType>;
340 
342  distribution_t>(&urbg, mean, stddev);
343 }
344 
345 // -----------------------------------------------------------------------------
346 // absl::LogUniform<T>(bitgen, lo, hi, base = 2)
347 // -----------------------------------------------------------------------------
348 //
349 // `absl::LogUniform` produces random values distributed where the log to a
350 // given base of all values is uniform in a closed interval [lo, hi]. `T` must
351 // be an integral type, but may be inferred from the types of `lo` and `hi`.
352 //
353 // I.e., `LogUniform(0, n, b)` is uniformly distributed across buckets
354 // [0], [1, b-1], [b, b^2-1] .. [b^(k-1), (b^k)-1] .. [b^floor(log(n, b)), n]
355 // and is uniformly distributed within each bucket.
356 //
357 // The resulting probability density is inversely related to bucket size, though
358 // values in the final bucket may be more likely than previous values. (In the
359 // extreme case where n = b^i the final value will be tied with zero as the most
360 // probable result.
361 //
362 // If `lo` is nonzero then this distribution is shifted to the desired interval,
363 // so LogUniform(lo, hi, b) is equivalent to LogUniform(0, hi-lo, b)+lo.
364 //
365 // See http://ecolego.facilia.se/ecolego/show/Log-Uniform%20Distribution
366 //
367 // Example:
368 //
369 // absl::BitGen bitgen;
370 // ...
371 // int v = absl::LogUniform(bitgen, 0, 1000);
372 //
373 template <typename IntType, typename URBG>
374 IntType LogUniform(URBG&& urbg, // NOLINT(runtime/references)
375  IntType lo, IntType hi, IntType base = 2) {
377  "Template-argument 'IntType' must be an integral type, in "
378  "absl::LogUniform<IntType, URBG>(...)");
379 
380  using gen_t = absl::decay_t<URBG>;
381  using distribution_t = typename absl::log_uniform_int_distribution<IntType>;
382 
384  distribution_t>(&urbg, lo, hi, base);
385 }
386 
387 // -----------------------------------------------------------------------------
388 // absl::Poisson<T>(bitgen, mean = 1)
389 // -----------------------------------------------------------------------------
390 //
391 // `absl::Poisson` produces discrete probabilities for a given number of events
392 // occurring within a fixed interval within the closed interval [0, max]. `T`
393 // must be an integral type.
394 //
395 // See https://en.wikipedia.org/wiki/Poisson_distribution
396 //
397 // Example:
398 //
399 // absl::BitGen bitgen;
400 // ...
401 // int requests_per_minute = absl::Poisson<int>(bitgen, 3.2);
402 //
403 template <typename IntType, typename URBG>
404 IntType Poisson(URBG&& urbg, // NOLINT(runtime/references)
405  double mean = 1.0) {
407  "Template-argument 'IntType' must be an integral type, in "
408  "absl::Poisson<IntType, URBG>(...)");
409 
410  using gen_t = absl::decay_t<URBG>;
411  using distribution_t = typename absl::poisson_distribution<IntType>;
412 
414  distribution_t>(&urbg, mean);
415 }
416 
417 // -----------------------------------------------------------------------------
418 // absl::Zipf<T>(bitgen, hi = max, q = 2, v = 1)
419 // -----------------------------------------------------------------------------
420 //
421 // `absl::Zipf` produces discrete probabilities commonly used for modelling of
422 // rare events over the closed interval [0, hi]. The parameters `v` and `q`
423 // determine the skew of the distribution. `T` must be an integral type, but
424 // may be inferred from the type of `hi`.
425 //
426 // See http://mathworld.wolfram.com/ZipfDistribution.html
427 //
428 // Example:
429 //
430 // absl::BitGen bitgen;
431 // ...
432 // int term_rank = absl::Zipf<int>(bitgen);
433 //
434 template <typename IntType, typename URBG>
435 IntType Zipf(URBG&& urbg, // NOLINT(runtime/references)
436  IntType hi = (std::numeric_limits<IntType>::max)(), double q = 2.0,
437  double v = 1.0) {
439  "Template-argument 'IntType' must be an integral type, in "
440  "absl::Zipf<IntType, URBG>(...)");
441 
442  using gen_t = absl::decay_t<URBG>;
443  using distribution_t = typename absl::zipf_distribution<IntType>;
444 
446  distribution_t>(&urbg, hi, q, v);
447 }
448 
450 } // namespace absl
451 
452 #endif // ABSL_RANDOM_DISTRIBUTIONS_H_
absl::decay_t
typename std::decay< T >::type decay_t
Definition: abseil-cpp/absl/meta/type_traits.h:628
absl::random_internal::uniform_inferred_return_t
absl::enable_if_t< absl::disjunction< is_widening_convertible< A, B >, is_widening_convertible< B, A > >::value, typename std::conditional< is_widening_convertible< A, B >::value, B, A >::type > uniform_inferred_return_t
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:82
absl::exponential_distribution
Definition: abseil-cpp/absl/random/exponential_distribution.h:36
absl::Beta
RealType Beta(URBG &&urbg, RealType alpha, RealType beta)
Definition: abseil-cpp/absl/random/distributions.h:268
absl::Gaussian
RealType Gaussian(URBG &&urbg, RealType mean=0, RealType stddev=1)
Definition: abseil-cpp/absl/random/distributions.h:331
absl::bernoulli_distribution
Definition: abseil-cpp/absl/random/bernoulli_distribution.h:35
grpc.beta._metadata.beta
def beta(metadata)
Definition: src/python/grpcio/grpc/beta/_metadata.py:39
absl::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: abseil-cpp/absl/meta/type_traits.h:631
absl::ABSL_INTERNAL_INLINE_CONSTEXPR
ABSL_NAMESPACE_BEGIN ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosedClosed, {})
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
absl::random_internal::IsIntegral
Definition: abseil-cpp/absl/random/internal/traits.h:65
absl::Poisson
IntType Poisson(URBG &&urbg, double mean=1.0)
Definition: abseil-cpp/absl/random/distributions.h:404
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::gaussian_distribution
Definition: abseil-cpp/absl/random/gaussian_distribution.h:87
absl::Exponential
RealType Exponential(URBG &&urbg, RealType lambda=1)
Definition: abseil-cpp/absl/random/distributions.h:300
absl::random_internal::DistributionCaller
Definition: abseil-cpp/absl/random/bit_gen_ref.h:59
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
tag
static void * tag(intptr_t t)
Definition: bad_client.cc:318
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
Call
Definition: api_fuzzer.cc:319
absl::random_internal::is_uniform_range_valid
absl::enable_if_t< std::is_floating_point< FloatType >::value, bool > is_uniform_range_valid(FloatType a, FloatType b)
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:199
gen_synthetic_protos.base
base
Definition: gen_synthetic_protos.py:31
absl::log_uniform_int_distribution
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:44
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
absl::random_internal::uniform_lower_bound
absl::enable_if_t< absl::conjunction< IsIntegral< IntType >, absl::disjunction< std::is_same< Tag, IntervalOpenClosedTag >, std::is_same< Tag, IntervalOpenOpenTag > > >::value, IntType > uniform_lower_bound(Tag, IntType a, IntType)
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:107
absl::random_internal::UniformDistributionWrapper
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:223
value
const char * value
Definition: hpack_parser_table.cc:165
absl::zipf_distribution
Definition: abseil-cpp/absl/random/zipf_distribution.h:52
A
Definition: miscompile_with_no_unique_address_test.cc:23
absl::LogUniform
IntType LogUniform(URBG &&urbg, IntType lo, IntType hi, IntType base=2)
Definition: abseil-cpp/absl/random/distributions.h:374
absl::Zipf
IntType Zipf(URBG &&urbg, IntType hi=(std::numeric_limits< IntType >::max)(), double q=2.0, double v=1.0)
Definition: abseil-cpp/absl/random/distributions.h:435
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::random_internal::uniform_upper_bound
absl::enable_if_t< absl::conjunction< IsIntegral< IntType >, absl::disjunction< std::is_same< Tag, IntervalClosedOpenTag >, std::is_same< Tag, IntervalOpenOpenTag > > >::value, IntType > uniform_upper_bound(Tag, IntType, IntType b)
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:138
absl::beta_distribution
Definition: abseil-cpp/absl/random/beta_distribution.h:49
absl::Bernoulli
bool Bernoulli(URBG &&urbg, double p)
Definition: abseil-cpp/absl/random/distributions.h:241
absl::Uniform
absl::enable_if_t<!std::is_same< R, void >::value, R > Uniform(TagType tag, URBG &&urbg, R lo, R hi)
Definition: abseil-cpp/absl/random/distributions.h:123


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