#ifndef ABSL_RANDOM_DISTRIBUTIONS_H_
#define ABSL_RANDOM_DISTRIBUTIONS_H_
#include <limits>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/base/internal/inline_variable.h"
#include "absl/meta/type_traits.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/distribution_caller.h"
#include "absl/random/internal/traits.h"
#include "absl/random/internal/uniform_helper.h"
#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_BEGIN
ABSL_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, {});
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, 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 (!random_internal::is_uniform_range_valid(a, b)) return lo;
return random_internal::DistributionCaller<gen_t>::template Call<
distribution_t>(&urbg, tag, lo, hi);
}
template <typename R = void, typename URBG>
typename absl::enable_if_t<!std::is_same<R, void>::value, R> Uniform(URBG&& urbg, 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 (!random_internal::is_uniform_range_valid(a, b)) return lo;
return random_internal::DistributionCaller<gen_t>::template Call<
distribution_t>(&urbg, lo, hi);
}
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, 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 (!random_internal::is_uniform_range_valid(a, b)) return lo;
return random_internal::DistributionCaller<gen_t>::template Call<
distribution_t>(&urbg, tag, static_cast<return_t>(lo),
static_cast<return_t>(hi));
}
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, 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 (!random_internal::is_uniform_range_valid(a, b)) return lo;
return random_internal::DistributionCaller<gen_t>::template Call<
distribution_t>(&urbg, static_cast<return_t>(lo),
static_cast<return_t>(hi));
}
template <typename R, typename URBG>
typename absl::enable_if_t<!std::numeric_limits<R>::is_signed, R> Uniform(URBG&& urbg) { 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);
}
template <typename URBG>
bool Bernoulli(URBG&& urbg, 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);
}
template <typename RealType, typename URBG>
RealType Beta(URBG&& urbg, 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);
}
template <typename RealType, typename URBG>
RealType Exponential(URBG&& urbg, 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);
}
template <typename RealType, typename URBG>
RealType Gaussian(URBG&& urbg, 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);
}
template <typename IntType, typename URBG>
IntType LogUniform(URBG&& urbg, IntType lo, IntType hi, IntType base = 2) {
static_assert(random_internal::IsIntegral<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);
}
template <typename IntType, typename URBG>
IntType Poisson(URBG&& urbg, double mean = 1.0) {
static_assert(random_internal::IsIntegral<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);
}
template <typename IntType, typename URBG>
IntType Zipf(URBG&& urbg, IntType hi = (std::numeric_limits<IntType>::max)(), double q = 2.0,
double v = 1.0) {
static_assert(random_internal::IsIntegral<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
}
#endif