| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 | // Copyright 2017 The Abseil Authors.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at////      https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.//// -----------------------------------------------------------------------------// File: distributions.h// -----------------------------------------------------------------------------//// This header defines functions representing distributions, which you use in// combination with an Abseil random bit generator to produce random values// according to the rules of that distribution.//// The Abseil random library defines the following distributions within this// file:////   * `absl::Uniform` for uniform (constant) distributions having constant//     probability//   * `absl::Bernoulli` for discrete distributions having exactly two outcomes//   * `absl::Beta` for continuous distributions parameterized through two//     free parameters//   * `absl::Exponential` for discrete distributions of events occurring//     continuously and independently at a constant average rate//   * `absl::Gaussian` (also known as "normal distributions") for continuous//     distributions using an associated quadratic function//   * `absl::LogUniform` for continuous uniform distributions where the log//     to the given base of all values is uniform//   * `absl::Poisson` for discrete probability distributions that express the//     probability of a given number of events occurring within a fixed interval//   * `absl::Zipf` for discrete probability distributions commonly used for//     modelling of rare events//// Prefer use of these distribution function classes over manual construction of// your own distribution classes, as it allows library maintainers greater// flexibility to change the underlying implementation in the future.#ifndef ABSL_RANDOM_DISTRIBUTIONS_H_#define ABSL_RANDOM_DISTRIBUTIONS_H_#include <algorithm>#include <cmath>#include <limits>#include <random>#include <type_traits>#include "absl/base/internal/inline_variable.h"#include "absl/random/bernoulli_distribution.h"#include "absl/random/beta_distribution.h"#include "absl/random/exponential_distribution.h"#include "absl/random/gaussian_distribution.h"#include "absl/random/internal/distributions.h"  // IWYU pragma: export#include "absl/random/internal/uniform_helper.h"  // IWYU pragma: export#include "absl/random/log_uniform_int_distribution.h"#include "absl/random/poisson_distribution.h"#include "absl/random/uniform_int_distribution.h"#include "absl/random/uniform_real_distribution.h"#include "absl/random/zipf_distribution.h"namespace absl {ABSL_NAMESPACE_BEGINABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosedClosed,                               {});ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosed, {});ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedOpenTag, IntervalClosedOpen, {});ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpenOpen, {});ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpen, {});ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenClosedTag, IntervalOpenClosed, {});// -----------------------------------------------------------------------------// absl::Uniform<T>(tag, bitgen, lo, hi)// -----------------------------------------------------------------------------//// `absl::Uniform()` produces random values of type `T` uniformly distributed in// a defined interval {lo, hi}. The interval `tag` defines the type of interval// which should be one of the following possible values:////   * `absl::IntervalOpenOpen`//   * `absl::IntervalOpenClosed`//   * `absl::IntervalClosedOpen`//   * `absl::IntervalClosedClosed`//// where "open" refers to an exclusive value (excluded) from the output, while// "closed" refers to an inclusive value (included) from the output.//// In the absence of an explicit return type `T`, `absl::Uniform()` will deduce// the return type based on the provided endpoint arguments {A lo, B hi}.// Given these endpoints, one of {A, B} will be chosen as the return type, if// a type can be implicitly converted into the other in a lossless way. The// lack of any such implicit conversion between {A, B} will produce a// compile-time error//// See https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)//// Example:////   absl::BitGen bitgen;////   // Produce a random float value between 0.0 and 1.0, inclusive//   auto x = absl::Uniform(absl::IntervalClosedClosed, bitgen, 0.0f, 1.0f);////   // The most common interval of `absl::IntervalClosedOpen` is available by//   // default:////   auto x = absl::Uniform(bitgen, 0.0f, 1.0f);////   // Return-types are typically inferred from the arguments, however callers//   // can optionally provide an explicit return-type to the template.////   auto x = absl::Uniform<float>(bitgen, 0, 1);//template <typename R = void, typename TagType, typename URBG>typename absl::enable_if_t<!std::is_same<R, void>::value, R>  //Uniform(TagType tag,        URBG&& urbg,  // NOLINT(runtime/references)        R lo, R hi) {  using gen_t = absl::decay_t<URBG>;  using distribution_t = random_internal::UniformDistributionWrapper<R>;  auto a = random_internal::uniform_lower_bound(tag, lo, hi);  auto b = random_internal::uniform_upper_bound(tag, lo, hi);  if (a > b) return a;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, tag, lo, hi);}// absl::Uniform<T>(bitgen, lo, hi)//// Overload of `Uniform()` using the default closed-open interval of [lo, hi),// and returning values of type `T`template <typename R = void, typename URBG>typename absl::enable_if_t<!std::is_same<R, void>::value, R>  //Uniform(URBG&& urbg,  // NOLINT(runtime/references)        R lo, R hi) {  using gen_t = absl::decay_t<URBG>;  using distribution_t = random_internal::UniformDistributionWrapper<R>;  constexpr auto tag = absl::IntervalClosedOpen;  auto a = random_internal::uniform_lower_bound(tag, lo, hi);  auto b = random_internal::uniform_upper_bound(tag, lo, hi);  if (a > b) return a;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, lo, hi);}// absl::Uniform(tag, bitgen, lo, hi)//// Overload of `Uniform()` using different (but compatible) lo, hi types. Note// that a compile-error will result if the return type cannot be deduced// correctly from the passed types.template <typename R = void, typename TagType, typename URBG, typename A,          typename B>typename absl::enable_if_t<std::is_same<R, void>::value,                           random_internal::uniform_inferred_return_t<A, B>>Uniform(TagType tag,        URBG&& urbg,  // NOLINT(runtime/references)        A lo, B hi) {  using gen_t = absl::decay_t<URBG>;  using return_t = typename random_internal::uniform_inferred_return_t<A, B>;  using distribution_t = random_internal::UniformDistributionWrapper<return_t>;  auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);  auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);  if (a > b) return a;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, tag, static_cast<return_t>(lo),                                static_cast<return_t>(hi));}// absl::Uniform(bitgen, lo, hi)//// Overload of `Uniform()` using different (but compatible) lo, hi types and the// default closed-open interval of [lo, hi). Note that a compile-error will// result if the return type cannot be deduced correctly from the passed types.template <typename R = void, typename URBG, typename A, typename B>typename absl::enable_if_t<std::is_same<R, void>::value,                           random_internal::uniform_inferred_return_t<A, B>>Uniform(URBG&& urbg,  // NOLINT(runtime/references)        A lo, B hi) {  using gen_t = absl::decay_t<URBG>;  using return_t = typename random_internal::uniform_inferred_return_t<A, B>;  using distribution_t = random_internal::UniformDistributionWrapper<return_t>;  constexpr auto tag = absl::IntervalClosedOpen;  auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);  auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);  if (a > b) return a;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, static_cast<return_t>(lo),                                static_cast<return_t>(hi));}// absl::Uniform<unsigned T>(bitgen)//// Overload of Uniform() using the minimum and maximum values of a given type// `T` (which must be unsigned), returning a value of type `unsigned T`template <typename R, typename URBG>typename absl::enable_if_t<!std::is_signed<R>::value, R>  //Uniform(URBG&& urbg) {  // NOLINT(runtime/references)  using gen_t = absl::decay_t<URBG>;  using distribution_t = random_internal::UniformDistributionWrapper<R>;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg);}// -----------------------------------------------------------------------------// absl::Bernoulli(bitgen, p)// -----------------------------------------------------------------------------//// `absl::Bernoulli` produces a random boolean value, with probability `p`// (where 0.0 <= p <= 1.0) equaling `true`.//// Prefer `absl::Bernoulli` to produce boolean values over other alternatives// such as comparing an `absl::Uniform()` value to a specific output.//// See https://en.wikipedia.org/wiki/Bernoulli_distribution//// Example:////   absl::BitGen bitgen;//   ...//   if (absl::Bernoulli(bitgen, 1.0/3721.0)) {//     std::cout << "Asteroid field navigation successful.";//   }//template <typename URBG>bool Bernoulli(URBG&& urbg,  // NOLINT(runtime/references)               double p) {  using gen_t = absl::decay_t<URBG>;  using distribution_t = absl::bernoulli_distribution;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, p);}// -----------------------------------------------------------------------------// absl::Beta<T>(bitgen, alpha, beta)// -----------------------------------------------------------------------------//// `absl::Beta` produces a floating point number distributed in the closed// interval [0,1] and parameterized by two values `alpha` and `beta` as per a// Beta distribution. `T` must be a floating point type, but may be inferred// from the types of `alpha` and `beta`.//// See https://en.wikipedia.org/wiki/Beta_distribution.//// Example:////   absl::BitGen bitgen;//   ...//   double sample = absl::Beta(bitgen, 3.0, 2.0);//template <typename RealType, typename URBG>RealType Beta(URBG&& urbg,  // NOLINT(runtime/references)              RealType alpha, RealType beta) {  static_assert(      std::is_floating_point<RealType>::value,      "Template-argument 'RealType' must be a floating-point type, in "      "absl::Beta<RealType, URBG>(...)");  using gen_t = absl::decay_t<URBG>;  using distribution_t = typename absl::beta_distribution<RealType>;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, alpha, beta);}// -----------------------------------------------------------------------------// absl::Exponential<T>(bitgen, lambda = 1)// -----------------------------------------------------------------------------//// `absl::Exponential` produces a floating point number representing the// distance (time) between two consecutive events in a point process of events// occurring continuously and independently at a constant average rate. `T` must// be a floating point type, but may be inferred from the type of `lambda`.//// See https://en.wikipedia.org/wiki/Exponential_distribution.//// Example:////   absl::BitGen bitgen;//   ...//   double call_length = absl::Exponential(bitgen, 7.0);//template <typename RealType, typename URBG>RealType Exponential(URBG&& urbg,  // NOLINT(runtime/references)                     RealType lambda = 1) {  static_assert(      std::is_floating_point<RealType>::value,      "Template-argument 'RealType' must be a floating-point type, in "      "absl::Exponential<RealType, URBG>(...)");  using gen_t = absl::decay_t<URBG>;  using distribution_t = typename absl::exponential_distribution<RealType>;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, lambda);}// -----------------------------------------------------------------------------// absl::Gaussian<T>(bitgen, mean = 0, stddev = 1)// -----------------------------------------------------------------------------//// `absl::Gaussian` produces a floating point number selected from the Gaussian// (ie. "Normal") distribution. `T` must be a floating point type, but may be// inferred from the types of `mean` and `stddev`.//// See https://en.wikipedia.org/wiki/Normal_distribution//// Example:////   absl::BitGen bitgen;//   ...//   double giraffe_height = absl::Gaussian(bitgen, 16.3, 3.3);//template <typename RealType, typename URBG>RealType Gaussian(URBG&& urbg,  // NOLINT(runtime/references)                  RealType mean = 0, RealType stddev = 1) {  static_assert(      std::is_floating_point<RealType>::value,      "Template-argument 'RealType' must be a floating-point type, in "      "absl::Gaussian<RealType, URBG>(...)");  using gen_t = absl::decay_t<URBG>;  using distribution_t = typename absl::gaussian_distribution<RealType>;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, mean, stddev);}// -----------------------------------------------------------------------------// absl::LogUniform<T>(bitgen, lo, hi, base = 2)// -----------------------------------------------------------------------------//// `absl::LogUniform` produces random values distributed where the log to a// given base of all values is uniform in a closed interval [lo, hi]. `T` must// be an integral type, but may be inferred from the types of `lo` and `hi`.//// I.e., `LogUniform(0, n, b)` is uniformly distributed across buckets// [0], [1, b-1], [b, b^2-1] .. [b^(k-1), (b^k)-1] .. [b^floor(log(n, b)), n]// and is uniformly distributed within each bucket.//// The resulting probability density is inversely related to bucket size, though// values in the final bucket may be more likely than previous values. (In the// extreme case where n = b^i the final value will be tied with zero as the most// probable result.//// If `lo` is nonzero then this distribution is shifted to the desired interval,// so LogUniform(lo, hi, b) is equivalent to LogUniform(0, hi-lo, b)+lo.//// See http://ecolego.facilia.se/ecolego/show/Log-Uniform%20Distribution//// Example:////   absl::BitGen bitgen;//   ...//   int v = absl::LogUniform(bitgen, 0, 1000);//template <typename IntType, typename URBG>IntType LogUniform(URBG&& urbg,  // NOLINT(runtime/references)                   IntType lo, IntType hi, IntType base = 2) {  static_assert(std::is_integral<IntType>::value,                "Template-argument 'IntType' must be an integral type, in "                "absl::LogUniform<IntType, URBG>(...)");  using gen_t = absl::decay_t<URBG>;  using distribution_t = typename absl::log_uniform_int_distribution<IntType>;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, lo, hi, base);}// -----------------------------------------------------------------------------// absl::Poisson<T>(bitgen, mean = 1)// -----------------------------------------------------------------------------//// `absl::Poisson` produces discrete probabilities for a given number of events// occurring within a fixed interval within the closed interval [0, max]. `T`// must be an integral type.//// See https://en.wikipedia.org/wiki/Poisson_distribution//// Example:////   absl::BitGen bitgen;//   ...//   int requests_per_minute = absl::Poisson<int>(bitgen, 3.2);//template <typename IntType, typename URBG>IntType Poisson(URBG&& urbg,  // NOLINT(runtime/references)                double mean = 1.0) {  static_assert(std::is_integral<IntType>::value,                "Template-argument 'IntType' must be an integral type, in "                "absl::Poisson<IntType, URBG>(...)");  using gen_t = absl::decay_t<URBG>;  using distribution_t = typename absl::poisson_distribution<IntType>;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, mean);}// -----------------------------------------------------------------------------// absl::Zipf<T>(bitgen, hi = max, q = 2, v = 1)// -----------------------------------------------------------------------------//// `absl::Zipf` produces discrete probabilities commonly used for modelling of// rare events over the closed interval [0, hi]. The parameters `v` and `q`// determine the skew of the distribution. `T`  must be an integral type, but// may be inferred from the type of `hi`.//// See http://mathworld.wolfram.com/ZipfDistribution.html//// Example:////   absl::BitGen bitgen;//   ...//   int term_rank = absl::Zipf<int>(bitgen);//template <typename IntType, typename URBG>IntType Zipf(URBG&& urbg,  // NOLINT(runtime/references)             IntType hi = (std::numeric_limits<IntType>::max)(), double q = 2.0,             double v = 1.0) {  static_assert(std::is_integral<IntType>::value,                "Template-argument 'IntType' must be an integral type, in "                "absl::Zipf<IntType, URBG>(...)");  using gen_t = absl::decay_t<URBG>;  using distribution_t = typename absl::zipf_distribution<IntType>;  return random_internal::DistributionCaller<gen_t>::template Call<      distribution_t>(&urbg, hi, q, v);}ABSL_NAMESPACE_END}  // namespace absl#endif  // ABSL_RANDOM_DISTRIBUTIONS_H_
 |