This commit is contained in:
Yao
2024-12-20 17:49:45 +08:00
parent 86b0363ce1
commit 654d456c7d
7011 changed files with 1705926 additions and 7 deletions

View File

@@ -0,0 +1,200 @@
// 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.
#ifndef ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_
#define ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_
#include <cstdint>
#include <istream>
#include <limits>
#include "absl/base/optimization.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/random/internal/iostream_state_saver.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::bernoulli_distribution is a drop in replacement for
// std::bernoulli_distribution. It guarantees that (given a perfect
// UniformRandomBitGenerator) the acceptance probability is *exactly* equal to
// the given double.
//
// The implementation assumes that double is IEEE754
class bernoulli_distribution {
public:
using result_type = bool;
class param_type {
public:
using distribution_type = bernoulli_distribution;
explicit param_type(double p = 0.5) : prob_(p) {
assert(p >= 0.0 && p <= 1.0);
}
double p() const { return prob_; }
friend bool operator==(const param_type& p1, const param_type& p2) {
return p1.p() == p2.p();
}
friend bool operator!=(const param_type& p1, const param_type& p2) {
return p1.p() != p2.p();
}
private:
double prob_;
};
bernoulli_distribution() : bernoulli_distribution(0.5) {}
explicit bernoulli_distribution(double p) : param_(p) {}
explicit bernoulli_distribution(param_type p) : param_(p) {}
// no-op
void reset() {}
template <typename URBG>
bool operator()(URBG& g) { // NOLINT(runtime/references)
return Generate(param_.p(), g);
}
template <typename URBG>
bool operator()(URBG& g, // NOLINT(runtime/references)
const param_type& param) {
return Generate(param.p(), g);
}
param_type param() const { return param_; }
void param(const param_type& param) { param_ = param; }
double p() const { return param_.p(); }
result_type(min)() const { return false; }
result_type(max)() const { return true; }
friend bool operator==(const bernoulli_distribution& d1,
const bernoulli_distribution& d2) {
return d1.param_ == d2.param_;
}
friend bool operator!=(const bernoulli_distribution& d1,
const bernoulli_distribution& d2) {
return d1.param_ != d2.param_;
}
private:
static constexpr uint64_t kP32 = static_cast<uint64_t>(1) << 32;
template <typename URBG>
static bool Generate(double p, URBG& g); // NOLINT(runtime/references)
param_type param_;
};
template <typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const bernoulli_distribution& x) {
auto saver = random_internal::make_ostream_state_saver(os);
os.precision(random_internal::stream_precision_helper<double>::kPrecision);
os << x.p();
return os;
}
template <typename CharT, typename Traits>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
bernoulli_distribution& x) { // NOLINT(runtime/references)
auto saver = random_internal::make_istream_state_saver(is);
auto p = random_internal::read_floating_point<double>(is);
if (!is.fail()) {
x.param(bernoulli_distribution::param_type(p));
}
return is;
}
template <typename URBG>
bool bernoulli_distribution::Generate(double p,
URBG& g) { // NOLINT(runtime/references)
random_internal::FastUniformBits<uint32_t> fast_u32;
while (true) {
// There are two aspects of the definition of `c` below that are worth
// commenting on. First, because `p` is in the range [0, 1], `c` is in the
// range [0, 2^32] which does not fit in a uint32_t and therefore requires
// 64 bits.
//
// Second, `c` is constructed by first casting explicitly to a signed
// integer and then casting explicitly to an unsigned integer of the same
// size. This is done because the hardware conversion instructions produce
// signed integers from double; if taken as a uint64_t the conversion would
// be wrong for doubles greater than 2^63 (not relevant in this use-case).
// If converted directly to an unsigned integer, the compiler would end up
// emitting code to handle such large values that are not relevant due to
// the known bounds on `c`. To avoid these extra instructions this
// implementation converts first to the signed type and then convert to
// unsigned (which is a no-op).
const uint64_t c = static_cast<uint64_t>(static_cast<int64_t>(p * kP32));
const uint32_t v = fast_u32(g);
// FAST PATH: this path fails with probability 1/2^32. Note that simply
// returning v <= c would approximate P very well (up to an absolute error
// of 1/2^32); the slow path (taken in that range of possible error, in the
// case of equality) eliminates the remaining error.
if (ABSL_PREDICT_TRUE(v != c)) return v < c;
// It is guaranteed that `q` is strictly less than 1, because if `q` were
// greater than or equal to 1, the same would be true for `p`. Certainly `p`
// cannot be greater than 1, and if `p == 1`, then the fast path would
// necessary have been taken already.
const double q = static_cast<double>(c) / kP32;
// The probability of acceptance on the fast path is `q` and so the
// probability of acceptance here should be `p - q`.
//
// Note that `q` is obtained from `p` via some shifts and conversions, the
// upshot of which is that `q` is simply `p` with some of the
// least-significant bits of its mantissa set to zero. This means that the
// difference `p - q` will not have any rounding errors. To see why, pretend
// that double has 10 bits of resolution and q is obtained from `p` in such
// a way that the 4 least-significant bits of its mantissa are set to zero.
// For example:
// p = 1.1100111011 * 2^-1
// q = 1.1100110000 * 2^-1
// p - q = 1.011 * 2^-8
// The difference `p - q` has exactly the nonzero mantissa bits that were
// "lost" in `q` producing a number which is certainly representable in a
// double.
const double left = p - q;
// By construction, the probability of being on this slow path is 1/2^32, so
// P(accept in slow path) = P(accept| in slow path) * P(slow path),
// which means the probability of acceptance here is `1 / (left * kP32)`:
const double here = left * kP32;
// The simplest way to compute the result of this trial is to repeat the
// whole algorithm with the new probability. This terminates because even
// given arbitrarily unfriendly "random" bits, each iteration either
// multiplies a tiny probability by 2^32 (if c == 0) or strips off some
// number of nonzero mantissa bits. That process is bounded.
if (here == 0) return false;
p = here;
}
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_

View File

@@ -0,0 +1,427 @@
// 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.
#ifndef ABSL_RANDOM_BETA_DISTRIBUTION_H_
#define ABSL_RANDOM_BETA_DISTRIBUTION_H_
#include <cassert>
#include <cmath>
#include <istream>
#include <limits>
#include <ostream>
#include <type_traits>
#include "absl/meta/type_traits.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/random/internal/fastmath.h"
#include "absl/random/internal/generate_real.h"
#include "absl/random/internal/iostream_state_saver.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::beta_distribution:
// Generate a floating-point variate conforming to a Beta distribution:
// pdf(x) \propto x^(alpha-1) * (1-x)^(beta-1),
// where the params alpha and beta are both strictly positive real values.
//
// The support is the open interval (0, 1), but the return value might be equal
// to 0 or 1, due to numerical errors when alpha and beta are very different.
//
// Usage note: One usage is that alpha and beta are counts of number of
// successes and failures. When the total number of trials are large, consider
// approximating a beta distribution with a Gaussian distribution with the same
// mean and variance. One could use the skewness, which depends only on the
// smaller of alpha and beta when the number of trials are sufficiently large,
// to quantify how far a beta distribution is from the normal distribution.
template <typename RealType = double>
class beta_distribution {
public:
using result_type = RealType;
class param_type {
public:
using distribution_type = beta_distribution;
explicit param_type(result_type alpha, result_type beta)
: alpha_(alpha), beta_(beta) {
assert(alpha >= 0);
assert(beta >= 0);
assert(alpha <= (std::numeric_limits<result_type>::max)());
assert(beta <= (std::numeric_limits<result_type>::max)());
if (alpha == 0 || beta == 0) {
method_ = DEGENERATE_SMALL;
x_ = (alpha >= beta) ? 1 : 0;
return;
}
// a_ = min(beta, alpha), b_ = max(beta, alpha).
if (beta < alpha) {
inverted_ = true;
a_ = beta;
b_ = alpha;
} else {
inverted_ = false;
a_ = alpha;
b_ = beta;
}
if (a_ <= 1 && b_ >= ThresholdForLargeA()) {
method_ = DEGENERATE_SMALL;
x_ = inverted_ ? result_type(1) : result_type(0);
return;
}
// For threshold values, see also:
// Evaluation of Beta Generation Algorithms, Ying-Chao Hung, et. al.
// February, 2009.
if ((b_ < 1.0 && a_ + b_ <= 1.2) || a_ <= ThresholdForSmallA()) {
// Choose Joehnk over Cheng when it's faster or when Cheng encounters
// numerical issues.
method_ = JOEHNK;
a_ = result_type(1) / alpha_;
b_ = result_type(1) / beta_;
if (std::isinf(a_) || std::isinf(b_)) {
method_ = DEGENERATE_SMALL;
x_ = inverted_ ? result_type(1) : result_type(0);
}
return;
}
if (a_ >= ThresholdForLargeA()) {
method_ = DEGENERATE_LARGE;
// Note: on PPC for long double, evaluating
// `std::numeric_limits::max() / ThresholdForLargeA` results in NaN.
result_type r = a_ / b_;
x_ = (inverted_ ? result_type(1) : r) / (1 + r);
return;
}
x_ = a_ + b_;
log_x_ = std::log(x_);
if (a_ <= 1) {
method_ = CHENG_BA;
y_ = result_type(1) / a_;
gamma_ = a_ + a_;
return;
}
method_ = CHENG_BB;
result_type r = (a_ - 1) / (b_ - 1);
y_ = std::sqrt((1 + r) / (b_ * r * 2 - r + 1));
gamma_ = a_ + result_type(1) / y_;
}
result_type alpha() const { return alpha_; }
result_type beta() const { return beta_; }
friend bool operator==(const param_type& a, const param_type& b) {
return a.alpha_ == b.alpha_ && a.beta_ == b.beta_;
}
friend bool operator!=(const param_type& a, const param_type& b) {
return !(a == b);
}
private:
friend class beta_distribution;
#ifdef _MSC_VER
// MSVC does not have constexpr implementations for std::log and std::exp
// so they are computed at runtime.
#define ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR
#else
#define ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR constexpr
#endif
// The threshold for whether std::exp(1/a) is finite.
// Note that this value is quite large, and a smaller a_ is NOT abnormal.
static ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR result_type
ThresholdForSmallA() {
return result_type(1) /
std::log((std::numeric_limits<result_type>::max)());
}
// The threshold for whether a * std::log(a) is finite.
static ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR result_type
ThresholdForLargeA() {
return std::exp(
std::log((std::numeric_limits<result_type>::max)()) -
std::log(std::log((std::numeric_limits<result_type>::max)())) -
ThresholdPadding());
}
#undef ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR
// Pad the threshold for large A for long double on PPC. This is done via a
// template specialization below.
static constexpr result_type ThresholdPadding() { return 0; }
enum Method {
JOEHNK, // Uses algorithm Joehnk
CHENG_BA, // Uses algorithm BA in Cheng
CHENG_BB, // Uses algorithm BB in Cheng
// Note: See also:
// Hung et al. Evaluation of beta generation algorithms. Communications
// in Statistics-Simulation and Computation 38.4 (2009): 750-770.
// especially:
// Zechner, Heinz, and Ernst Stadlober. Generating beta variates via
// patchwork rejection. Computing 50.1 (1993): 1-18.
DEGENERATE_SMALL, // a_ is abnormally small.
DEGENERATE_LARGE, // a_ is abnormally large.
};
result_type alpha_;
result_type beta_;
result_type a_; // the smaller of {alpha, beta}, or 1.0/alpha_ in JOEHNK
result_type b_; // the larger of {alpha, beta}, or 1.0/beta_ in JOEHNK
result_type x_; // alpha + beta, or the result in degenerate cases
result_type log_x_; // log(x_)
result_type y_; // "beta" in Cheng
result_type gamma_; // "gamma" in Cheng
Method method_;
// Placing this last for optimal alignment.
// Whether alpha_ != a_, i.e. true iff alpha_ > beta_.
bool inverted_;
static_assert(std::is_floating_point<RealType>::value,
"Class-template absl::beta_distribution<> must be "
"parameterized using a floating-point type.");
};
beta_distribution() : beta_distribution(1) {}
explicit beta_distribution(result_type alpha, result_type beta = 1)
: param_(alpha, beta) {}
explicit beta_distribution(const param_type& p) : param_(p) {}
void reset() {}
// Generating functions
template <typename URBG>
result_type operator()(URBG& g) { // NOLINT(runtime/references)
return (*this)(g, param_);
}
template <typename URBG>
result_type operator()(URBG& g, // NOLINT(runtime/references)
const param_type& p);
param_type param() const { return param_; }
void param(const param_type& p) { param_ = p; }
result_type(min)() const { return 0; }
result_type(max)() const { return 1; }
result_type alpha() const { return param_.alpha(); }
result_type beta() const { return param_.beta(); }
friend bool operator==(const beta_distribution& a,
const beta_distribution& b) {
return a.param_ == b.param_;
}
friend bool operator!=(const beta_distribution& a,
const beta_distribution& b) {
return a.param_ != b.param_;
}
private:
template <typename URBG>
result_type AlgorithmJoehnk(URBG& g, // NOLINT(runtime/references)
const param_type& p);
template <typename URBG>
result_type AlgorithmCheng(URBG& g, // NOLINT(runtime/references)
const param_type& p);
template <typename URBG>
result_type DegenerateCase(URBG& g, // NOLINT(runtime/references)
const param_type& p) {
if (p.method_ == param_type::DEGENERATE_SMALL && p.alpha_ == p.beta_) {
// Returns 0 or 1 with equal probability.
random_internal::FastUniformBits<uint8_t> fast_u8;
return static_cast<result_type>((fast_u8(g) & 0x10) !=
0); // pick any single bit.
}
return p.x_;
}
param_type param_;
random_internal::FastUniformBits<uint64_t> fast_u64_;
};
#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \
defined(__ppc__) || defined(__PPC__)
// PPC needs a more stringent boundary for long double.
template <>
constexpr long double
beta_distribution<long double>::param_type::ThresholdPadding() {
return 10;
}
#endif
template <typename RealType>
template <typename URBG>
typename beta_distribution<RealType>::result_type
beta_distribution<RealType>::AlgorithmJoehnk(
URBG& g, // NOLINT(runtime/references)
const param_type& p) {
using random_internal::GeneratePositiveTag;
using random_internal::GenerateRealFromBits;
using real_type =
absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
// Based on Joehnk, M. D. Erzeugung von betaverteilten und gammaverteilten
// Zufallszahlen. Metrika 8.1 (1964): 5-15.
// This method is described in Knuth, Vol 2 (Third Edition), pp 134.
result_type u, v, x, y, z;
for (;;) {
u = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
fast_u64_(g));
v = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
fast_u64_(g));
// Direct method. std::pow is slow for float, so rely on the optimizer to
// remove the std::pow() path for that case.
if (!std::is_same<float, result_type>::value) {
x = std::pow(u, p.a_);
y = std::pow(v, p.b_);
z = x + y;
if (z > 1) {
// Reject if and only if `x + y > 1.0`
continue;
}
if (z > 0) {
// When both alpha and beta are small, x and y are both close to 0, so
// divide by (x+y) directly may result in nan.
return x / z;
}
}
// Log transform.
// x = log( pow(u, p.a_) ), y = log( pow(v, p.b_) )
// since u, v <= 1.0, x, y < 0.
x = std::log(u) * p.a_;
y = std::log(v) * p.b_;
if (!std::isfinite(x) || !std::isfinite(y)) {
continue;
}
// z = log( pow(u, a) + pow(v, b) )
z = x > y ? (x + std::log(1 + std::exp(y - x)))
: (y + std::log(1 + std::exp(x - y)));
// Reject iff log(x+y) > 0.
if (z > 0) {
continue;
}
return std::exp(x - z);
}
}
template <typename RealType>
template <typename URBG>
typename beta_distribution<RealType>::result_type
beta_distribution<RealType>::AlgorithmCheng(
URBG& g, // NOLINT(runtime/references)
const param_type& p) {
using random_internal::GeneratePositiveTag;
using random_internal::GenerateRealFromBits;
using real_type =
absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
// Based on Cheng, Russell CH. Generating beta variates with nonintegral
// shape parameters. Communications of the ACM 21.4 (1978): 317-322.
// (https://dl.acm.org/citation.cfm?id=359482).
static constexpr result_type kLogFour =
result_type(1.3862943611198906188344642429163531361); // log(4)
static constexpr result_type kS =
result_type(2.6094379124341003746007593332261876); // 1+log(5)
const bool use_algorithm_ba = (p.method_ == param_type::CHENG_BA);
result_type u1, u2, v, w, z, r, s, t, bw_inv, lhs;
for (;;) {
u1 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
fast_u64_(g));
u2 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
fast_u64_(g));
v = p.y_ * std::log(u1 / (1 - u1));
w = p.a_ * std::exp(v);
bw_inv = result_type(1) / (p.b_ + w);
r = p.gamma_ * v - kLogFour;
s = p.a_ + r - w;
z = u1 * u1 * u2;
if (!use_algorithm_ba && s + kS >= 5 * z) {
break;
}
t = std::log(z);
if (!use_algorithm_ba && s >= t) {
break;
}
lhs = p.x_ * (p.log_x_ + std::log(bw_inv)) + r;
if (lhs >= t) {
break;
}
}
return p.inverted_ ? (1 - w * bw_inv) : w * bw_inv;
}
template <typename RealType>
template <typename URBG>
typename beta_distribution<RealType>::result_type
beta_distribution<RealType>::operator()(URBG& g, // NOLINT(runtime/references)
const param_type& p) {
switch (p.method_) {
case param_type::JOEHNK:
return AlgorithmJoehnk(g, p);
case param_type::CHENG_BA:
ABSL_FALLTHROUGH_INTENDED;
case param_type::CHENG_BB:
return AlgorithmCheng(g, p);
default:
return DegenerateCase(g, p);
}
}
template <typename CharT, typename Traits, typename RealType>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const beta_distribution<RealType>& x) {
auto saver = random_internal::make_ostream_state_saver(os);
os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);
os << x.alpha() << os.fill() << x.beta();
return os;
}
template <typename CharT, typename Traits, typename RealType>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
beta_distribution<RealType>& x) { // NOLINT(runtime/references)
using result_type = typename beta_distribution<RealType>::result_type;
using param_type = typename beta_distribution<RealType>::param_type;
result_type alpha, beta;
auto saver = random_internal::make_istream_state_saver(is);
alpha = random_internal::read_floating_point<result_type>(is);
if (is.fail()) return is;
beta = random_internal::read_floating_point<result_type>(is);
if (!is.fail()) {
x.param(param_type(alpha, beta));
}
return is;
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_BETA_DISTRIBUTION_H_

185
Pods/abseil/absl/random/bit_gen_ref.h generated Normal file
View File

@@ -0,0 +1,185 @@
//
// Copyright 2018 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: bit_gen_ref.h
// -----------------------------------------------------------------------------
//
// This header defines a bit generator "reference" class, for use in interfaces
// that take both Abseil (e.g. `absl::BitGen`) and standard library (e.g.
// `std::mt19937`) bit generators.
#ifndef ABSL_RANDOM_BIT_GEN_REF_H_
#define ABSL_RANDOM_BIT_GEN_REF_H_
#include <limits>
#include <type_traits>
#include <utility>
#include "absl/base/internal/fast_type_id.h"
#include "absl/base/macros.h"
#include "absl/meta/type_traits.h"
#include "absl/random/internal/distribution_caller.h"
#include "absl/random/internal/fast_uniform_bits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
template <typename URBG, typename = void, typename = void, typename = void>
struct is_urbg : std::false_type {};
template <typename URBG>
struct is_urbg<
URBG,
absl::enable_if_t<std::is_same<
typename URBG::result_type,
typename std::decay<decltype((URBG::min)())>::type>::value>,
absl::enable_if_t<std::is_same<
typename URBG::result_type,
typename std::decay<decltype((URBG::max)())>::type>::value>,
absl::enable_if_t<std::is_same<
typename URBG::result_type,
typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
: std::true_type {};
template <typename>
struct DistributionCaller;
class MockHelpers;
} // namespace random_internal
// -----------------------------------------------------------------------------
// absl::BitGenRef
// -----------------------------------------------------------------------------
//
// `absl::BitGenRef` is a type-erasing class that provides a generator-agnostic
// non-owning "reference" interface for use in place of any specific uniform
// random bit generator (URBG). This class may be used for both Abseil
// (e.g. `absl::BitGen`, `absl::InsecureBitGen`) and Standard library (e.g
// `std::mt19937`, `std::minstd_rand`) bit generators.
//
// Like other reference classes, `absl::BitGenRef` does not own the
// underlying bit generator, and the underlying instance must outlive the
// `absl::BitGenRef`.
//
// `absl::BitGenRef` is particularly useful when used with an
// `absl::MockingBitGen` to test specific paths in functions which use random
// values.
//
// Example:
// void TakesBitGenRef(absl::BitGenRef gen) {
// int x = absl::Uniform<int>(gen, 0, 1000);
// }
//
class BitGenRef {
// SFINAE to detect whether the URBG type includes a member matching
// bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
//
// These live inside BitGenRef so that they have friend access
// to MockingBitGen. (see similar methods in DistributionCaller).
template <template <class...> class Trait, class AlwaysVoid, class... Args>
struct detector : std::false_type {};
template <template <class...> class Trait, class... Args>
struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
: std::true_type {};
template <class T>
using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(),
std::declval<void*>()));
template <typename T>
using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
public:
BitGenRef(const BitGenRef&) = default;
BitGenRef(BitGenRef&&) = default;
BitGenRef& operator=(const BitGenRef&) = default;
BitGenRef& operator=(BitGenRef&&) = default;
template <typename URBG, typename absl::enable_if_t<
(!std::is_same<URBG, BitGenRef>::value &&
random_internal::is_urbg<URBG>::value &&
!HasInvokeMock<URBG>::value)>* = nullptr>
BitGenRef(URBG& gen) // NOLINT
: t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
mock_call_(NotAMock),
generate_impl_fn_(ImplFn<URBG>) {}
template <typename URBG,
typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
random_internal::is_urbg<URBG>::value &&
HasInvokeMock<URBG>::value)>* = nullptr>
BitGenRef(URBG& gen) // NOLINT
: t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
mock_call_(&MockCall<URBG>),
generate_impl_fn_(ImplFn<URBG>) {}
using result_type = uint64_t;
static constexpr result_type(min)() {
return (std::numeric_limits<result_type>::min)();
}
static constexpr result_type(max)() {
return (std::numeric_limits<result_type>::max)();
}
result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); }
private:
using impl_fn = result_type (*)(uintptr_t);
using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*,
void*);
template <typename URBG>
static result_type ImplFn(uintptr_t ptr) {
// Ensure that the return values from operator() fill the entire
// range promised by result_type, min() and max().
absl::random_internal::FastUniformBits<result_type> fast_uniform_bits;
return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr));
}
// Get a type-erased InvokeMock pointer.
template <typename URBG>
static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type,
void* result, void* arg_tuple) {
return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result,
arg_tuple);
}
static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) {
return false;
}
inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
void* result) {
if (mock_call_ == NotAMock) return false; // avoids an indirect call.
return mock_call_(t_erased_gen_ptr_, type, args_tuple, result);
}
uintptr_t t_erased_gen_ptr_;
mock_call_fn mock_call_;
impl_fn generate_impl_fn_;
template <typename>
friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock
friend class ::absl::random_internal::MockHelpers; // for InvokeMock
};
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_BIT_GEN_REF_H_

View File

@@ -0,0 +1,98 @@
// 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.
#include "absl/random/discrete_distribution.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Initializes the distribution table for Walker's Aliasing algorithm, described
// in Knuth, Vol 2. as well as in https://en.wikipedia.org/wiki/Alias_method
std::vector<std::pair<double, size_t>> InitDiscreteDistribution(
std::vector<double>* probabilities) {
// The empty-case should already be handled by the constructor.
assert(probabilities);
assert(!probabilities->empty());
// Step 1. Normalize the input probabilities to 1.0.
double sum = std::accumulate(std::begin(*probabilities),
std::end(*probabilities), 0.0);
if (std::fabs(sum - 1.0) > 1e-6) {
// Scale `probabilities` only when the sum is too far from 1.0. Scaling
// unconditionally will alter the probabilities slightly.
for (double& item : *probabilities) {
item = item / sum;
}
}
// Step 2. At this point `probabilities` is set to the conditional
// probabilities of each element which sum to 1.0, to within reasonable error.
// These values are used to construct the proportional probability tables for
// the selection phases of Walker's Aliasing algorithm.
//
// To construct the table, pick an element which is under-full (i.e., an
// element for which `(*probabilities)[i] < 1.0/n`), and pair it with an
// element which is over-full (i.e., an element for which
// `(*probabilities)[i] > 1.0/n`). The smaller value can always be retired.
// The larger may still be greater than 1.0/n, or may now be less than 1.0/n,
// and put back onto the appropriate collection.
const size_t n = probabilities->size();
std::vector<std::pair<double, size_t>> q;
q.reserve(n);
std::vector<size_t> over;
std::vector<size_t> under;
size_t idx = 0;
for (const double item : *probabilities) {
assert(item >= 0);
const double v = item * n;
q.emplace_back(v, 0);
if (v < 1.0) {
under.push_back(idx++);
} else {
over.push_back(idx++);
}
}
while (!over.empty() && !under.empty()) {
auto lo = under.back();
under.pop_back();
auto hi = over.back();
over.pop_back();
q[lo].second = hi;
const double r = q[hi].first - (1.0 - q[lo].first);
q[hi].first = r;
if (r < 1.0) {
under.push_back(hi);
} else {
over.push_back(hi);
}
}
// Due to rounding errors, there may be un-paired elements in either
// collection; these should all be values near 1.0. For these values, set `q`
// to 1.0 and set the alternate to the identity.
for (auto i : over) {
q[i] = {1.0, i};
}
for (auto i : under) {
q[i] = {1.0, i};
}
return q;
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl

View File

@@ -0,0 +1,247 @@
// 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.
#ifndef ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_
#define ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_
#include <cassert>
#include <cmath>
#include <istream>
#include <limits>
#include <numeric>
#include <type_traits>
#include <utility>
#include <vector>
#include "absl/random/bernoulli_distribution.h"
#include "absl/random/internal/iostream_state_saver.h"
#include "absl/random/uniform_int_distribution.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::discrete_distribution
//
// A discrete distribution produces random integers i, where 0 <= i < n
// distributed according to the discrete probability function:
//
// P(i|p0,...,pn1)=pi
//
// This class is an implementation of discrete_distribution (see
// [rand.dist.samp.discrete]).
//
// The algorithm used is Walker's Aliasing algorithm, described in Knuth, Vol 2.
// absl::discrete_distribution takes O(N) time to precompute the probabilities
// (where N is the number of possible outcomes in the distribution) at
// construction, and then takes O(1) time for each variate generation. Many
// other implementations also take O(N) time to construct an ordered sequence of
// partial sums, plus O(log N) time per variate to binary search.
//
template <typename IntType = int>
class discrete_distribution {
public:
using result_type = IntType;
class param_type {
public:
using distribution_type = discrete_distribution;
param_type() { init(); }
template <typename InputIterator>
explicit param_type(InputIterator begin, InputIterator end)
: p_(begin, end) {
init();
}
explicit param_type(std::initializer_list<double> weights) : p_(weights) {
init();
}
template <class UnaryOperation>
explicit param_type(size_t nw, double xmin, double xmax,
UnaryOperation fw) {
if (nw > 0) {
p_.reserve(nw);
double delta = (xmax - xmin) / static_cast<double>(nw);
assert(delta > 0);
double t = delta * 0.5;
for (size_t i = 0; i < nw; ++i) {
p_.push_back(fw(xmin + i * delta + t));
}
}
init();
}
const std::vector<double>& probabilities() const { return p_; }
size_t n() const { return p_.size() - 1; }
friend bool operator==(const param_type& a, const param_type& b) {
return a.probabilities() == b.probabilities();
}
friend bool operator!=(const param_type& a, const param_type& b) {
return !(a == b);
}
private:
friend class discrete_distribution;
void init();
std::vector<double> p_; // normalized probabilities
std::vector<std::pair<double, size_t>> q_; // (acceptance, alternate) pairs
static_assert(std::is_integral<result_type>::value,
"Class-template absl::discrete_distribution<> must be "
"parameterized using an integral type.");
};
discrete_distribution() : param_() {}
explicit discrete_distribution(const param_type& p) : param_(p) {}
template <typename InputIterator>
explicit discrete_distribution(InputIterator begin, InputIterator end)
: param_(begin, end) {}
explicit discrete_distribution(std::initializer_list<double> weights)
: param_(weights) {}
template <class UnaryOperation>
explicit discrete_distribution(size_t nw, double xmin, double xmax,
UnaryOperation fw)
: param_(nw, xmin, xmax, std::move(fw)) {}
void reset() {}
// generating functions
template <typename URBG>
result_type operator()(URBG& g) { // NOLINT(runtime/references)
return (*this)(g, param_);
}
template <typename URBG>
result_type operator()(URBG& g, // NOLINT(runtime/references)
const param_type& p);
const param_type& param() const { return param_; }
void param(const param_type& p) { param_ = p; }
result_type(min)() const { return 0; }
result_type(max)() const {
return static_cast<result_type>(param_.n());
} // inclusive
// NOTE [rand.dist.sample.discrete] returns a std::vector<double> not a
// const std::vector<double>&.
const std::vector<double>& probabilities() const {
return param_.probabilities();
}
friend bool operator==(const discrete_distribution& a,
const discrete_distribution& b) {
return a.param_ == b.param_;
}
friend bool operator!=(const discrete_distribution& a,
const discrete_distribution& b) {
return a.param_ != b.param_;
}
private:
param_type param_;
};
// --------------------------------------------------------------------------
// Implementation details only below
// --------------------------------------------------------------------------
namespace random_internal {
// Using the vector `*probabilities`, whose values are the weights or
// probabilities of an element being selected, constructs the proportional
// probabilities used by the discrete distribution. `*probabilities` will be
// scaled, if necessary, so that its entries sum to a value sufficiently close
// to 1.0.
std::vector<std::pair<double, size_t>> InitDiscreteDistribution(
std::vector<double>* probabilities);
} // namespace random_internal
template <typename IntType>
void discrete_distribution<IntType>::param_type::init() {
if (p_.empty()) {
p_.push_back(1.0);
q_.emplace_back(1.0, 0);
} else {
assert(n() <= (std::numeric_limits<IntType>::max)());
q_ = random_internal::InitDiscreteDistribution(&p_);
}
}
template <typename IntType>
template <typename URBG>
typename discrete_distribution<IntType>::result_type
discrete_distribution<IntType>::operator()(
URBG& g, // NOLINT(runtime/references)
const param_type& p) {
const auto idx = absl::uniform_int_distribution<result_type>(0, p.n())(g);
const auto& q = p.q_[idx];
const bool selected = absl::bernoulli_distribution(q.first)(g);
return selected ? idx : static_cast<result_type>(q.second);
}
template <typename CharT, typename Traits, typename IntType>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const discrete_distribution<IntType>& x) {
auto saver = random_internal::make_ostream_state_saver(os);
const auto& probabilities = x.param().probabilities();
os << probabilities.size();
os.precision(random_internal::stream_precision_helper<double>::kPrecision);
for (const auto& p : probabilities) {
os << os.fill() << p;
}
return os;
}
template <typename CharT, typename Traits, typename IntType>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
discrete_distribution<IntType>& x) { // NOLINT(runtime/references)
using param_type = typename discrete_distribution<IntType>::param_type;
auto saver = random_internal::make_istream_state_saver(is);
size_t n;
std::vector<double> p;
is >> n;
if (is.fail()) return is;
if (n > 0) {
p.reserve(n);
for (IntType i = 0; i < n && !is.fail(); ++i) {
auto tmp = random_internal::read_floating_point<double>(is);
if (is.fail()) return is;
p.push_back(tmp);
}
}
x.param(param_type(p.begin(), p.end()));
return is;
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_

452
Pods/abseil/absl/random/distributions.h generated Normal file
View File

@@ -0,0 +1,452 @@
// 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/distribution_caller.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_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, {});
// -----------------------------------------------------------------------------
// 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 (!random_internal::is_uniform_range_valid(a, b)) return lo;
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 (!random_internal::is_uniform_range_valid(a, b)) return lo;
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 (!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));
}
// 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 (!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));
}
// 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 https://en.wikipedia.org/wiki/Log-normal_distribution
//
// 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(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);
}
// -----------------------------------------------------------------------------
// 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(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);
}
// -----------------------------------------------------------------------------
// 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(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
} // namespace absl
#endif // ABSL_RANDOM_DISTRIBUTIONS_H_

View File

@@ -0,0 +1,165 @@
// 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.
#ifndef ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_
#define ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_
#include <cassert>
#include <cmath>
#include <istream>
#include <limits>
#include <type_traits>
#include "absl/meta/type_traits.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/random/internal/generate_real.h"
#include "absl/random/internal/iostream_state_saver.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::exponential_distribution:
// Generates a number conforming to an exponential distribution and is
// equivalent to the standard [rand.dist.pois.exp] distribution.
template <typename RealType = double>
class exponential_distribution {
public:
using result_type = RealType;
class param_type {
public:
using distribution_type = exponential_distribution;
explicit param_type(result_type lambda = 1) : lambda_(lambda) {
assert(lambda > 0);
neg_inv_lambda_ = -result_type(1) / lambda_;
}
result_type lambda() const { return lambda_; }
friend bool operator==(const param_type& a, const param_type& b) {
return a.lambda_ == b.lambda_;
}
friend bool operator!=(const param_type& a, const param_type& b) {
return !(a == b);
}
private:
friend class exponential_distribution;
result_type lambda_;
result_type neg_inv_lambda_;
static_assert(
std::is_floating_point<RealType>::value,
"Class-template absl::exponential_distribution<> must be parameterized "
"using a floating-point type.");
};
exponential_distribution() : exponential_distribution(1) {}
explicit exponential_distribution(result_type lambda) : param_(lambda) {}
explicit exponential_distribution(const param_type& p) : param_(p) {}
void reset() {}
// Generating functions
template <typename URBG>
result_type operator()(URBG& g) { // NOLINT(runtime/references)
return (*this)(g, param_);
}
template <typename URBG>
result_type operator()(URBG& g, // NOLINT(runtime/references)
const param_type& p);
param_type param() const { return param_; }
void param(const param_type& p) { param_ = p; }
result_type(min)() const { return 0; }
result_type(max)() const {
return std::numeric_limits<result_type>::infinity();
}
result_type lambda() const { return param_.lambda(); }
friend bool operator==(const exponential_distribution& a,
const exponential_distribution& b) {
return a.param_ == b.param_;
}
friend bool operator!=(const exponential_distribution& a,
const exponential_distribution& b) {
return a.param_ != b.param_;
}
private:
param_type param_;
random_internal::FastUniformBits<uint64_t> fast_u64_;
};
// --------------------------------------------------------------------------
// Implementation details follow
// --------------------------------------------------------------------------
template <typename RealType>
template <typename URBG>
typename exponential_distribution<RealType>::result_type
exponential_distribution<RealType>::operator()(
URBG& g, // NOLINT(runtime/references)
const param_type& p) {
using random_internal::GenerateNegativeTag;
using random_internal::GenerateRealFromBits;
using real_type =
absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
const result_type u = GenerateRealFromBits<real_type, GenerateNegativeTag,
false>(fast_u64_(g)); // U(-1, 0)
// log1p(-x) is mathematically equivalent to log(1 - x) but has more
// accuracy for x near zero.
return p.neg_inv_lambda_ * std::log1p(u);
}
template <typename CharT, typename Traits, typename RealType>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const exponential_distribution<RealType>& x) {
auto saver = random_internal::make_ostream_state_saver(os);
os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);
os << x.lambda();
return os;
}
template <typename CharT, typename Traits, typename RealType>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
exponential_distribution<RealType>& x) { // NOLINT(runtime/references)
using result_type = typename exponential_distribution<RealType>::result_type;
using param_type = typename exponential_distribution<RealType>::param_type;
result_type lambda;
auto saver = random_internal::make_istream_state_saver(is);
lambda = random_internal::read_floating_point<result_type>(is);
if (!is.fail()) {
x.param(param_type(lambda));
}
return is;
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_

View File

@@ -0,0 +1,104 @@
// BEGIN GENERATED CODE; DO NOT EDIT
// clang-format off
#include "absl/random/gaussian_distribution.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
const gaussian_distribution_base::Tables
gaussian_distribution_base::zg_ = {
{3.7130862467425505, 3.442619855899000214, 3.223084984581141565,
3.083228858216868318, 2.978696252647779819, 2.894344007021528942,
2.82312535054891045, 2.761169372387176857, 2.706113573121819549,
2.656406411261359679, 2.610972248431847387, 2.56903362592493778,
2.530009672388827457, 2.493454522095372106, 2.459018177411830486,
2.426420645533749809, 2.395434278011062457, 2.365871370117638595,
2.337575241339236776, 2.310413683698762988, 2.284274059677471769,
2.25905957386919809, 2.234686395590979036, 2.21108140887870297,
2.188180432076048731, 2.165926793748921497, 2.144270182360394905,
2.123165708673976138, 2.102573135189237608, 2.082456237992015957,
2.062782274508307978, 2.043521536655067194, 2.02464697337738464,
2.006133869963471206, 1.987959574127619033, 1.970103260854325633,
1.952545729553555764, 1.935269228296621957, 1.918257300864508963,
1.901494653105150423, 1.884967035707758143, 1.868661140994487768,
1.852564511728090002, 1.836665460258444904, 1.820952996596124418,
1.805416764219227366, 1.790046982599857506, 1.77483439558606837,
1.759770224899592339, 1.744846128113799244, 1.730054160563729182,
1.71538674071366648, 1.700836618569915748, 1.686396846779167014,
1.6720607540975998, 1.657821920954023254, 1.643674156862867441,
1.629611479470633562, 1.615628095043159629, 1.601718380221376581,
1.587876864890574558, 1.574098216022999264, 1.560377222366167382,
1.546708779859908844, 1.533087877674041755, 1.519509584765938559,
1.505969036863201937, 1.492461423781352714, 1.478981976989922842,
1.465525957342709296, 1.452088642889222792, 1.438665316684561546,
1.425251254514058319, 1.411841712447055919, 1.398431914131003539,
1.385017037732650058, 1.371592202427340812, 1.358152454330141534,
1.34469275175354519, 1.331207949665625279, 1.317692783209412299,
1.304141850128615054, 1.290549591926194894, 1.27691027356015363,
1.263217961454619287, 1.249466499573066436, 1.23564948326336066,
1.221760230539994385, 1.207791750415947662, 1.193736707833126465,
1.17958738466398616, 1.165335636164750222, 1.150972842148865416,
1.136489852013158774, 1.121876922582540237, 1.107123647534034028,
1.092218876907275371, 1.077150624892893482, 1.061905963694822042,
1.046470900764042922, 1.030830236068192907, 1.014967395251327842,
0.9988642334929808131, 0.9825008035154263464, 0.9658550794011470098,
0.9489026255113034436, 0.9316161966151479401, 0.9139652510230292792,
0.8959153525809346874, 0.8774274291129204872, 0.8584568431938099931,
0.8389522142975741614, 0.8188539067003538507, 0.7980920606440534693,
0.7765839878947563557, 0.7542306644540520688, 0.7309119106424850631,
0.7064796113354325779, 0.6807479186691505202, 0.6534786387399710295,
0.6243585973360461505, 0.5929629424714434327, 0.5586921784081798625,
0.5206560387620546848, 0.4774378372966830431, 0.4265479863554152429,
0.3628714310970211909, 0.2723208648139477384, 0},
{0.001014352564120377413, 0.002669629083880922793, 0.005548995220771345792,
0.008624484412859888607, 0.01183947865788486861, 0.01516729801054656976,
0.01859210273701129151, 0.02210330461592709475, 0.02569329193593428151,
0.02935631744000685023, 0.03308788614622575758, 0.03688438878665621645,
0.04074286807444417458, 0.04466086220049143157, 0.04863629585986780496,
0.05266740190305100461, 0.05675266348104984759, 0.06089077034804041277,
0.06508058521306804567, 0.06932111739357792179, 0.07361150188411341722,
0.07795098251397346301, 0.08233889824223575293, 0.08677467189478028919,
0.09125780082683036809, 0.095787849121731522, 0.1003644410286559929,
0.1049872554094214289, 0.1096560210148404546, 0.1143705124488661323,
0.1191305467076509556, 0.1239359802028679736, 0.1287867061959434012,
0.1336826525834396151, 0.1386237799845948804, 0.1436100800906280339,
0.1486415742423425057, 0.1537183122081819397, 0.1588403711394795748,
0.1640078546834206341, 0.1692208922373653057, 0.1744796383307898324,
0.1797842721232958407, 0.1851349970089926078, 0.1905320403191375633,
0.1959756531162781534, 0.2014661100743140865, 0.2070037094399269362,
0.2125887730717307134, 0.2182216465543058426, 0.2239026993850088965,
0.229632325232116602, 0.2354109422634795556, 0.2412389935454402889,
0.2471169475123218551, 0.2530452985073261551, 0.2590245673962052742,
0.2650553022555897087, 0.271138079138385224, 0.2772735029191887857,
0.2834622082232336471, 0.2897048604429605656, 0.2960021568469337061,
0.3023548277864842593, 0.3087636380061818397, 0.3152293880650116065,
0.3217529158759855901, 0.3283350983728509642, 0.3349768533135899506,
0.3416791412315512977, 0.3484429675463274756, 0.355269384847918035,
0.3621594953693184626, 0.3691144536644731522, 0.376135469510563536,
0.3832238110559021416, 0.3903808082373155797, 0.3976078564938743676,
0.404906420807223999, 0.4122780401026620578, 0.4197243320495753771,
0.4272469983049970721, 0.4348478302499918513, 0.4425287152754694975,
0.4502916436820402768, 0.458138716267873114, 0.4660721526894572309,
0.4740943006930180559, 0.4822076463294863724, 0.4904148252838453348,
0.4987186354709807201, 0.5071220510755701794, 0.5156282382440030565,
0.5242405726729852944, 0.5329626593838373561, 0.5417983550254266145,
0.5507517931146057588, 0.5598274127040882009, 0.5690299910679523787,
0.5783646811197646898, 0.5878370544347081283, 0.5974531509445183408,
0.6072195366251219584, 0.6171433708188825973, 0.6272324852499290282,
0.6374954773350440806, 0.6479418211102242475, 0.6585820000500898219,
0.6694276673488921414, 0.6804918409973358395, 0.6917891434366769676,
0.7033360990161600101, 0.7151515074105005976, 0.7272569183441868201,
0.7396772436726493094, 0.7524415591746134169, 0.7655841738977066102,
0.7791460859296898134, 0.7931770117713072832, 0.8077382946829627652,
0.8229072113814113187, 0.8387836052959920519, 0.8555006078694531446,
0.873243048910072206, 0.8922816507840289901, 0.9130436479717434217,
0.9362826816850632339, 0.9635996931270905952, 1}};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
// clang-format on
// END GENERATED CODE

View File

@@ -0,0 +1,275 @@
// 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.
#ifndef ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_
#define ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_
// absl::gaussian_distribution implements the Ziggurat algorithm
// for generating random gaussian numbers.
//
// Implementation based on "The Ziggurat Method for Generating Random Variables"
// by George Marsaglia and Wai Wan Tsang: http://www.jstatsoft.org/v05/i08/
//
#include <cmath>
#include <cstdint>
#include <istream>
#include <limits>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/random/internal/generate_real.h"
#include "absl/random/internal/iostream_state_saver.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// absl::gaussian_distribution_base implements the underlying ziggurat algorithm
// using the ziggurat tables generated by the gaussian_distribution_gentables
// binary.
//
// The specific algorithm has some of the improvements suggested by the
// 2005 paper, "An Improved Ziggurat Method to Generate Normal Random Samples",
// Jurgen A Doornik. (https://www.doornik.com/research/ziggurat.pdf)
class ABSL_DLL gaussian_distribution_base {
public:
template <typename URBG>
inline double zignor(URBG& g); // NOLINT(runtime/references)
private:
friend class TableGenerator;
template <typename URBG>
inline double zignor_fallback(URBG& g, // NOLINT(runtime/references)
bool neg);
// Constants used for the gaussian distribution.
static constexpr double kR = 3.442619855899; // Start of the tail.
static constexpr double kRInv = 0.29047645161474317; // ~= (1.0 / kR) .
static constexpr double kV = 9.91256303526217e-3;
static constexpr uint64_t kMask = 0x07f;
// The ziggurat tables store the pdf(f) and inverse-pdf(x) for equal-area
// points on one-half of the normal distribution, where the pdf function,
// pdf = e ^ (-1/2 *x^2), assumes that the mean = 0 & stddev = 1.
//
// These tables are just over 2kb in size; larger tables might improve the
// distributions, but also lead to more cache pollution.
//
// x = {3.71308, 3.44261, 3.22308, ..., 0}
// f = {0.00101, 0.00266, 0.00554, ..., 1}
struct Tables {
double x[kMask + 2];
double f[kMask + 2];
};
static const Tables zg_;
random_internal::FastUniformBits<uint64_t> fast_u64_;
};
} // namespace random_internal
// absl::gaussian_distribution:
// Generates a number conforming to a Gaussian distribution.
template <typename RealType = double>
class gaussian_distribution : random_internal::gaussian_distribution_base {
public:
using result_type = RealType;
class param_type {
public:
using distribution_type = gaussian_distribution;
explicit param_type(result_type mean = 0, result_type stddev = 1)
: mean_(mean), stddev_(stddev) {}
// Returns the mean distribution parameter. The mean specifies the location
// of the peak. The default value is 0.0.
result_type mean() const { return mean_; }
// Returns the deviation distribution parameter. The default value is 1.0.
result_type stddev() const { return stddev_; }
friend bool operator==(const param_type& a, const param_type& b) {
return a.mean_ == b.mean_ && a.stddev_ == b.stddev_;
}
friend bool operator!=(const param_type& a, const param_type& b) {
return !(a == b);
}
private:
result_type mean_;
result_type stddev_;
static_assert(
std::is_floating_point<RealType>::value,
"Class-template absl::gaussian_distribution<> must be parameterized "
"using a floating-point type.");
};
gaussian_distribution() : gaussian_distribution(0) {}
explicit gaussian_distribution(result_type mean, result_type stddev = 1)
: param_(mean, stddev) {}
explicit gaussian_distribution(const param_type& p) : param_(p) {}
void reset() {}
// Generating functions
template <typename URBG>
result_type operator()(URBG& g) { // NOLINT(runtime/references)
return (*this)(g, param_);
}
template <typename URBG>
result_type operator()(URBG& g, // NOLINT(runtime/references)
const param_type& p);
param_type param() const { return param_; }
void param(const param_type& p) { param_ = p; }
result_type(min)() const {
return -std::numeric_limits<result_type>::infinity();
}
result_type(max)() const {
return std::numeric_limits<result_type>::infinity();
}
result_type mean() const { return param_.mean(); }
result_type stddev() const { return param_.stddev(); }
friend bool operator==(const gaussian_distribution& a,
const gaussian_distribution& b) {
return a.param_ == b.param_;
}
friend bool operator!=(const gaussian_distribution& a,
const gaussian_distribution& b) {
return a.param_ != b.param_;
}
private:
param_type param_;
};
// --------------------------------------------------------------------------
// Implementation details only below
// --------------------------------------------------------------------------
template <typename RealType>
template <typename URBG>
typename gaussian_distribution<RealType>::result_type
gaussian_distribution<RealType>::operator()(
URBG& g, // NOLINT(runtime/references)
const param_type& p) {
return p.mean() + p.stddev() * static_cast<result_type>(zignor(g));
}
template <typename CharT, typename Traits, typename RealType>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const gaussian_distribution<RealType>& x) {
auto saver = random_internal::make_ostream_state_saver(os);
os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);
os << x.mean() << os.fill() << x.stddev();
return os;
}
template <typename CharT, typename Traits, typename RealType>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
gaussian_distribution<RealType>& x) { // NOLINT(runtime/references)
using result_type = typename gaussian_distribution<RealType>::result_type;
using param_type = typename gaussian_distribution<RealType>::param_type;
auto saver = random_internal::make_istream_state_saver(is);
auto mean = random_internal::read_floating_point<result_type>(is);
if (is.fail()) return is;
auto stddev = random_internal::read_floating_point<result_type>(is);
if (!is.fail()) {
x.param(param_type(mean, stddev));
}
return is;
}
namespace random_internal {
template <typename URBG>
inline double gaussian_distribution_base::zignor_fallback(URBG& g, bool neg) {
using random_internal::GeneratePositiveTag;
using random_internal::GenerateRealFromBits;
// This fallback path happens approximately 0.05% of the time.
double x, y;
do {
// kRInv = 1/r, U(0, 1)
x = kRInv *
std::log(GenerateRealFromBits<double, GeneratePositiveTag, false>(
fast_u64_(g)));
y = -std::log(
GenerateRealFromBits<double, GeneratePositiveTag, false>(fast_u64_(g)));
} while ((y + y) < (x * x));
return neg ? (x - kR) : (kR - x);
}
template <typename URBG>
inline double gaussian_distribution_base::zignor(
URBG& g) { // NOLINT(runtime/references)
using random_internal::GeneratePositiveTag;
using random_internal::GenerateRealFromBits;
using random_internal::GenerateSignedTag;
while (true) {
// We use a single uint64_t to generate both a double and a strip.
// These bits are unused when the generated double is > 1/2^5.
// This may introduce some bias from the duplicated low bits of small
// values (those smaller than 1/2^5, which all end up on the left tail).
uint64_t bits = fast_u64_(g);
int i = static_cast<int>(bits & kMask); // pick a random strip
double j = GenerateRealFromBits<double, GenerateSignedTag, false>(
bits); // U(-1, 1)
const double x = j * zg_.x[i];
// Retangular box. Handles >97% of all cases.
// For any given box, this handles between 75% and 99% of values.
// Equivalent to U(01) < (x[i+1] / x[i]), and when i == 0, ~93.5%
if (std::abs(x) < zg_.x[i + 1]) {
return x;
}
// i == 0: Base box. Sample using a ratio of uniforms.
if (i == 0) {
// This path happens about 0.05% of the time.
return zignor_fallback(g, j < 0);
}
// i > 0: Wedge samples using precomputed values.
double v = GenerateRealFromBits<double, GeneratePositiveTag, false>(
fast_u64_(g)); // U(0, 1)
if ((zg_.f[i + 1] + v * (zg_.f[i] - zg_.f[i + 1])) <
std::exp(-0.5 * x * x)) {
return x;
}
// The wedge was missed; reject the value and try again.
}
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_

View File

@@ -0,0 +1,95 @@
//
// Copyright 2018 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.
//
#ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
#define ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
#include <utility>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/base/internal/fast_type_id.h"
#include "absl/utility/utility.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// DistributionCaller provides an opportunity to overload the general
// mechanism for calling a distribution, allowing for mock-RNG classes
// to intercept such calls.
template <typename URBG>
struct DistributionCaller {
static_assert(!std::is_pointer<URBG>::value,
"You must pass a reference, not a pointer.");
// SFINAE to detect whether the URBG type includes a member matching
// bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
//
// These live inside BitGenRef so that they have friend access
// to MockingBitGen. (see similar methods in DistributionCaller).
template <template <class...> class Trait, class AlwaysVoid, class... Args>
struct detector : std::false_type {};
template <template <class...> class Trait, class... Args>
struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
: std::true_type {};
template <class T>
using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
std::declval<::absl::base_internal::FastTypeIdType>(),
std::declval<void*>(), std::declval<void*>()));
using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
// Default implementation of distribution caller.
template <typename DistrT, typename... Args>
static typename DistrT::result_type Impl(std::false_type, URBG* urbg,
Args&&... args) {
DistrT dist(std::forward<Args>(args)...);
return dist(*urbg);
}
// Mock implementation of distribution caller.
// The underlying KeyT must match the KeyT constructed by MockOverloadSet.
template <typename DistrT, typename... Args>
static typename DistrT::result_type Impl(std::true_type, URBG* urbg,
Args&&... args) {
using ResultT = typename DistrT::result_type;
using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
using KeyT = ResultT(DistrT, ArgTupleT);
ArgTupleT arg_tuple(std::forward<Args>(args)...);
ResultT result;
if (!urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
&result)) {
auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
result = dist(*urbg);
}
return result;
}
// Default implementation of distribution caller.
template <typename DistrT, typename... Args>
static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,
std::forward<Args>(args)...);
}
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_

View File

@@ -0,0 +1,271 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
#define ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
#include <cstddef>
#include <cstdint>
#include <limits>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/meta/type_traits.h"
#include "absl/random/internal/traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Returns true if the input value is zero or a power of two. Useful for
// determining if the range of output values in a URBG
template <typename UIntType>
constexpr bool IsPowerOfTwoOrZero(UIntType n) {
return (n == 0) || ((n & (n - 1)) == 0);
}
// Computes the length of the range of values producible by the URBG, or returns
// zero if that would encompass the entire range of representable values in
// URBG::result_type.
template <typename URBG>
constexpr typename URBG::result_type RangeSize() {
using result_type = typename URBG::result_type;
static_assert((URBG::max)() != (URBG::min)(), "URBG range cannot be 0.");
return ((URBG::max)() == (std::numeric_limits<result_type>::max)() &&
(URBG::min)() == std::numeric_limits<result_type>::lowest())
? result_type{0}
: ((URBG::max)() - (URBG::min)() + result_type{1});
}
// Computes the floor of the log. (i.e., std::floor(std::log2(N));
template <typename UIntType>
constexpr UIntType IntegerLog2(UIntType n) {
return (n <= 1) ? 0 : 1 + IntegerLog2(n >> 1);
}
// Returns the number of bits of randomness returned through
// `PowerOfTwoVariate(urbg)`.
template <typename URBG>
constexpr size_t NumBits() {
return static_cast<size_t>(
RangeSize<URBG>() == 0
? std::numeric_limits<typename URBG::result_type>::digits
: IntegerLog2(RangeSize<URBG>()));
}
// Given a shift value `n`, constructs a mask with exactly the low `n` bits set.
// If `n == 0`, all bits are set.
template <typename UIntType>
constexpr UIntType MaskFromShift(size_t n) {
return ((n % std::numeric_limits<UIntType>::digits) == 0)
? ~UIntType{0}
: (UIntType{1} << n) - UIntType{1};
}
// Tags used to dispatch FastUniformBits::generate to the simple or more complex
// entropy extraction algorithm.
struct SimplifiedLoopTag {};
struct RejectionLoopTag {};
// FastUniformBits implements a fast path to acquire uniform independent bits
// from a type which conforms to the [rand.req.urbg] concept.
// Parameterized by:
// `UIntType`: the result (output) type
//
// The std::independent_bits_engine [rand.adapt.ibits] adaptor can be
// instantiated from an existing generator through a copy or a move. It does
// not, however, facilitate the production of pseudorandom bits from an un-owned
// generator that will outlive the std::independent_bits_engine instance.
template <typename UIntType = uint64_t>
class FastUniformBits {
public:
using result_type = UIntType;
static constexpr result_type(min)() { return 0; }
static constexpr result_type(max)() {
return (std::numeric_limits<result_type>::max)();
}
template <typename URBG>
result_type operator()(URBG& g); // NOLINT(runtime/references)
private:
static_assert(IsUnsigned<UIntType>::value,
"Class-template FastUniformBits<> must be parameterized using "
"an unsigned type.");
// Generate() generates a random value, dispatched on whether
// the underlying URBG must use rejection sampling to generate a value,
// or whether a simplified loop will suffice.
template <typename URBG>
result_type Generate(URBG& g, // NOLINT(runtime/references)
SimplifiedLoopTag);
template <typename URBG>
result_type Generate(URBG& g, // NOLINT(runtime/references)
RejectionLoopTag);
};
template <typename UIntType>
template <typename URBG>
typename FastUniformBits<UIntType>::result_type
FastUniformBits<UIntType>::operator()(URBG& g) { // NOLINT(runtime/references)
// kRangeMask is the mask used when sampling variates from the URBG when the
// width of the URBG range is not a power of 2.
// Y = (2 ^ kRange) - 1
static_assert((URBG::max)() > (URBG::min)(),
"URBG::max and URBG::min may not be equal.");
using tag = absl::conditional_t<IsPowerOfTwoOrZero(RangeSize<URBG>()),
SimplifiedLoopTag, RejectionLoopTag>;
return Generate(g, tag{});
}
template <typename UIntType>
template <typename URBG>
typename FastUniformBits<UIntType>::result_type
FastUniformBits<UIntType>::Generate(URBG& g, // NOLINT(runtime/references)
SimplifiedLoopTag) {
// The simplified version of FastUniformBits works only on URBGs that have
// a range that is a power of 2. In this case we simply loop and shift without
// attempting to balance the bits across calls.
static_assert(IsPowerOfTwoOrZero(RangeSize<URBG>()),
"incorrect Generate tag for URBG instance");
static constexpr size_t kResultBits =
std::numeric_limits<result_type>::digits;
static constexpr size_t kUrbgBits = NumBits<URBG>();
static constexpr size_t kIters =
(kResultBits / kUrbgBits) + (kResultBits % kUrbgBits != 0);
static constexpr size_t kShift = (kIters == 1) ? 0 : kUrbgBits;
static constexpr auto kMin = (URBG::min)();
result_type r = static_cast<result_type>(g() - kMin);
for (size_t n = 1; n < kIters; ++n) {
r = static_cast<result_type>(r << kShift) +
static_cast<result_type>(g() - kMin);
}
return r;
}
template <typename UIntType>
template <typename URBG>
typename FastUniformBits<UIntType>::result_type
FastUniformBits<UIntType>::Generate(URBG& g, // NOLINT(runtime/references)
RejectionLoopTag) {
static_assert(!IsPowerOfTwoOrZero(RangeSize<URBG>()),
"incorrect Generate tag for URBG instance");
using urbg_result_type = typename URBG::result_type;
// See [rand.adapt.ibits] for more details on the constants calculated below.
//
// It is preferable to use roughly the same number of bits from each generator
// call, however this is only possible when the number of bits provided by the
// URBG is a divisor of the number of bits in `result_type`. In all other
// cases, the number of bits used cannot always be the same, but it can be
// guaranteed to be off by at most 1. Thus we run two loops, one with a
// smaller bit-width size (`kSmallWidth`) and one with a larger width size
// (satisfying `kLargeWidth == kSmallWidth + 1`). The loops are run
// `kSmallIters` and `kLargeIters` times respectively such
// that
//
// `kResultBits == kSmallIters * kSmallBits
// + kLargeIters * kLargeBits`
//
// where `kResultBits` is the total number of bits in `result_type`.
//
static constexpr size_t kResultBits =
std::numeric_limits<result_type>::digits; // w
static constexpr urbg_result_type kUrbgRange = RangeSize<URBG>(); // R
static constexpr size_t kUrbgBits = NumBits<URBG>(); // m
// compute the initial estimate of the bits used.
// [rand.adapt.ibits] 2 (c)
static constexpr size_t kA = // ceil(w/m)
(kResultBits / kUrbgBits) + ((kResultBits % kUrbgBits) != 0); // n'
static constexpr size_t kABits = kResultBits / kA; // w0'
static constexpr urbg_result_type kARejection =
((kUrbgRange >> kABits) << kABits); // y0'
// refine the selection to reduce the rejection frequency.
static constexpr size_t kTotalIters =
((kUrbgRange - kARejection) <= (kARejection / kA)) ? kA : (kA + 1); // n
// [rand.adapt.ibits] 2 (b)
static constexpr size_t kSmallIters =
kTotalIters - (kResultBits % kTotalIters); // n0
static constexpr size_t kSmallBits = kResultBits / kTotalIters; // w0
static constexpr urbg_result_type kSmallRejection =
((kUrbgRange >> kSmallBits) << kSmallBits); // y0
static constexpr size_t kLargeBits = kSmallBits + 1; // w0+1
static constexpr urbg_result_type kLargeRejection =
((kUrbgRange >> kLargeBits) << kLargeBits); // y1
//
// Because `kLargeBits == kSmallBits + 1`, it follows that
//
// `kResultBits == kSmallIters * kSmallBits + kLargeIters`
//
// and therefore
//
// `kLargeIters == kTotalWidth % kSmallWidth`
//
// Intuitively, each iteration with the large width accounts for one unit
// of the remainder when `kTotalWidth` is divided by `kSmallWidth`. As
// mentioned above, if the URBG width is a divisor of `kTotalWidth`, then
// there would be no need for any large iterations (i.e., one loop would
// suffice), and indeed, in this case, `kLargeIters` would be zero.
static_assert(kResultBits == kSmallIters * kSmallBits +
(kTotalIters - kSmallIters) * kLargeBits,
"Error in looping constant calculations.");
// The small shift is essentially small bits, but due to the potential
// of generating a smaller result_type from a larger urbg type, the actual
// shift might be 0.
static constexpr size_t kSmallShift = kSmallBits % kResultBits;
static constexpr auto kSmallMask =
MaskFromShift<urbg_result_type>(kSmallShift);
static constexpr size_t kLargeShift = kLargeBits % kResultBits;
static constexpr auto kLargeMask =
MaskFromShift<urbg_result_type>(kLargeShift);
static constexpr auto kMin = (URBG::min)();
result_type s = 0;
for (size_t n = 0; n < kSmallIters; ++n) {
urbg_result_type v;
do {
v = g() - kMin;
} while (v >= kSmallRejection);
s = (s << kSmallShift) + static_cast<result_type>(v & kSmallMask);
}
for (size_t n = kSmallIters; n < kTotalIters; ++n) {
urbg_result_type v;
do {
v = g() - kMin;
} while (v >= kLargeRejection);
s = (s << kLargeShift) + static_cast<result_type>(v & kLargeMask);
}
return s;
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_

View File

@@ -0,0 +1,57 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_FASTMATH_H_
#define ABSL_RANDOM_INTERNAL_FASTMATH_H_
// This file contains fast math functions (bitwise ops as well as some others)
// which are implementation details of various absl random number distributions.
#include <cassert>
#include <cmath>
#include <cstdint>
#include "absl/numeric/bits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Compute log2(n) using integer operations.
// While std::log2 is more accurate than std::log(n) / std::log(2), for
// very large numbers--those close to std::numeric_limits<uint64_t>::max() - 2,
// for instance--std::log2 rounds up rather than down, which introduces
// definite skew in the results.
inline int IntLog2Floor(uint64_t n) {
return (n <= 1) ? 0 : (63 - countl_zero(n));
}
inline int IntLog2Ceil(uint64_t n) {
return (n <= 1) ? 0 : (64 - countl_zero(n - 1));
}
inline double StirlingLogFactorial(double n) {
assert(n >= 1);
// Using Stirling's approximation.
constexpr double kLog2PI = 1.83787706640934548356;
const double logn = std::log(n);
const double ninv = 1.0 / static_cast<double>(n);
return n * logn - n + 0.5 * (kLog2PI + logn) + (1.0 / 12.0) * ninv -
(1.0 / 360.0) * ninv * ninv * ninv;
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_FASTMATH_H_

View File

@@ -0,0 +1,144 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_
#define ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_
// This file contains some implementation details which are used by one or more
// of the absl random number distributions.
#include <cstdint>
#include <cstring>
#include <limits>
#include <type_traits>
#include "absl/meta/type_traits.h"
#include "absl/numeric/bits.h"
#include "absl/random/internal/fastmath.h"
#include "absl/random/internal/traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Tristate tag types controlling the output of GenerateRealFromBits.
struct GeneratePositiveTag {};
struct GenerateNegativeTag {};
struct GenerateSignedTag {};
// GenerateRealFromBits generates a single real value from a single 64-bit
// `bits` with template fields controlling the output.
//
// The `SignedTag` parameter controls whether positive, negative,
// or either signed/unsigned may be returned.
// When SignedTag == GeneratePositiveTag, range is U(0, 1)
// When SignedTag == GenerateNegativeTag, range is U(-1, 0)
// When SignedTag == GenerateSignedTag, range is U(-1, 1)
//
// When the `IncludeZero` parameter is true, the function may return 0 for some
// inputs, otherwise it never returns 0.
//
// When a value in U(0,1) is required, use:
// GenerateRealFromBits<double, PositiveValueT, true>;
//
// When a value in U(-1,1) is required, use:
// GenerateRealFromBits<double, SignedValueT, false>;
//
// This generates more distinct values than the mathematical equivalent
// `U(0, 1) * 2.0 - 1.0`.
//
// Scaling the result by powers of 2 (and avoiding a multiply) is also possible:
// GenerateRealFromBits<double>(..., -1); => U(0, 0.5)
// GenerateRealFromBits<double>(..., 1); => U(0, 2)
//
template <typename RealType, // Real type, either float or double.
typename SignedTag = GeneratePositiveTag, // Whether a positive,
// negative, or signed
// value is generated.
bool IncludeZero = true>
inline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 0) {
using real_type = RealType;
using uint_type = absl::conditional_t<std::is_same<real_type, float>::value,
uint32_t, uint64_t>;
static_assert(
(std::is_same<double, real_type>::value ||
std::is_same<float, real_type>::value),
"GenerateRealFromBits must be parameterized by either float or double.");
static_assert(sizeof(uint_type) == sizeof(real_type),
"Mismatched unsigned and real types.");
static_assert((std::numeric_limits<real_type>::is_iec559 &&
std::numeric_limits<real_type>::radix == 2),
"RealType representation is not IEEE 754 binary.");
static_assert((std::is_same<SignedTag, GeneratePositiveTag>::value ||
std::is_same<SignedTag, GenerateNegativeTag>::value ||
std::is_same<SignedTag, GenerateSignedTag>::value),
"");
static constexpr int kExp = std::numeric_limits<real_type>::digits - 1;
static constexpr uint_type kMask = (static_cast<uint_type>(1) << kExp) - 1u;
static constexpr int kUintBits = sizeof(uint_type) * 8;
int exp = exp_bias + int{std::numeric_limits<real_type>::max_exponent - 2};
// Determine the sign bit.
// Depending on the SignedTag, this may use the left-most bit
// or it may be a constant value.
uint_type sign = std::is_same<SignedTag, GenerateNegativeTag>::value
? (static_cast<uint_type>(1) << (kUintBits - 1))
: 0;
if (std::is_same<SignedTag, GenerateSignedTag>::value) {
if (std::is_same<uint_type, uint64_t>::value) {
sign = bits & uint64_t{0x8000000000000000};
}
if (std::is_same<uint_type, uint32_t>::value) {
const uint64_t tmp = bits & uint64_t{0x8000000000000000};
sign = static_cast<uint32_t>(tmp >> 32);
}
// adjust the bits and the exponent to account for removing
// the leading bit.
bits = bits & uint64_t{0x7FFFFFFFFFFFFFFF};
exp++;
}
if (IncludeZero) {
if (bits == 0u) return 0;
}
// Number of leading zeros is mapped to the exponent: 2^-clz
// bits is 0..01xxxxxx. After shifting, we're left with 1xxx...0..0
int clz = countl_zero(bits);
bits <<= (IncludeZero ? clz : (clz & 63)); // remove 0-bits.
exp -= clz; // set the exponent.
bits >>= (63 - kExp);
// Construct the 32-bit or 64-bit IEEE 754 floating-point value from
// the individual fields: sign, exp, mantissa(bits).
uint_type val = sign | (static_cast<uint_type>(exp) << kExp) |
(static_cast<uint_type>(bits) & kMask);
// bit_cast to the output-type
real_type result;
memcpy(static_cast<void*>(&result), static_cast<const void*>(&val),
sizeof(result));
return result;
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_

View File

@@ -0,0 +1,245 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_
#define ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_
#include <cmath>
#include <iostream>
#include <limits>
#include <type_traits>
#include "absl/meta/type_traits.h"
#include "absl/numeric/int128.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// The null_state_saver does nothing.
template <typename T>
class null_state_saver {
public:
using stream_type = T;
using flags_type = std::ios_base::fmtflags;
null_state_saver(T&, flags_type) {}
~null_state_saver() {}
};
// ostream_state_saver is a RAII object to save and restore the common
// basic_ostream flags used when implementing `operator <<()` on any of
// the absl random distributions.
template <typename OStream>
class ostream_state_saver {
public:
using ostream_type = OStream;
using flags_type = std::ios_base::fmtflags;
using fill_type = typename ostream_type::char_type;
using precision_type = std::streamsize;
ostream_state_saver(ostream_type& os, // NOLINT(runtime/references)
flags_type flags, fill_type fill)
: os_(os),
flags_(os.flags(flags)),
fill_(os.fill(fill)),
precision_(os.precision()) {
// Save state in initialized variables.
}
~ostream_state_saver() {
// Restore saved state.
os_.precision(precision_);
os_.fill(fill_);
os_.flags(flags_);
}
private:
ostream_type& os_;
const flags_type flags_;
const fill_type fill_;
const precision_type precision_;
};
#if defined(__NDK_MAJOR__) && __NDK_MAJOR__ < 16
#define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 1
#else
#define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 0
#endif
template <typename CharT, typename Traits>
ostream_state_saver<std::basic_ostream<CharT, Traits>> make_ostream_state_saver(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
std::ios_base::fmtflags flags = std::ios_base::dec | std::ios_base::left |
#if ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT
std::ios_base::fixed |
#endif
std::ios_base::scientific) {
using result_type = ostream_state_saver<std::basic_ostream<CharT, Traits>>;
return result_type(os, flags, os.widen(' '));
}
template <typename T>
typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
null_state_saver<T>>
make_ostream_state_saver(T& is, // NOLINT(runtime/references)
std::ios_base::fmtflags flags = std::ios_base::dec) {
std::cerr << "null_state_saver";
using result_type = null_state_saver<T>;
return result_type(is, flags);
}
// stream_precision_helper<type>::kPrecision returns the base 10 precision
// required to stream and reconstruct a real type exact binary value through
// a binary->decimal->binary transition.
template <typename T>
struct stream_precision_helper {
// max_digits10 may be 0 on MSVC; if so, use digits10 + 3.
static constexpr int kPrecision =
(std::numeric_limits<T>::max_digits10 > std::numeric_limits<T>::digits10)
? std::numeric_limits<T>::max_digits10
: (std::numeric_limits<T>::digits10 + 3);
};
template <>
struct stream_precision_helper<float> {
static constexpr int kPrecision = 9;
};
template <>
struct stream_precision_helper<double> {
static constexpr int kPrecision = 17;
};
template <>
struct stream_precision_helper<long double> {
static constexpr int kPrecision = 36; // assuming fp128
};
// istream_state_saver is a RAII object to save and restore the common
// std::basic_istream<> flags used when implementing `operator >>()` on any of
// the absl random distributions.
template <typename IStream>
class istream_state_saver {
public:
using istream_type = IStream;
using flags_type = std::ios_base::fmtflags;
istream_state_saver(istream_type& is, // NOLINT(runtime/references)
flags_type flags)
: is_(is), flags_(is.flags(flags)) {}
~istream_state_saver() { is_.flags(flags_); }
private:
istream_type& is_;
flags_type flags_;
};
template <typename CharT, typename Traits>
istream_state_saver<std::basic_istream<CharT, Traits>> make_istream_state_saver(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
std::ios_base::fmtflags flags = std::ios_base::dec |
std::ios_base::scientific |
std::ios_base::skipws) {
using result_type = istream_state_saver<std::basic_istream<CharT, Traits>>;
return result_type(is, flags);
}
template <typename T>
typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
null_state_saver<T>>
make_istream_state_saver(T& is, // NOLINT(runtime/references)
std::ios_base::fmtflags flags = std::ios_base::dec) {
using result_type = null_state_saver<T>;
return result_type(is, flags);
}
// stream_format_type<T> is a helper struct to convert types which
// basic_iostream cannot output as decimal numbers into types which
// basic_iostream can output as decimal numbers. Specifically:
// * signed/unsigned char-width types are converted to int.
// * TODO(lar): __int128 => uint128, except there is no operator << yet.
//
template <typename T>
struct stream_format_type
: public std::conditional<(sizeof(T) == sizeof(char)), int, T> {};
// stream_u128_helper allows us to write out either absl::uint128 or
// __uint128_t types in the same way, which enables their use as internal
// state of PRNG engines.
template <typename T>
struct stream_u128_helper;
template <>
struct stream_u128_helper<absl::uint128> {
template <typename IStream>
inline absl::uint128 read(IStream& in) {
uint64_t h = 0;
uint64_t l = 0;
in >> h >> l;
return absl::MakeUint128(h, l);
}
template <typename OStream>
inline void write(absl::uint128 val, OStream& out) {
uint64_t h = absl::Uint128High64(val);
uint64_t l = absl::Uint128Low64(val);
out << h << out.fill() << l;
}
};
#ifdef ABSL_HAVE_INTRINSIC_INT128
template <>
struct stream_u128_helper<__uint128_t> {
template <typename IStream>
inline __uint128_t read(IStream& in) {
uint64_t h = 0;
uint64_t l = 0;
in >> h >> l;
return (static_cast<__uint128_t>(h) << 64) | l;
}
template <typename OStream>
inline void write(__uint128_t val, OStream& out) {
uint64_t h = static_cast<uint64_t>(val >> 64u);
uint64_t l = static_cast<uint64_t>(val);
out << h << out.fill() << l;
}
};
#endif
template <typename FloatType, typename IStream>
inline FloatType read_floating_point(IStream& is) {
static_assert(std::is_floating_point<FloatType>::value, "");
FloatType dest;
is >> dest;
// Parsing a double value may report a subnormal value as an error
// despite being able to represent it.
// See https://stackoverflow.com/q/52410931/3286653
// It may also report an underflow when parsing DOUBLE_MIN as an
// ERANGE error, as the parsed value may be smaller than DOUBLE_MIN
// and rounded up.
// See: https://stackoverflow.com/q/42005462
if (is.fail() &&
(std::fabs(dest) == (std::numeric_limits<FloatType>::min)() ||
std::fpclassify(dest) == FP_SUBNORMAL)) {
is.clear(is.rdstate() & (~std::ios_base::failbit));
}
return dest;
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_

View File

@@ -0,0 +1,161 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_
#define ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_
#include <algorithm>
#include <cstdint>
#include <iterator>
#include <type_traits>
#include <utility>
#include <vector>
#include "absl/base/macros.h"
#include "absl/container/inlined_vector.h"
#include "absl/meta/type_traits.h"
#include "absl/random/internal/pool_urbg.h"
#include "absl/random/internal/salted_seed_seq.h"
#include "absl/random/internal/seed_material.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RandenPoolSeedSeq is a custom seed sequence type where generate() fills the
// provided buffer via the RandenPool entropy source.
class RandenPoolSeedSeq {
private:
struct ContiguousTag {};
struct BufferTag {};
// Generate random unsigned values directly into the buffer.
template <typename Contiguous>
void generate_impl(ContiguousTag, Contiguous begin, Contiguous end) {
const size_t n = static_cast<size_t>(std::distance(begin, end));
auto* a = &(*begin);
RandenPool<uint8_t>::Fill(
absl::MakeSpan(reinterpret_cast<uint8_t*>(a), sizeof(*a) * n));
}
// Construct a buffer of size n and fill it with values, then copy
// those values into the seed iterators.
template <typename RandomAccessIterator>
void generate_impl(BufferTag, RandomAccessIterator begin,
RandomAccessIterator end) {
const size_t n = std::distance(begin, end);
absl::InlinedVector<uint32_t, 8> data(n, 0);
RandenPool<uint32_t>::Fill(absl::MakeSpan(data.begin(), data.end()));
std::copy(std::begin(data), std::end(data), begin);
}
public:
using result_type = uint32_t;
size_t size() { return 0; }
template <typename OutIterator>
void param(OutIterator) const {}
template <typename RandomAccessIterator>
void generate(RandomAccessIterator begin, RandomAccessIterator end) {
// RandomAccessIterator must be assignable from uint32_t
if (begin != end) {
using U = typename std::iterator_traits<RandomAccessIterator>::value_type;
// ContiguousTag indicates the common case of a known contiguous buffer,
// which allows directly filling the buffer. In C++20,
// std::contiguous_iterator_tag provides a mechanism for testing this
// capability, however until Abseil's support requirements allow us to
// assume C++20, limit checks to a few common cases.
using TagType = absl::conditional_t<
(std::is_pointer<RandomAccessIterator>::value ||
std::is_same<RandomAccessIterator,
typename std::vector<U>::iterator>::value),
ContiguousTag, BufferTag>;
generate_impl(TagType{}, begin, end);
}
}
};
// Each instance of NonsecureURBGBase<URBG> will be seeded by variates produced
// by a thread-unique URBG-instance.
template <typename URBG, typename Seeder = RandenPoolSeedSeq>
class NonsecureURBGBase {
public:
using result_type = typename URBG::result_type;
// Default constructor
NonsecureURBGBase() : urbg_(ConstructURBG()) {}
// Copy disallowed, move allowed.
NonsecureURBGBase(const NonsecureURBGBase&) = delete;
NonsecureURBGBase& operator=(const NonsecureURBGBase&) = delete;
NonsecureURBGBase(NonsecureURBGBase&&) = default;
NonsecureURBGBase& operator=(NonsecureURBGBase&&) = default;
// Constructor using a seed
template <class SSeq, typename = typename absl::enable_if_t<
!std::is_same<SSeq, NonsecureURBGBase>::value>>
explicit NonsecureURBGBase(SSeq&& seq)
: urbg_(ConstructURBG(std::forward<SSeq>(seq))) {}
// Note: on MSVC, min() or max() can be interpreted as MIN() or MAX(), so we
// enclose min() or max() in parens as (min)() and (max)().
// Additionally, clang-format requires no space before this construction.
// NonsecureURBGBase::min()
static constexpr result_type(min)() { return (URBG::min)(); }
// NonsecureURBGBase::max()
static constexpr result_type(max)() { return (URBG::max)(); }
// NonsecureURBGBase::operator()()
result_type operator()() { return urbg_(); }
// NonsecureURBGBase::discard()
void discard(unsigned long long values) { // NOLINT(runtime/int)
urbg_.discard(values);
}
bool operator==(const NonsecureURBGBase& other) const {
return urbg_ == other.urbg_;
}
bool operator!=(const NonsecureURBGBase& other) const {
return !(urbg_ == other.urbg_);
}
private:
static URBG ConstructURBG() {
Seeder seeder;
return URBG(seeder);
}
template <typename SSeq>
static URBG ConstructURBG(SSeq&& seq) { // NOLINT(runtime/references)
auto salted_seq =
random_internal::MakeSaltedSeedSeq(std::forward<SSeq>(seq));
return URBG(salted_seq);
}
URBG urbg_;
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_

View File

@@ -0,0 +1,287 @@
// Copyright 2018 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.
#ifndef ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_
#define ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_
#include <type_traits>
#include "absl/base/config.h"
#include "absl/meta/type_traits.h"
#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
#include "absl/random/internal/fastmath.h"
#include "absl/random/internal/iostream_state_saver.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// pcg_engine is a simplified implementation of Melissa O'Neil's PCG engine in
// C++. PCG combines a linear congruential generator (LCG) with output state
// mixing functions to generate each random variate. pcg_engine supports only a
// single sequence (oneseq), and does not support streams.
//
// pcg_engine is parameterized by two types:
// Params, which provides the multiplier and increment values;
// Mix, which mixes the state into the result.
//
template <typename Params, typename Mix>
class pcg_engine {
static_assert(std::is_same<typename Params::state_type,
typename Mix::state_type>::value,
"Class-template absl::pcg_engine must be parameterized by "
"Params and Mix with identical state_type");
static_assert(std::is_unsigned<typename Mix::result_type>::value,
"Class-template absl::pcg_engine must be parameterized by "
"an unsigned Mix::result_type");
using params_type = Params;
using mix_type = Mix;
using state_type = typename Mix::state_type;
public:
// C++11 URBG interface:
using result_type = typename Mix::result_type;
static constexpr result_type(min)() {
return (std::numeric_limits<result_type>::min)();
}
static constexpr result_type(max)() {
return (std::numeric_limits<result_type>::max)();
}
explicit pcg_engine(uint64_t seed_value = 0) { seed(seed_value); }
template <class SeedSequence,
typename = typename absl::enable_if_t<
!std::is_same<SeedSequence, pcg_engine>::value>>
explicit pcg_engine(SeedSequence&& seq) {
seed(seq);
}
pcg_engine(const pcg_engine&) = default;
pcg_engine& operator=(const pcg_engine&) = default;
pcg_engine(pcg_engine&&) = default;
pcg_engine& operator=(pcg_engine&&) = default;
result_type operator()() {
// Advance the LCG state, always using the new value to generate the output.
state_ = lcg(state_);
return Mix{}(state_);
}
void seed(uint64_t seed_value = 0) {
state_type tmp = seed_value;
state_ = lcg(tmp + Params::increment());
}
template <class SeedSequence>
typename absl::enable_if_t<
!std::is_convertible<SeedSequence, uint64_t>::value, void>
seed(SeedSequence&& seq) {
reseed(seq);
}
void discard(uint64_t count) { state_ = advance(state_, count); }
bool operator==(const pcg_engine& other) const {
return state_ == other.state_;
}
bool operator!=(const pcg_engine& other) const { return !(*this == other); }
template <class CharT, class Traits>
friend typename absl::enable_if_t<(sizeof(state_type) == 16),
std::basic_ostream<CharT, Traits>&>
operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const pcg_engine& engine) {
auto saver = random_internal::make_ostream_state_saver(os);
random_internal::stream_u128_helper<state_type> helper;
helper.write(pcg_engine::params_type::multiplier(), os);
os << os.fill();
helper.write(pcg_engine::params_type::increment(), os);
os << os.fill();
helper.write(engine.state_, os);
return os;
}
template <class CharT, class Traits>
friend typename absl::enable_if_t<(sizeof(state_type) <= 8),
std::basic_ostream<CharT, Traits>&>
operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const pcg_engine& engine) {
auto saver = random_internal::make_ostream_state_saver(os);
os << pcg_engine::params_type::multiplier() << os.fill();
os << pcg_engine::params_type::increment() << os.fill();
os << engine.state_;
return os;
}
template <class CharT, class Traits>
friend typename absl::enable_if_t<(sizeof(state_type) == 16),
std::basic_istream<CharT, Traits>&>
operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
pcg_engine& engine) { // NOLINT(runtime/references)
random_internal::stream_u128_helper<state_type> helper;
auto mult = helper.read(is);
auto inc = helper.read(is);
auto tmp = helper.read(is);
if (mult != pcg_engine::params_type::multiplier() ||
inc != pcg_engine::params_type::increment()) {
// signal failure by setting the failbit.
is.setstate(is.rdstate() | std::ios_base::failbit);
}
if (!is.fail()) {
engine.state_ = tmp;
}
return is;
}
template <class CharT, class Traits>
friend typename absl::enable_if_t<(sizeof(state_type) <= 8),
std::basic_istream<CharT, Traits>&>
operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
pcg_engine& engine) { // NOLINT(runtime/references)
state_type mult{}, inc{}, tmp{};
is >> mult >> inc >> tmp;
if (mult != pcg_engine::params_type::multiplier() ||
inc != pcg_engine::params_type::increment()) {
// signal failure by setting the failbit.
is.setstate(is.rdstate() | std::ios_base::failbit);
}
if (!is.fail()) {
engine.state_ = tmp;
}
return is;
}
private:
state_type state_;
// Returns the linear-congruential generator next state.
static inline constexpr state_type lcg(state_type s) {
return s * Params::multiplier() + Params::increment();
}
// Returns the linear-congruential arbitrary seek state.
inline state_type advance(state_type s, uint64_t n) const {
state_type mult = Params::multiplier();
state_type inc = Params::increment();
state_type m = 1;
state_type i = 0;
while (n > 0) {
if (n & 1) {
m *= mult;
i = i * mult + inc;
}
inc = (mult + 1) * inc;
mult *= mult;
n >>= 1;
}
return m * s + i;
}
template <class SeedSequence>
void reseed(SeedSequence& seq) {
using sequence_result_type = typename SeedSequence::result_type;
constexpr size_t kBufferSize =
sizeof(state_type) / sizeof(sequence_result_type);
sequence_result_type buffer[kBufferSize];
seq.generate(std::begin(buffer), std::end(buffer));
// Convert the seed output to a single state value.
state_type tmp = buffer[0];
for (size_t i = 1; i < kBufferSize; i++) {
tmp <<= (sizeof(sequence_result_type) * 8);
tmp |= buffer[i];
}
state_ = lcg(tmp + params_type::increment());
}
};
// Parameterized implementation of the PCG 128-bit oneseq state.
// This provides state_type, multiplier, and increment for pcg_engine.
template <uint64_t kMultA, uint64_t kMultB, uint64_t kIncA, uint64_t kIncB>
class pcg128_params {
public:
using state_type = absl::uint128;
static inline constexpr state_type multiplier() {
return absl::MakeUint128(kMultA, kMultB);
}
static inline constexpr state_type increment() {
return absl::MakeUint128(kIncA, kIncB);
}
};
// Implementation of the PCG xsl_rr_128_64 128-bit mixing function, which
// accepts an input of state_type and mixes it into an output of result_type.
struct pcg_xsl_rr_128_64 {
using state_type = absl::uint128;
using result_type = uint64_t;
inline uint64_t operator()(state_type state) {
// This is equivalent to the xsl_rr_128_64 mixing function.
uint64_t rotate = static_cast<uint64_t>(state >> 122u);
state ^= state >> 64;
uint64_t s = static_cast<uint64_t>(state);
return rotr(s, static_cast<int>(rotate));
}
};
// Parameterized implementation of the PCG 64-bit oneseq state.
// This provides state_type, multiplier, and increment for pcg_engine.
template <uint64_t kMult, uint64_t kInc>
class pcg64_params {
public:
using state_type = uint64_t;
static inline constexpr state_type multiplier() { return kMult; }
static inline constexpr state_type increment() { return kInc; }
};
// Implementation of the PCG xsh_rr_64_32 64-bit mixing function, which accepts
// an input of state_type and mixes it into an output of result_type.
struct pcg_xsh_rr_64_32 {
using state_type = uint64_t;
using result_type = uint32_t;
inline uint32_t operator()(uint64_t state) {
return rotr(static_cast<uint32_t>(((state >> 18) ^ state) >> 27),
state >> 59);
}
};
// Stable pcg_engine implementations:
// This is a 64-bit generator using 128-bits of state.
// The output sequence is equivalent to Melissa O'Neil's pcg64_oneseq.
using pcg64_2018_engine = pcg_engine<
random_internal::pcg128_params<0x2360ed051fc65da4ull, 0x4385df649fccf645ull,
0x5851f42d4c957f2d, 0x14057b7ef767814f>,
random_internal::pcg_xsl_rr_128_64>;
// This is a 32-bit generator using 64-bits of state.
// This is equivalent to Melissa O'Neil's pcg32_oneseq.
using pcg32_2018_engine = pcg_engine<
random_internal::pcg64_params<0x5851f42d4c957f2dull, 0x14057b7ef767814full>,
random_internal::pcg_xsh_rr_64_32>;
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_

View File

@@ -0,0 +1,171 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_PLATFORM_H_
#define ABSL_RANDOM_INTERNAL_PLATFORM_H_
// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
// symbols from arbitrary system and other headers, since it may be built
// with different flags from other targets, using different levels of
// optimization, potentially introducing ODR violations.
// -----------------------------------------------------------------------------
// Platform Feature Checks
// -----------------------------------------------------------------------------
// Currently supported operating systems and associated preprocessor
// symbols:
//
// Linux and Linux-derived __linux__
// Android __ANDROID__ (implies __linux__)
// Linux (non-Android) __linux__ && !__ANDROID__
// Darwin (macOS and iOS) __APPLE__
// Akaros (http://akaros.org) __ros__
// Windows _WIN32
// NaCL __native_client__
// AsmJS __asmjs__
// WebAssembly __wasm__
// Fuchsia __Fuchsia__
//
// Note that since Android defines both __ANDROID__ and __linux__, one
// may probe for either Linux or Android by simply testing for __linux__.
//
// NOTE: For __APPLE__ platforms, we use #include <TargetConditionals.h>
// to distinguish os variants.
//
// http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
// -----------------------------------------------------------------------------
// Architecture Checks
// -----------------------------------------------------------------------------
// These preprocessor directives are trying to determine CPU architecture,
// including necessary headers to support hardware AES.
//
// ABSL_ARCH_{X86/PPC/ARM} macros determine the platform.
#if defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || \
defined(_M_X64)
#define ABSL_ARCH_X86_64
#elif defined(__i386) || defined(_M_IX86)
#define ABSL_ARCH_X86_32
#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
#define ABSL_ARCH_AARCH64
#elif defined(__arm__) || defined(__ARMEL__) || defined(_M_ARM)
#define ABSL_ARCH_ARM
#elif defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \
defined(__ppc__) || defined(__PPC__)
#define ABSL_ARCH_PPC
#else
// Unsupported architecture.
// * https://sourceforge.net/p/predef/wiki/Architectures/
// * https://msdn.microsoft.com/en-us/library/b0084kay.aspx
// * for gcc, clang: "echo | gcc -E -dM -"
#endif
// -----------------------------------------------------------------------------
// Attribute Checks
// -----------------------------------------------------------------------------
// ABSL_RANDOM_INTERNAL_RESTRICT annotates whether pointers may be considered
// to be unaliased.
#if defined(__clang__) || defined(__GNUC__)
#define ABSL_RANDOM_INTERNAL_RESTRICT __restrict__
#elif defined(_MSC_VER)
#define ABSL_RANDOM_INTERNAL_RESTRICT __restrict
#else
#define ABSL_RANDOM_INTERNAL_RESTRICT
#endif
// ABSL_HAVE_ACCELERATED_AES indicates whether the currently active compiler
// flags (e.g. -maes) allow using hardware accelerated AES instructions, which
// implies us assuming that the target platform supports them.
#define ABSL_HAVE_ACCELERATED_AES 0
#if defined(ABSL_ARCH_X86_64)
#if defined(__AES__) || defined(__AVX__)
#undef ABSL_HAVE_ACCELERATED_AES
#define ABSL_HAVE_ACCELERATED_AES 1
#endif
#elif defined(ABSL_ARCH_PPC)
// Rely on VSX and CRYPTO extensions for vcipher on PowerPC.
#if (defined(__VEC__) || defined(__ALTIVEC__)) && defined(__VSX__) && \
defined(__CRYPTO__)
#undef ABSL_HAVE_ACCELERATED_AES
#define ABSL_HAVE_ACCELERATED_AES 1
#endif
#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf
// Rely on NEON+CRYPTO extensions for ARM.
#if defined(__ARM_NEON) && defined(__ARM_FEATURE_CRYPTO)
#undef ABSL_HAVE_ACCELERATED_AES
#define ABSL_HAVE_ACCELERATED_AES 1
#endif
#endif
// NaCl does not allow AES.
#if defined(__native_client__)
#undef ABSL_HAVE_ACCELERATED_AES
#define ABSL_HAVE_ACCELERATED_AES 0
#endif
// ABSL_RANDOM_INTERNAL_AES_DISPATCH indicates whether the currently active
// platform has, or should use run-time dispatch for selecting the
// accelerated Randen implementation.
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
#if defined(ABSL_ARCH_X86_64)
// Dispatch is available on x86_64
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
#elif defined(__linux__) && defined(ABSL_ARCH_PPC)
// Or when running linux PPC
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
#elif defined(__linux__) && defined(ABSL_ARCH_AARCH64)
// Or when running linux AArch64
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
#elif defined(__linux__) && defined(ABSL_ARCH_ARM) && (__ARM_ARCH >= 8)
// Or when running linux ARM v8 or higher.
// (This captures a lot of Android configurations.)
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
#endif
// NaCl does not allow dispatch.
#if defined(__native_client__)
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
#endif
// iOS does not support dispatch, even on x86, since applications
// should be bundled as fat binaries, with a different build tailored for
// each specific supported platform/architecture.
#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
(defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR)
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
#endif
#endif // ABSL_RANDOM_INTERNAL_PLATFORM_H_

View File

@@ -0,0 +1,253 @@
// 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.
#include "absl/random/internal/pool_urbg.h"
#include <algorithm>
#include <atomic>
#include <cstdint>
#include <cstring>
#include <iterator>
#include "absl/base/attributes.h"
#include "absl/base/call_once.h"
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/spinlock.h"
#include "absl/base/internal/sysinfo.h"
#include "absl/base/internal/unaligned_access.h"
#include "absl/base/optimization.h"
#include "absl/random/internal/randen.h"
#include "absl/random/internal/seed_material.h"
#include "absl/random/seed_gen_exception.h"
using absl::base_internal::SpinLock;
using absl::base_internal::SpinLockHolder;
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
namespace {
// RandenPoolEntry is a thread-safe pseudorandom bit generator, implementing a
// single generator within a RandenPool<T>. It is an internal implementation
// detail, and does not aim to conform to [rand.req.urng].
//
// NOTE: There are alignment issues when used on ARM, for instance.
// See the allocation code in PoolAlignedAlloc().
class RandenPoolEntry {
public:
static constexpr size_t kState = RandenTraits::kStateBytes / sizeof(uint32_t);
static constexpr size_t kCapacity =
RandenTraits::kCapacityBytes / sizeof(uint32_t);
void Init(absl::Span<const uint32_t> data) {
SpinLockHolder l(&mu_); // Always uncontested.
std::copy(data.begin(), data.end(), std::begin(state_));
next_ = kState;
}
// Copy bytes into out.
void Fill(uint8_t* out, size_t bytes) ABSL_LOCKS_EXCLUDED(mu_);
// Returns random bits from the buffer in units of T.
template <typename T>
inline T Generate() ABSL_LOCKS_EXCLUDED(mu_);
inline void MaybeRefill() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
if (next_ >= kState) {
next_ = kCapacity;
impl_.Generate(state_);
}
}
private:
// Randen URBG state.
uint32_t state_[kState] ABSL_GUARDED_BY(mu_); // First to satisfy alignment.
SpinLock mu_;
const Randen impl_;
size_t next_ ABSL_GUARDED_BY(mu_);
};
template <>
inline uint8_t RandenPoolEntry::Generate<uint8_t>() {
SpinLockHolder l(&mu_);
MaybeRefill();
return static_cast<uint8_t>(state_[next_++]);
}
template <>
inline uint16_t RandenPoolEntry::Generate<uint16_t>() {
SpinLockHolder l(&mu_);
MaybeRefill();
return static_cast<uint16_t>(state_[next_++]);
}
template <>
inline uint32_t RandenPoolEntry::Generate<uint32_t>() {
SpinLockHolder l(&mu_);
MaybeRefill();
return state_[next_++];
}
template <>
inline uint64_t RandenPoolEntry::Generate<uint64_t>() {
SpinLockHolder l(&mu_);
if (next_ >= kState - 1) {
next_ = kCapacity;
impl_.Generate(state_);
}
auto p = state_ + next_;
next_ += 2;
uint64_t result;
std::memcpy(&result, p, sizeof(result));
return result;
}
void RandenPoolEntry::Fill(uint8_t* out, size_t bytes) {
SpinLockHolder l(&mu_);
while (bytes > 0) {
MaybeRefill();
size_t remaining = (kState - next_) * sizeof(state_[0]);
size_t to_copy = std::min(bytes, remaining);
std::memcpy(out, &state_[next_], to_copy);
out += to_copy;
bytes -= to_copy;
next_ += (to_copy + sizeof(state_[0]) - 1) / sizeof(state_[0]);
}
}
// Number of pooled urbg entries.
static constexpr size_t kPoolSize = 8;
// Shared pool entries.
static absl::once_flag pool_once;
ABSL_CACHELINE_ALIGNED static RandenPoolEntry* shared_pools[kPoolSize];
// Returns an id in the range [0 ... kPoolSize), which indexes into the
// pool of random engines.
//
// Each thread to access the pool is assigned a sequential ID (without reuse)
// from the pool-id space; the id is cached in a thread_local variable.
// This id is assigned based on the arrival-order of the thread to the
// GetPoolID call; this has no binary, CL, or runtime stability because
// on subsequent runs the order within the same program may be significantly
// different. However, as other thread IDs are not assigned sequentially,
// this is not expected to matter.
size_t GetPoolID() {
static_assert(kPoolSize >= 1,
"At least one urbg instance is required for PoolURBG");
ABSL_CONST_INIT static std::atomic<uint64_t> sequence{0};
#ifdef ABSL_HAVE_THREAD_LOCAL
static thread_local size_t my_pool_id = kPoolSize;
if (ABSL_PREDICT_FALSE(my_pool_id == kPoolSize)) {
my_pool_id = (sequence++ % kPoolSize);
}
return my_pool_id;
#else
static pthread_key_t tid_key = [] {
pthread_key_t tmp_key;
int err = pthread_key_create(&tmp_key, nullptr);
if (err) {
ABSL_RAW_LOG(FATAL, "pthread_key_create failed with %d", err);
}
return tmp_key;
}();
// Store the value in the pthread_{get/set}specific. However an uninitialized
// value is 0, so add +1 to distinguish from the null value.
uintptr_t my_pool_id =
reinterpret_cast<uintptr_t>(pthread_getspecific(tid_key));
if (ABSL_PREDICT_FALSE(my_pool_id == 0)) {
// No allocated ID, allocate the next value, cache it, and return.
my_pool_id = (sequence++ % kPoolSize) + 1;
int err = pthread_setspecific(tid_key, reinterpret_cast<void*>(my_pool_id));
if (err) {
ABSL_RAW_LOG(FATAL, "pthread_setspecific failed with %d", err);
}
}
return my_pool_id - 1;
#endif
}
// Allocate a RandenPoolEntry with at least 32-byte alignment, which is required
// by ARM platform code.
RandenPoolEntry* PoolAlignedAlloc() {
constexpr size_t kAlignment =
ABSL_CACHELINE_SIZE > 32 ? ABSL_CACHELINE_SIZE : 32;
// Not all the platforms that we build for have std::aligned_alloc, however
// since we never free these objects, we can over allocate and munge the
// pointers to the correct alignment.
uintptr_t x = reinterpret_cast<uintptr_t>(
new char[sizeof(RandenPoolEntry) + kAlignment]);
auto y = x % kAlignment;
void* aligned = reinterpret_cast<void*>(y == 0 ? x : (x + kAlignment - y));
return new (aligned) RandenPoolEntry();
}
// Allocate and initialize kPoolSize objects of type RandenPoolEntry.
//
// The initialization strategy is to initialize one object directly from
// OS entropy, then to use that object to seed all of the individual
// pool instances.
void InitPoolURBG() {
static constexpr size_t kSeedSize =
RandenTraits::kStateBytes / sizeof(uint32_t);
// Read the seed data from OS entropy once.
uint32_t seed_material[kPoolSize * kSeedSize];
if (!random_internal::ReadSeedMaterialFromOSEntropy(
absl::MakeSpan(seed_material))) {
random_internal::ThrowSeedGenException();
}
for (size_t i = 0; i < kPoolSize; i++) {
shared_pools[i] = PoolAlignedAlloc();
shared_pools[i]->Init(
absl::MakeSpan(&seed_material[i * kSeedSize], kSeedSize));
}
}
// Returns the pool entry for the current thread.
RandenPoolEntry* GetPoolForCurrentThread() {
absl::call_once(pool_once, InitPoolURBG);
return shared_pools[GetPoolID()];
}
} // namespace
template <typename T>
typename RandenPool<T>::result_type RandenPool<T>::Generate() {
auto* pool = GetPoolForCurrentThread();
return pool->Generate<T>();
}
template <typename T>
void RandenPool<T>::Fill(absl::Span<result_type> data) {
auto* pool = GetPoolForCurrentThread();
pool->Fill(reinterpret_cast<uint8_t*>(data.data()),
data.size() * sizeof(result_type));
}
template class RandenPool<uint8_t>;
template class RandenPool<uint16_t>;
template class RandenPool<uint32_t>;
template class RandenPool<uint64_t>;
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl

View File

@@ -0,0 +1,131 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_POOL_URBG_H_
#define ABSL_RANDOM_INTERNAL_POOL_URBG_H_
#include <cinttypes>
#include <limits>
#include "absl/random/internal/traits.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RandenPool is a thread-safe random number generator [random.req.urbg] that
// uses an underlying pool of Randen generators to generate values. Each thread
// has affinity to one instance of the underlying pool generators. Concurrent
// access is guarded by a spin-lock.
template <typename T>
class RandenPool {
public:
using result_type = T;
static_assert(std::is_unsigned<result_type>::value,
"RandenPool template argument must be a built-in unsigned "
"integer type");
static constexpr result_type(min)() {
return (std::numeric_limits<result_type>::min)();
}
static constexpr result_type(max)() {
return (std::numeric_limits<result_type>::max)();
}
RandenPool() {}
// Returns a single value.
inline result_type operator()() { return Generate(); }
// Fill data with random values.
static void Fill(absl::Span<result_type> data);
protected:
// Generate returns a single value.
static result_type Generate();
};
extern template class RandenPool<uint8_t>;
extern template class RandenPool<uint16_t>;
extern template class RandenPool<uint32_t>;
extern template class RandenPool<uint64_t>;
// PoolURBG uses an underlying pool of random generators to implement a
// thread-compatible [random.req.urbg] interface with an internal cache of
// values.
template <typename T, size_t kBufferSize>
class PoolURBG {
// Inheritance to access the protected static members of RandenPool.
using unsigned_type = typename make_unsigned_bits<T>::type;
using PoolType = RandenPool<unsigned_type>;
using SpanType = absl::Span<unsigned_type>;
static constexpr size_t kInitialBuffer = kBufferSize + 1;
static constexpr size_t kHalfBuffer = kBufferSize / 2;
public:
using result_type = T;
static_assert(std::is_unsigned<result_type>::value,
"PoolURBG must be parameterized by an unsigned integer type");
static_assert(kBufferSize > 1,
"PoolURBG must be parameterized by a buffer-size > 1");
static_assert(kBufferSize <= 256,
"PoolURBG must be parameterized by a buffer-size <= 256");
static constexpr result_type(min)() {
return (std::numeric_limits<result_type>::min)();
}
static constexpr result_type(max)() {
return (std::numeric_limits<result_type>::max)();
}
PoolURBG() : next_(kInitialBuffer) {}
// copy-constructor does not copy cache.
PoolURBG(const PoolURBG&) : next_(kInitialBuffer) {}
const PoolURBG& operator=(const PoolURBG&) {
next_ = kInitialBuffer;
return *this;
}
// move-constructor does move cache.
PoolURBG(PoolURBG&&) = default;
PoolURBG& operator=(PoolURBG&&) = default;
inline result_type operator()() {
if (next_ >= kBufferSize) {
next_ = (kBufferSize > 2 && next_ > kBufferSize) ? kHalfBuffer : 0;
PoolType::Fill(SpanType(reinterpret_cast<unsigned_type*>(state_ + next_),
kBufferSize - next_));
}
return state_[next_++];
}
private:
// Buffer size.
size_t next_; // index within state_
result_type state_[kBufferSize];
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_POOL_URBG_H_

View File

@@ -0,0 +1,91 @@
// 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.
#include "absl/random/internal/randen.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/random/internal/randen_detect.h"
// RANDen = RANDom generator or beetroots in Swiss High German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
// High-level summary:
// 1) Reverie (see "A Robust and Sponge-Like PRNG with Improved Efficiency") is
// a sponge-like random generator that requires a cryptographic permutation.
// It improves upon "Provably Robust Sponge-Based PRNGs and KDFs" by
// achieving backtracking resistance with only one Permute() per buffer.
//
// 2) "Simpira v2: A Family of Efficient Permutations Using the AES Round
// Function" constructs up to 1024-bit permutations using an improved
// Generalized Feistel network with 2-round AES-128 functions. This Feistel
// block shuffle achieves diffusion faster and is less vulnerable to
// sliced-biclique attacks than the Type-2 cyclic shuffle.
//
// 3) "Improving the Generalized Feistel" and "New criterion for diffusion
// property" extends the same kind of improved Feistel block shuffle to 16
// branches, which enables a 2048-bit permutation.
//
// We combine these three ideas and also change Simpira's subround keys from
// structured/low-entropy counters to digits of Pi.
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
namespace {
struct RandenState {
const void* keys;
bool has_crypto;
};
RandenState GetRandenState() {
static const RandenState state = []() {
RandenState tmp;
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
// HW AES Dispatch.
if (HasRandenHwAesImplementation() && CPUSupportsRandenHwAes()) {
tmp.has_crypto = true;
tmp.keys = RandenHwAes::GetKeys();
} else {
tmp.has_crypto = false;
tmp.keys = RandenSlow::GetKeys();
}
#elif ABSL_HAVE_ACCELERATED_AES
// HW AES is enabled.
tmp.has_crypto = true;
tmp.keys = RandenHwAes::GetKeys();
#else
// HW AES is disabled.
tmp.has_crypto = false;
tmp.keys = RandenSlow::GetKeys();
#endif
return tmp;
}();
return state;
}
} // namespace
Randen::Randen() {
auto tmp = GetRandenState();
keys_ = tmp.keys;
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
has_crypto_ = tmp.has_crypto;
#endif
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl

View File

@@ -0,0 +1,96 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_H_
#include <cstddef>
#include "absl/random/internal/platform.h"
#include "absl/random/internal/randen_hwaes.h"
#include "absl/random/internal/randen_slow.h"
#include "absl/random/internal/randen_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RANDen = RANDom generator or beetroots in Swiss High German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
// Randen implements the basic state manipulation methods.
class Randen {
public:
static constexpr size_t kStateBytes = RandenTraits::kStateBytes;
static constexpr size_t kCapacityBytes = RandenTraits::kCapacityBytes;
static constexpr size_t kSeedBytes = RandenTraits::kSeedBytes;
~Randen() = default;
Randen();
// Generate updates the randen sponge. The outer portion of the sponge
// (kCapacityBytes .. kStateBytes) may be consumed as PRNG state.
// REQUIRES: state points to kStateBytes of state.
inline void Generate(void* state) const {
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
// HW AES Dispatch.
if (has_crypto_) {
RandenHwAes::Generate(keys_, state);
} else {
RandenSlow::Generate(keys_, state);
}
#elif ABSL_HAVE_ACCELERATED_AES
// HW AES is enabled.
RandenHwAes::Generate(keys_, state);
#else
// HW AES is disabled.
RandenSlow::Generate(keys_, state);
#endif
}
// Absorb incorporates additional seed material into the randen sponge. After
// absorb returns, Generate must be called before the state may be consumed.
// REQUIRES: seed points to kSeedBytes of seed.
// REQUIRES: state points to kStateBytes of state.
inline void Absorb(const void* seed, void* state) const {
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
// HW AES Dispatch.
if (has_crypto_) {
RandenHwAes::Absorb(seed, state);
} else {
RandenSlow::Absorb(seed, state);
}
#elif ABSL_HAVE_ACCELERATED_AES
// HW AES is enabled.
RandenHwAes::Absorb(seed, state);
#else
// HW AES is disabled.
RandenSlow::Absorb(seed, state);
#endif
}
private:
const void* keys_;
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
bool has_crypto_;
#endif
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_H_

View File

@@ -0,0 +1,229 @@
// 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.
// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
// symbols from arbitrary system and other headers, since it may be built
// with different flags from other targets, using different levels of
// optimization, potentially introducing ODR violations.
#include "absl/random/internal/randen_detect.h"
#include <cstdint>
#include <cstring>
#include "absl/random/internal/platform.h"
#if !defined(__UCLIBC__) && defined(__GLIBC__) && \
(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16))
#define ABSL_HAVE_GETAUXVAL
#endif
#if defined(ABSL_ARCH_X86_64)
#define ABSL_INTERNAL_USE_X86_CPUID
#elif defined(ABSL_ARCH_PPC) || defined(ABSL_ARCH_ARM) || \
defined(ABSL_ARCH_AARCH64)
#if defined(__ANDROID__)
#define ABSL_INTERNAL_USE_ANDROID_GETAUXVAL
#define ABSL_INTERNAL_USE_GETAUXVAL
#elif defined(__linux__) && defined(ABSL_HAVE_GETAUXVAL)
#define ABSL_INTERNAL_USE_LINUX_GETAUXVAL
#define ABSL_INTERNAL_USE_GETAUXVAL
#endif
#endif
#if defined(ABSL_INTERNAL_USE_X86_CPUID)
#if defined(_WIN32) || defined(_WIN64)
#include <intrin.h> // NOLINT(build/include_order)
#elif ABSL_HAVE_BUILTIN(__cpuid)
// MSVC-equivalent __cpuid intrinsic declaration for clang-like compilers
// for non-Windows build environments.
extern void __cpuid(int[4], int);
#else
// MSVC-equivalent __cpuid intrinsic function.
static void __cpuid(int cpu_info[4], int info_type) {
__asm__ volatile("cpuid \n\t"
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
"=d"(cpu_info[3])
: "a"(info_type), "c"(0));
}
#endif
#endif // ABSL_INTERNAL_USE_X86_CPUID
// On linux, just use the c-library getauxval call.
#if defined(ABSL_INTERNAL_USE_LINUX_GETAUXVAL)
extern "C" unsigned long getauxval(unsigned long type); // NOLINT(runtime/int)
static uint32_t GetAuxval(uint32_t hwcap_type) {
return static_cast<uint32_t>(getauxval(hwcap_type));
}
#endif
// On android, probe the system's C library for getauxval().
// This is the same technique used by the android NDK cpu features library
// as well as the google open-source cpu_features library.
//
// TODO(absl-team): Consider implementing a fallback of directly reading
// /proc/self/auxval.
#if defined(ABSL_INTERNAL_USE_ANDROID_GETAUXVAL)
#include <dlfcn.h>
static uint32_t GetAuxval(uint32_t hwcap_type) {
// NOLINTNEXTLINE(runtime/int)
typedef unsigned long (*getauxval_func_t)(unsigned long);
dlerror(); // Cleaning error state before calling dlopen.
void* libc_handle = dlopen("libc.so", RTLD_NOW);
if (!libc_handle) {
return 0;
}
uint32_t result = 0;
void* sym = dlsym(libc_handle, "getauxval");
if (sym) {
getauxval_func_t func;
memcpy(&func, &sym, sizeof(func));
result = static_cast<uint32_t>((*func)(hwcap_type));
}
dlclose(libc_handle);
return result;
}
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// The default return at the end of the function might be unreachable depending
// on the configuration. Ignore that warning.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code-return"
#endif
// CPUSupportsRandenHwAes returns whether the CPU is a microarchitecture
// which supports the crpyto/aes instructions or extensions necessary to use the
// accelerated RandenHwAes implementation.
//
// 1. For x86 it is sufficient to use the CPUID instruction to detect whether
// the cpu supports AES instructions. Done.
//
// Fon non-x86 it is much more complicated.
//
// 2. When ABSL_INTERNAL_USE_GETAUXVAL is defined, use getauxval() (either
// the direct c-library version, or the android probing version which loads
// libc), and read the hardware capability bits.
// This is based on the technique used by boringssl uses to detect
// cpu capabilities, and should allow us to enable crypto in the android
// builds where it is supported.
//
// 3. Use the default for the compiler architecture.
//
bool CPUSupportsRandenHwAes() {
#if defined(ABSL_INTERNAL_USE_X86_CPUID)
// 1. For x86: Use CPUID to detect the required AES instruction set.
int regs[4];
__cpuid(reinterpret_cast<int*>(regs), 1);
return regs[2] & (1 << 25); // AES
#elif defined(ABSL_INTERNAL_USE_GETAUXVAL)
// 2. Use getauxval() to read the hardware bits and determine
// cpu capabilities.
#define AT_HWCAP 16
#define AT_HWCAP2 26
#if defined(ABSL_ARCH_PPC)
// For Power / PPC: Expect that the cpu supports VCRYPTO
// See https://members.openpowerfoundation.org/document/dl/576
// VCRYPTO should be present in POWER8 >= 2.07.
// Uses Linux kernel constants from arch/powerpc/include/uapi/asm/cputable.h
static const uint32_t kVCRYPTO = 0x02000000;
const uint32_t hwcap = GetAuxval(AT_HWCAP2);
return (hwcap & kVCRYPTO) != 0;
#elif defined(ABSL_ARCH_ARM)
// For ARM: Require crypto+neon
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500f/CIHBIBBA.html
// Uses Linux kernel constants from arch/arm64/include/asm/hwcap.h
static const uint32_t kNEON = 1 << 12;
uint32_t hwcap = GetAuxval(AT_HWCAP);
if ((hwcap & kNEON) == 0) {
return false;
}
// And use it again to detect AES.
static const uint32_t kAES = 1 << 0;
const uint32_t hwcap2 = GetAuxval(AT_HWCAP2);
return (hwcap2 & kAES) != 0;
#elif defined(ABSL_ARCH_AARCH64)
// For AARCH64: Require crypto+neon
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500f/CIHBIBBA.html
static const uint32_t kNEON = 1 << 1;
static const uint32_t kAES = 1 << 3;
const uint32_t hwcap = GetAuxval(AT_HWCAP);
return ((hwcap & kNEON) != 0) && ((hwcap & kAES) != 0);
#endif
#else // ABSL_INTERNAL_USE_GETAUXVAL
// 3. By default, assume that the compiler default.
return ABSL_HAVE_ACCELERATED_AES ? true : false;
#endif
// NOTE: There are some other techniques that may be worth trying:
//
// * Use an environment variable: ABSL_RANDOM_USE_HWAES
//
// * Rely on compiler-generated target-based dispatch.
// Using x86/gcc it might look something like this:
//
// int __attribute__((target("aes"))) HasAes() { return 1; }
// int __attribute__((target("default"))) HasAes() { return 0; }
//
// This does not work on all architecture/compiler combinations.
//
// * On Linux consider reading /proc/cpuinfo and/or /proc/self/auxv.
// These files have lines which are easy to parse; for ARM/AARCH64 it is quite
// easy to find the Features: line and extract aes / neon. Likewise for
// PPC.
//
// * Fork a process and test for SIGILL:
//
// * Many architectures have instructions to read the ISA. Unfortunately
// most of those require that the code is running in ring 0 /
// protected-mode.
//
// There are several examples. e.g. Valgrind detects PPC ISA 2.07:
// https://github.com/lu-zero/valgrind/blob/master/none/tests/ppc64/test_isa_2_07_part1.c
//
// MRS <Xt>, ID_AA64ISAR0_EL1 ; Read ID_AA64ISAR0_EL1 into Xt
//
// uint64_t val;
// __asm __volatile("mrs %0, id_aa64isar0_el1" :"=&r" (val));
//
// * Use a CPUID-style heuristic database.
//
// * On Apple (__APPLE__), AES is available on Arm v8.
// https://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl

View File

@@ -0,0 +1,33 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Returns whether the current CPU supports RandenHwAes implementation.
// This typically involves supporting cryptographic extensions on whichever
// platform is currently running.
bool CPUSupportsRandenHwAes();
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_

View File

@@ -0,0 +1,264 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_
#include <algorithm>
#include <cinttypes>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <limits>
#include <type_traits>
#include "absl/base/internal/endian.h"
#include "absl/meta/type_traits.h"
#include "absl/random/internal/iostream_state_saver.h"
#include "absl/random/internal/randen.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Deterministic pseudorandom byte generator with backtracking resistance
// (leaking the state does not compromise prior outputs). Based on Reverie
// (see "A Robust and Sponge-Like PRNG with Improved Efficiency") instantiated
// with an improved Simpira-like permutation.
// Returns values of type "T" (must be a built-in unsigned integer type).
//
// RANDen = RANDom generator or beetroots in Swiss High German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
template <typename T>
class alignas(8) randen_engine {
public:
// C++11 URBG interface:
using result_type = T;
static_assert(std::is_unsigned<result_type>::value,
"randen_engine template argument must be a built-in unsigned "
"integer type");
static constexpr result_type(min)() {
return (std::numeric_limits<result_type>::min)();
}
static constexpr result_type(max)() {
return (std::numeric_limits<result_type>::max)();
}
randen_engine() : randen_engine(0) {}
explicit randen_engine(result_type seed_value) { seed(seed_value); }
template <class SeedSequence,
typename = typename absl::enable_if_t<
!std::is_same<SeedSequence, randen_engine>::value>>
explicit randen_engine(SeedSequence&& seq) {
seed(seq);
}
// alignment requirements dictate custom copy and move constructors.
randen_engine(const randen_engine& other)
: next_(other.next_), impl_(other.impl_) {
std::memcpy(state(), other.state(), kStateSizeT * sizeof(result_type));
}
randen_engine& operator=(const randen_engine& other) {
next_ = other.next_;
impl_ = other.impl_;
std::memcpy(state(), other.state(), kStateSizeT * sizeof(result_type));
return *this;
}
// Returns random bits from the buffer in units of result_type.
result_type operator()() {
// Refill the buffer if needed (unlikely).
auto* begin = state();
if (next_ >= kStateSizeT) {
next_ = kCapacityT;
impl_.Generate(begin);
}
return little_endian::ToHost(begin[next_++]);
}
template <class SeedSequence>
typename absl::enable_if_t<
!std::is_convertible<SeedSequence, result_type>::value>
seed(SeedSequence&& seq) {
// Zeroes the state.
seed();
reseed(seq);
}
void seed(result_type seed_value = 0) {
next_ = kStateSizeT;
// Zeroes the inner state and fills the outer state with seed_value to
// mimic the behaviour of reseed
auto* begin = state();
std::fill(begin, begin + kCapacityT, 0);
std::fill(begin + kCapacityT, begin + kStateSizeT, seed_value);
}
// Inserts entropy into (part of) the state. Calling this periodically with
// sufficient entropy ensures prediction resistance (attackers cannot predict
// future outputs even if state is compromised).
template <class SeedSequence>
void reseed(SeedSequence& seq) {
using sequence_result_type = typename SeedSequence::result_type;
static_assert(sizeof(sequence_result_type) == 4,
"SeedSequence::result_type must be 32-bit");
constexpr size_t kBufferSize =
Randen::kSeedBytes / sizeof(sequence_result_type);
alignas(16) sequence_result_type buffer[kBufferSize];
// Randen::Absorb XORs the seed into state, which is then mixed by a call
// to Randen::Generate. Seeding with only the provided entropy is preferred
// to using an arbitrary generate() call, so use [rand.req.seed_seq]
// size as a proxy for the number of entropy units that can be generated
// without relying on seed sequence mixing...
const size_t entropy_size = seq.size();
if (entropy_size < kBufferSize) {
// ... and only request that many values, or 256-bits, when unspecified.
const size_t requested_entropy = (entropy_size == 0) ? 8u : entropy_size;
std::fill(buffer + requested_entropy, buffer + kBufferSize, 0);
seq.generate(buffer, buffer + requested_entropy);
#ifdef ABSL_IS_BIG_ENDIAN
// Randen expects the seed buffer to be in Little Endian; reverse it on
// Big Endian platforms.
for (sequence_result_type& e : buffer) {
e = absl::little_endian::FromHost(e);
}
#endif
// The Randen paper suggests preferentially initializing even-numbered
// 128-bit vectors of the randen state (there are 16 such vectors).
// The seed data is merged into the state offset by 128-bits, which
// implies preferring seed bytes [16..31, ..., 208..223]. Since the
// buffer is 32-bit values, we swap the corresponding buffer positions in
// 128-bit chunks.
size_t dst = kBufferSize;
while (dst > 7) {
// leave the odd bucket as-is.
dst -= 4;
size_t src = dst >> 1;
// swap 128-bits into the even bucket
std::swap(buffer[--dst], buffer[--src]);
std::swap(buffer[--dst], buffer[--src]);
std::swap(buffer[--dst], buffer[--src]);
std::swap(buffer[--dst], buffer[--src]);
}
} else {
seq.generate(buffer, buffer + kBufferSize);
}
impl_.Absorb(buffer, state());
// Generate will be called when operator() is called
next_ = kStateSizeT;
}
void discard(uint64_t count) {
uint64_t step = std::min<uint64_t>(kStateSizeT - next_, count);
count -= step;
constexpr uint64_t kRateT = kStateSizeT - kCapacityT;
auto* begin = state();
while (count > 0) {
next_ = kCapacityT;
impl_.Generate(*reinterpret_cast<result_type(*)[kStateSizeT]>(begin));
step = std::min<uint64_t>(kRateT, count);
count -= step;
}
next_ += step;
}
bool operator==(const randen_engine& other) const {
const auto* begin = state();
return next_ == other.next_ &&
std::equal(begin, begin + kStateSizeT, other.state());
}
bool operator!=(const randen_engine& other) const {
return !(*this == other);
}
template <class CharT, class Traits>
friend std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const randen_engine<T>& engine) { // NOLINT(runtime/references)
using numeric_type =
typename random_internal::stream_format_type<result_type>::type;
auto saver = random_internal::make_ostream_state_saver(os);
auto* it = engine.state();
for (auto* end = it + kStateSizeT; it < end; ++it) {
// In the case that `elem` is `uint8_t`, it must be cast to something
// larger so that it prints as an integer rather than a character. For
// simplicity, apply the cast all circumstances.
os << static_cast<numeric_type>(little_endian::FromHost(*it))
<< os.fill();
}
os << engine.next_;
return os;
}
template <class CharT, class Traits>
friend std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
randen_engine<T>& engine) { // NOLINT(runtime/references)
using numeric_type =
typename random_internal::stream_format_type<result_type>::type;
result_type state[kStateSizeT];
size_t next;
for (auto& elem : state) {
// It is not possible to read uint8_t from wide streams, so it is
// necessary to read a wider type and then cast it to uint8_t.
numeric_type value;
is >> value;
elem = little_endian::ToHost(static_cast<result_type>(value));
}
is >> next;
if (is.fail()) {
return is;
}
std::memcpy(engine.state(), state, sizeof(state));
engine.next_ = next;
return is;
}
private:
static constexpr size_t kStateSizeT =
Randen::kStateBytes / sizeof(result_type);
static constexpr size_t kCapacityT =
Randen::kCapacityBytes / sizeof(result_type);
// Returns the state array pointer, which is aligned to 16 bytes.
// The first kCapacityT are the `inner' sponge; the remainder are available.
result_type* state() {
return reinterpret_cast<result_type*>(
(reinterpret_cast<uintptr_t>(&raw_state_) & 0xf) ? (raw_state_ + 8)
: raw_state_);
}
const result_type* state() const {
return const_cast<randen_engine*>(this)->state();
}
// raw state array, manually aligned in state(). This overallocates
// by 8 bytes since C++ does not guarantee extended heap alignment.
alignas(8) char raw_state_[Randen::kStateBytes + 8];
size_t next_; // index within state()
Randen impl_;
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_

View File

@@ -0,0 +1,526 @@
// 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.
// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
// symbols from arbitrary system and other headers, since it may be built
// with different flags from other targets, using different levels of
// optimization, potentially introducing ODR violations.
#include "absl/random/internal/randen_hwaes.h"
#include <cstdint>
#include <cstring>
#include "absl/base/attributes.h"
#include "absl/numeric/int128.h"
#include "absl/random/internal/platform.h"
#include "absl/random/internal/randen_traits.h"
// ABSL_RANDEN_HWAES_IMPL indicates whether this file will contain
// a hardware accelerated implementation of randen, or whether it
// will contain stubs that exit the process.
#if ABSL_HAVE_ACCELERATED_AES
// The following platforms have implemented RandenHwAes.
#if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32) || \
defined(ABSL_ARCH_PPC) || defined(ABSL_ARCH_ARM) || \
defined(ABSL_ARCH_AARCH64)
#define ABSL_RANDEN_HWAES_IMPL 1
#endif
#endif
#if !defined(ABSL_RANDEN_HWAES_IMPL)
// No accelerated implementation is supported.
// The RandenHwAes functions are stubs that print an error and exit.
#include <cstdio>
#include <cstdlib>
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// No accelerated implementation.
bool HasRandenHwAesImplementation() { return false; }
// NOLINTNEXTLINE
const void* RandenHwAes::GetKeys() {
// Attempted to dispatch to an unsupported dispatch target.
const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH;
fprintf(stderr, "AES Hardware detection failed (%d).\n", d);
exit(1);
return nullptr;
}
// NOLINTNEXTLINE
void RandenHwAes::Absorb(const void*, void*) {
// Attempted to dispatch to an unsupported dispatch target.
const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH;
fprintf(stderr, "AES Hardware detection failed (%d).\n", d);
exit(1);
}
// NOLINTNEXTLINE
void RandenHwAes::Generate(const void*, void*) {
// Attempted to dispatch to an unsupported dispatch target.
const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH;
fprintf(stderr, "AES Hardware detection failed (%d).\n", d);
exit(1);
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#else // defined(ABSL_RANDEN_HWAES_IMPL)
//
// Accelerated implementations are supported.
// We need the per-architecture includes and defines.
//
namespace {
using absl::random_internal::RandenTraits;
} // namespace
// TARGET_CRYPTO defines a crypto attribute for each architecture.
//
// NOTE: Evaluate whether we should eliminate ABSL_TARGET_CRYPTO.
#if (defined(__clang__) || defined(__GNUC__))
#if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)
#define ABSL_TARGET_CRYPTO __attribute__((target("aes")))
#elif defined(ABSL_ARCH_PPC)
#define ABSL_TARGET_CRYPTO __attribute__((target("crypto")))
#else
#define ABSL_TARGET_CRYPTO
#endif
#else
#define ABSL_TARGET_CRYPTO
#endif
#if defined(ABSL_ARCH_PPC)
// NOTE: Keep in mind that PPC can operate in little-endian or big-endian mode,
// however the PPC altivec vector registers (and thus the AES instructions)
// always operate in big-endian mode.
#include <altivec.h>
// <altivec.h> #defines vector __vector; in C++, this is bad form.
#undef vector
#undef bool
// Rely on the PowerPC AltiVec vector operations for accelerated AES
// instructions. GCC support of the PPC vector types is described in:
// https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/PowerPC-AltiVec_002fVSX-Built-in-Functions.html
//
// Already provides operator^=.
using Vector128 = __vector unsigned long long; // NOLINT(runtime/int)
namespace {
inline ABSL_TARGET_CRYPTO Vector128 ReverseBytes(const Vector128& v) {
// Reverses the bytes of the vector.
const __vector unsigned char perm = {15, 14, 13, 12, 11, 10, 9, 8,
7, 6, 5, 4, 3, 2, 1, 0};
return vec_perm(v, v, perm);
}
// WARNING: these load/store in native byte order. It is OK to load and then
// store an unchanged vector, but interpreting the bits as a number or input
// to AES will have undefined results.
inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
return vec_vsx_ld(0, reinterpret_cast<const Vector128*>(from));
}
inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
vec_vsx_st(v, 0, reinterpret_cast<Vector128*>(to));
}
// One round of AES. "round_key" is a public constant for breaking the
// symmetry of AES (ensures previously equal columns differ afterwards).
inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
const Vector128& round_key) {
return Vector128(__builtin_crypto_vcipher(state, round_key));
}
// Enables native loads in the round loop by pre-swapping.
inline ABSL_TARGET_CRYPTO void SwapEndian(absl::uint128* state) {
for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {
Vector128Store(ReverseBytes(Vector128Load(state + block)), state + block);
}
}
} // namespace
#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)
// Rely on the ARM NEON+Crypto advanced simd types, defined in <arm_neon.h>.
// uint8x16_t is the user alias for underlying __simd128_uint8_t type.
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf
//
// <arm_neon> defines the following
//
// typedef __attribute__((neon_vector_type(16))) uint8_t uint8x16_t;
// typedef __attribute__((neon_vector_type(16))) int8_t int8x16_t;
// typedef __attribute__((neon_polyvector_type(16))) int8_t poly8x16_t;
//
// vld1q_v
// vst1q_v
// vaeseq_v
// vaesmcq_v
#include <arm_neon.h>
// Already provides operator^=.
using Vector128 = uint8x16_t;
namespace {
inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
return vld1q_u8(reinterpret_cast<const uint8_t*>(from));
}
inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
vst1q_u8(reinterpret_cast<uint8_t*>(to), v);
}
// One round of AES. "round_key" is a public constant for breaking the
// symmetry of AES (ensures previously equal columns differ afterwards).
inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
const Vector128& round_key) {
// It is important to always use the full round function - omitting the
// final MixColumns reduces security [https://eprint.iacr.org/2010/041.pdf]
// and does not help because we never decrypt.
//
// Note that ARM divides AES instructions differently than x86 / PPC,
// And we need to skip the first AddRoundKey step and add an extra
// AddRoundKey step to the end. Lucky for us this is just XOR.
return vaesmcq_u8(vaeseq_u8(state, uint8x16_t{})) ^ round_key;
}
inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
} // namespace
#elif defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)
// On x86 we rely on the aesni instructions
#include <immintrin.h>
namespace {
// Vector128 class is only wrapper for __m128i, benchmark indicates that it's
// faster than using __m128i directly.
class Vector128 {
public:
// Convert from/to intrinsics.
inline explicit Vector128(const __m128i& v) : data_(v) {}
inline __m128i data() const { return data_; }
inline Vector128& operator^=(const Vector128& other) {
data_ = _mm_xor_si128(data_, other.data());
return *this;
}
private:
__m128i data_;
};
inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
return Vector128(_mm_load_si128(reinterpret_cast<const __m128i*>(from)));
}
inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
_mm_store_si128(reinterpret_cast<__m128i*>(to), v.data());
}
// One round of AES. "round_key" is a public constant for breaking the
// symmetry of AES (ensures previously equal columns differ afterwards).
inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
const Vector128& round_key) {
// It is important to always use the full round function - omitting the
// final MixColumns reduces security [https://eprint.iacr.org/2010/041.pdf]
// and does not help because we never decrypt.
return Vector128(_mm_aesenc_si128(state.data(), round_key.data()));
}
inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
} // namespace
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#endif
// At this point, all of the platform-specific features have been defined /
// implemented.
//
// REQUIRES: using Vector128 = ...
// REQUIRES: Vector128 Vector128Load(void*) {...}
// REQUIRES: void Vector128Store(Vector128, void*) {...}
// REQUIRES: Vector128 AesRound(Vector128, Vector128) {...}
// REQUIRES: void SwapEndian(uint64_t*) {...}
//
// PROVIDES: absl::random_internal::RandenHwAes::Absorb
// PROVIDES: absl::random_internal::RandenHwAes::Generate
namespace {
// Block shuffles applies a shuffle to the entire state between AES rounds.
// Improved odd-even shuffle from "New criterion for diffusion property".
inline ABSL_TARGET_CRYPTO void BlockShuffle(absl::uint128* state) {
static_assert(RandenTraits::kFeistelBlocks == 16,
"Expecting 16 FeistelBlocks.");
constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = {
7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};
const Vector128 v0 = Vector128Load(state + shuffle[0]);
const Vector128 v1 = Vector128Load(state + shuffle[1]);
const Vector128 v2 = Vector128Load(state + shuffle[2]);
const Vector128 v3 = Vector128Load(state + shuffle[3]);
const Vector128 v4 = Vector128Load(state + shuffle[4]);
const Vector128 v5 = Vector128Load(state + shuffle[5]);
const Vector128 v6 = Vector128Load(state + shuffle[6]);
const Vector128 v7 = Vector128Load(state + shuffle[7]);
const Vector128 w0 = Vector128Load(state + shuffle[8]);
const Vector128 w1 = Vector128Load(state + shuffle[9]);
const Vector128 w2 = Vector128Load(state + shuffle[10]);
const Vector128 w3 = Vector128Load(state + shuffle[11]);
const Vector128 w4 = Vector128Load(state + shuffle[12]);
const Vector128 w5 = Vector128Load(state + shuffle[13]);
const Vector128 w6 = Vector128Load(state + shuffle[14]);
const Vector128 w7 = Vector128Load(state + shuffle[15]);
Vector128Store(v0, state + 0);
Vector128Store(v1, state + 1);
Vector128Store(v2, state + 2);
Vector128Store(v3, state + 3);
Vector128Store(v4, state + 4);
Vector128Store(v5, state + 5);
Vector128Store(v6, state + 6);
Vector128Store(v7, state + 7);
Vector128Store(w0, state + 8);
Vector128Store(w1, state + 9);
Vector128Store(w2, state + 10);
Vector128Store(w3, state + 11);
Vector128Store(w4, state + 12);
Vector128Store(w5, state + 13);
Vector128Store(w6, state + 14);
Vector128Store(w7, state + 15);
}
// Feistel round function using two AES subrounds. Very similar to F()
// from Simpira v2, but with independent subround keys. Uses 17 AES rounds
// per 16 bytes (vs. 10 for AES-CTR). Computing eight round functions in
// parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel
// XORs are 'free' (included in the second AES instruction).
inline ABSL_TARGET_CRYPTO const absl::uint128* FeistelRound(
absl::uint128* state,
const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
static_assert(RandenTraits::kFeistelBlocks == 16,
"Expecting 16 FeistelBlocks.");
// MSVC does a horrible job at unrolling loops.
// So we unroll the loop by hand to improve the performance.
const Vector128 s0 = Vector128Load(state + 0);
const Vector128 s1 = Vector128Load(state + 1);
const Vector128 s2 = Vector128Load(state + 2);
const Vector128 s3 = Vector128Load(state + 3);
const Vector128 s4 = Vector128Load(state + 4);
const Vector128 s5 = Vector128Load(state + 5);
const Vector128 s6 = Vector128Load(state + 6);
const Vector128 s7 = Vector128Load(state + 7);
const Vector128 s8 = Vector128Load(state + 8);
const Vector128 s9 = Vector128Load(state + 9);
const Vector128 s10 = Vector128Load(state + 10);
const Vector128 s11 = Vector128Load(state + 11);
const Vector128 s12 = Vector128Load(state + 12);
const Vector128 s13 = Vector128Load(state + 13);
const Vector128 s14 = Vector128Load(state + 14);
const Vector128 s15 = Vector128Load(state + 15);
// Encode even blocks with keys.
const Vector128 e0 = AesRound(s0, Vector128Load(keys + 0));
const Vector128 e2 = AesRound(s2, Vector128Load(keys + 1));
const Vector128 e4 = AesRound(s4, Vector128Load(keys + 2));
const Vector128 e6 = AesRound(s6, Vector128Load(keys + 3));
const Vector128 e8 = AesRound(s8, Vector128Load(keys + 4));
const Vector128 e10 = AesRound(s10, Vector128Load(keys + 5));
const Vector128 e12 = AesRound(s12, Vector128Load(keys + 6));
const Vector128 e14 = AesRound(s14, Vector128Load(keys + 7));
// Encode odd blocks with even output from above.
const Vector128 o1 = AesRound(e0, s1);
const Vector128 o3 = AesRound(e2, s3);
const Vector128 o5 = AesRound(e4, s5);
const Vector128 o7 = AesRound(e6, s7);
const Vector128 o9 = AesRound(e8, s9);
const Vector128 o11 = AesRound(e10, s11);
const Vector128 o13 = AesRound(e12, s13);
const Vector128 o15 = AesRound(e14, s15);
// Store odd blocks. (These will be shuffled later).
Vector128Store(o1, state + 1);
Vector128Store(o3, state + 3);
Vector128Store(o5, state + 5);
Vector128Store(o7, state + 7);
Vector128Store(o9, state + 9);
Vector128Store(o11, state + 11);
Vector128Store(o13, state + 13);
Vector128Store(o15, state + 15);
return keys + 8;
}
// Cryptographic permutation based via type-2 Generalized Feistel Network.
// Indistinguishable from ideal by chosen-ciphertext adversaries using less than
// 2^64 queries if the round function is a PRF. This is similar to the b=8 case
// of Simpira v2, but more efficient than its generic construction for b=16.
inline ABSL_TARGET_CRYPTO void Permute(
absl::uint128* state,
const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
// (Successfully unrolled; the first iteration jumps into the second half)
#ifdef __clang__
#pragma clang loop unroll_count(2)
#endif
for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {
keys = FeistelRound(state, keys);
BlockShuffle(state);
}
}
} // namespace
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
bool HasRandenHwAesImplementation() { return true; }
const void* ABSL_TARGET_CRYPTO RandenHwAes::GetKeys() {
// Round keys for one AES per Feistel round and branch.
// The canonical implementation uses first digits of Pi.
#if defined(ABSL_ARCH_PPC)
return kRandenRoundKeysBE;
#else
return kRandenRoundKeys;
#endif
}
// NOLINTNEXTLINE
void ABSL_TARGET_CRYPTO RandenHwAes::Absorb(const void* seed_void,
void* state_void) {
static_assert(RandenTraits::kCapacityBytes / sizeof(Vector128) == 1,
"Unexpected Randen kCapacityBlocks");
static_assert(RandenTraits::kStateBytes / sizeof(Vector128) == 16,
"Unexpected Randen kStateBlocks");
auto* state = reinterpret_cast<absl::uint128 * ABSL_RANDOM_INTERNAL_RESTRICT>(
state_void);
const auto* seed =
reinterpret_cast<const absl::uint128 * ABSL_RANDOM_INTERNAL_RESTRICT>(
seed_void);
Vector128 b1 = Vector128Load(state + 1);
b1 ^= Vector128Load(seed + 0);
Vector128Store(b1, state + 1);
Vector128 b2 = Vector128Load(state + 2);
b2 ^= Vector128Load(seed + 1);
Vector128Store(b2, state + 2);
Vector128 b3 = Vector128Load(state + 3);
b3 ^= Vector128Load(seed + 2);
Vector128Store(b3, state + 3);
Vector128 b4 = Vector128Load(state + 4);
b4 ^= Vector128Load(seed + 3);
Vector128Store(b4, state + 4);
Vector128 b5 = Vector128Load(state + 5);
b5 ^= Vector128Load(seed + 4);
Vector128Store(b5, state + 5);
Vector128 b6 = Vector128Load(state + 6);
b6 ^= Vector128Load(seed + 5);
Vector128Store(b6, state + 6);
Vector128 b7 = Vector128Load(state + 7);
b7 ^= Vector128Load(seed + 6);
Vector128Store(b7, state + 7);
Vector128 b8 = Vector128Load(state + 8);
b8 ^= Vector128Load(seed + 7);
Vector128Store(b8, state + 8);
Vector128 b9 = Vector128Load(state + 9);
b9 ^= Vector128Load(seed + 8);
Vector128Store(b9, state + 9);
Vector128 b10 = Vector128Load(state + 10);
b10 ^= Vector128Load(seed + 9);
Vector128Store(b10, state + 10);
Vector128 b11 = Vector128Load(state + 11);
b11 ^= Vector128Load(seed + 10);
Vector128Store(b11, state + 11);
Vector128 b12 = Vector128Load(state + 12);
b12 ^= Vector128Load(seed + 11);
Vector128Store(b12, state + 12);
Vector128 b13 = Vector128Load(state + 13);
b13 ^= Vector128Load(seed + 12);
Vector128Store(b13, state + 13);
Vector128 b14 = Vector128Load(state + 14);
b14 ^= Vector128Load(seed + 13);
Vector128Store(b14, state + 14);
Vector128 b15 = Vector128Load(state + 15);
b15 ^= Vector128Load(seed + 14);
Vector128Store(b15, state + 15);
}
// NOLINTNEXTLINE
void ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys_void,
void* state_void) {
static_assert(RandenTraits::kCapacityBytes == sizeof(Vector128),
"Capacity mismatch");
auto* state = reinterpret_cast<absl::uint128*>(state_void);
const auto* keys = reinterpret_cast<const absl::uint128*>(keys_void);
const Vector128 prev_inner = Vector128Load(state);
SwapEndian(state);
Permute(state, keys);
SwapEndian(state);
// Ensure backtracking resistance.
Vector128 inner = Vector128Load(state);
inner ^= prev_inner;
Vector128Store(inner, state);
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // (ABSL_RANDEN_HWAES_IMPL)

View File

@@ -0,0 +1,50 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_
#include "absl/base/config.h"
// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
// symbols from arbitrary system and other headers, since it may be built
// with different flags from other targets, using different levels of
// optimization, potentially introducing ODR violations.
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RANDen = RANDom generator or beetroots in Swiss High German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
// RandenHwAes implements the basic state manipulation methods.
class RandenHwAes {
public:
static void Generate(const void* keys, void* state_void);
static void Absorb(const void* seed_void, void* state_void);
static const void* GetKeys();
};
// HasRandenHwAesImplementation returns true when there is an accelerated
// implementation, and false otherwise. If there is no implementation,
// then attempting to use it will abort the program.
bool HasRandenHwAesImplementation();
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_

View File

@@ -0,0 +1,462 @@
// 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.
#include "absl/random/internal/randen_traits.h"
// This file contains only the round keys for randen.
//
// "Nothing up my sleeve" numbers from the first hex digits of Pi, obtained
// from http://hexpi.sourceforge.net/. The array was generated by following
// Python script:
/*
python >tmp.cc << EOF
"""Generates Randen round keys array from pi-hex.62500.txt file."""
import binascii
KEYS = 17 * 8
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
def pairwise(t):
"""Transforms sequence into sequence of pairs."""
it = iter(t)
return zip(it,it)
def digits_from_pi():
"""Reads digits from hexpi.sourceforge.net file."""
with open("pi-hex.62500.txt") as file:
return file.read()
def digits_from_urandom():
"""Reads digits from /dev/urandom."""
with open("/dev/urandom") as file:
return binascii.hexlify(file.read(KEYS * 16))
def print_row(b)
print(" 0x{0}, 0x{1}, 0x{2}, 0x{3}, 0x{4}, 0x{5}, 0x{6}, 0x{7}, 0x{8}, 0x{9},
0x{10}, 0x{11}, 0x{12}, 0x{13}, 0x{14}, 0x{15},".format(*b))
digits = digits_from_pi()
#digits = digits_from_urandom()
print("namespace {")
print("static constexpr size_t kKeyBytes = {0};\n".format(KEYS * 16))
print("}")
print("alignas(16) const unsigned char kRandenRoundKeysBE[kKeyBytes] = {")
for i, u16 in zip(range(KEYS), chunks(digits, 32)):
b = list(chunks(u16, 2))
print_row(b)
print("};")
print("alignas(16) const unsigned char kRandenRoundKeys[kKeyBytes] = {")
for i, u16 in zip(range(KEYS), chunks(digits, 32)):
b = list(chunks(u16, 2))
b.reverse()
print_row(b)
print("};")
EOF
*/
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
namespace {
static constexpr size_t kKeyBytes = 2176;
}
alignas(16) const unsigned char kRandenRoundKeysBE[kKeyBytes] = {
0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E,
0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, 0x45, 0x28, 0x21, 0xE6,
0x38, 0xD0, 0x13, 0x77, 0xBE, 0x54, 0x66, 0xCF, 0x34, 0xE9, 0x0C, 0x6C,
0xC0, 0xAC, 0x29, 0xB7, 0xC9, 0x7C, 0x50, 0xDD, 0x3F, 0x84, 0xD5, 0xB5,
0xB5, 0x47, 0x09, 0x17, 0x92, 0x16, 0xD5, 0xD9, 0x89, 0x79, 0xFB, 0x1B,
0xD1, 0x31, 0x0B, 0xA6, 0x98, 0xDF, 0xB5, 0xAC, 0x2F, 0xFD, 0x72, 0xDB,
0xD0, 0x1A, 0xDF, 0xB7, 0xB8, 0xE1, 0xAF, 0xED, 0x6A, 0x26, 0x7E, 0x96,
0xBA, 0x7C, 0x90, 0x45, 0xF1, 0x2C, 0x7F, 0x99, 0x24, 0xA1, 0x99, 0x47,
0xB3, 0x91, 0x6C, 0xF7, 0x08, 0x01, 0xF2, 0xE2, 0x85, 0x8E, 0xFC, 0x16,
0x63, 0x69, 0x20, 0xD8, 0x71, 0x57, 0x4E, 0x69, 0xA4, 0x58, 0xFE, 0xA3,
0xF4, 0x93, 0x3D, 0x7E, 0x0D, 0x95, 0x74, 0x8F, 0x72, 0x8E, 0xB6, 0x58,
0x71, 0x8B, 0xCD, 0x58, 0x82, 0x15, 0x4A, 0xEE, 0x7B, 0x54, 0xA4, 0x1D,
0xC2, 0x5A, 0x59, 0xB5, 0x9C, 0x30, 0xD5, 0x39, 0x2A, 0xF2, 0x60, 0x13,
0xC5, 0xD1, 0xB0, 0x23, 0x28, 0x60, 0x85, 0xF0, 0xCA, 0x41, 0x79, 0x18,
0xB8, 0xDB, 0x38, 0xEF, 0x8E, 0x79, 0xDC, 0xB0, 0x60, 0x3A, 0x18, 0x0E,
0x6C, 0x9E, 0x0E, 0x8B, 0xB0, 0x1E, 0x8A, 0x3E, 0xD7, 0x15, 0x77, 0xC1,
0xBD, 0x31, 0x4B, 0x27, 0x78, 0xAF, 0x2F, 0xDA, 0x55, 0x60, 0x5C, 0x60,
0xE6, 0x55, 0x25, 0xF3, 0xAA, 0x55, 0xAB, 0x94, 0x57, 0x48, 0x98, 0x62,
0x63, 0xE8, 0x14, 0x40, 0x55, 0xCA, 0x39, 0x6A, 0x2A, 0xAB, 0x10, 0xB6,
0xB4, 0xCC, 0x5C, 0x34, 0x11, 0x41, 0xE8, 0xCE, 0xA1, 0x54, 0x86, 0xAF,
0x7C, 0x72, 0xE9, 0x93, 0xB3, 0xEE, 0x14, 0x11, 0x63, 0x6F, 0xBC, 0x2A,
0x2B, 0xA9, 0xC5, 0x5D, 0x74, 0x18, 0x31, 0xF6, 0xCE, 0x5C, 0x3E, 0x16,
0x9B, 0x87, 0x93, 0x1E, 0xAF, 0xD6, 0xBA, 0x33, 0x6C, 0x24, 0xCF, 0x5C,
0x7A, 0x32, 0x53, 0x81, 0x28, 0x95, 0x86, 0x77, 0x3B, 0x8F, 0x48, 0x98,
0x6B, 0x4B, 0xB9, 0xAF, 0xC4, 0xBF, 0xE8, 0x1B, 0x66, 0x28, 0x21, 0x93,
0x61, 0xD8, 0x09, 0xCC, 0xFB, 0x21, 0xA9, 0x91, 0x48, 0x7C, 0xAC, 0x60,
0x5D, 0xEC, 0x80, 0x32, 0xEF, 0x84, 0x5D, 0x5D, 0xE9, 0x85, 0x75, 0xB1,
0xDC, 0x26, 0x23, 0x02, 0xEB, 0x65, 0x1B, 0x88, 0x23, 0x89, 0x3E, 0x81,
0xD3, 0x96, 0xAC, 0xC5, 0x0F, 0x6D, 0x6F, 0xF3, 0x83, 0xF4, 0x42, 0x39,
0x2E, 0x0B, 0x44, 0x82, 0xA4, 0x84, 0x20, 0x04, 0x69, 0xC8, 0xF0, 0x4A,
0x9E, 0x1F, 0x9B, 0x5E, 0x21, 0xC6, 0x68, 0x42, 0xF6, 0xE9, 0x6C, 0x9A,
0x67, 0x0C, 0x9C, 0x61, 0xAB, 0xD3, 0x88, 0xF0, 0x6A, 0x51, 0xA0, 0xD2,
0xD8, 0x54, 0x2F, 0x68, 0x96, 0x0F, 0xA7, 0x28, 0xAB, 0x51, 0x33, 0xA3,
0x6E, 0xEF, 0x0B, 0x6C, 0x13, 0x7A, 0x3B, 0xE4, 0xBA, 0x3B, 0xF0, 0x50,
0x7E, 0xFB, 0x2A, 0x98, 0xA1, 0xF1, 0x65, 0x1D, 0x39, 0xAF, 0x01, 0x76,
0x66, 0xCA, 0x59, 0x3E, 0x82, 0x43, 0x0E, 0x88, 0x8C, 0xEE, 0x86, 0x19,
0x45, 0x6F, 0x9F, 0xB4, 0x7D, 0x84, 0xA5, 0xC3, 0x3B, 0x8B, 0x5E, 0xBE,
0xE0, 0x6F, 0x75, 0xD8, 0x85, 0xC1, 0x20, 0x73, 0x40, 0x1A, 0x44, 0x9F,
0x56, 0xC1, 0x6A, 0xA6, 0x4E, 0xD3, 0xAA, 0x62, 0x36, 0x3F, 0x77, 0x06,
0x1B, 0xFE, 0xDF, 0x72, 0x42, 0x9B, 0x02, 0x3D, 0x37, 0xD0, 0xD7, 0x24,
0xD0, 0x0A, 0x12, 0x48, 0xDB, 0x0F, 0xEA, 0xD3, 0x49, 0xF1, 0xC0, 0x9B,
0x07, 0x53, 0x72, 0xC9, 0x80, 0x99, 0x1B, 0x7B, 0x25, 0xD4, 0x79, 0xD8,
0xF6, 0xE8, 0xDE, 0xF7, 0xE3, 0xFE, 0x50, 0x1A, 0xB6, 0x79, 0x4C, 0x3B,
0x97, 0x6C, 0xE0, 0xBD, 0x04, 0xC0, 0x06, 0xBA, 0xC1, 0xA9, 0x4F, 0xB6,
0x40, 0x9F, 0x60, 0xC4, 0x5E, 0x5C, 0x9E, 0xC2, 0x19, 0x6A, 0x24, 0x63,
0x68, 0xFB, 0x6F, 0xAF, 0x3E, 0x6C, 0x53, 0xB5, 0x13, 0x39, 0xB2, 0xEB,
0x3B, 0x52, 0xEC, 0x6F, 0x6D, 0xFC, 0x51, 0x1F, 0x9B, 0x30, 0x95, 0x2C,
0xCC, 0x81, 0x45, 0x44, 0xAF, 0x5E, 0xBD, 0x09, 0xBE, 0xE3, 0xD0, 0x04,
0xDE, 0x33, 0x4A, 0xFD, 0x66, 0x0F, 0x28, 0x07, 0x19, 0x2E, 0x4B, 0xB3,
0xC0, 0xCB, 0xA8, 0x57, 0x45, 0xC8, 0x74, 0x0F, 0xD2, 0x0B, 0x5F, 0x39,
0xB9, 0xD3, 0xFB, 0xDB, 0x55, 0x79, 0xC0, 0xBD, 0x1A, 0x60, 0x32, 0x0A,
0xD6, 0xA1, 0x00, 0xC6, 0x40, 0x2C, 0x72, 0x79, 0x67, 0x9F, 0x25, 0xFE,
0xFB, 0x1F, 0xA3, 0xCC, 0x8E, 0xA5, 0xE9, 0xF8, 0xDB, 0x32, 0x22, 0xF8,
0x3C, 0x75, 0x16, 0xDF, 0xFD, 0x61, 0x6B, 0x15, 0x2F, 0x50, 0x1E, 0xC8,
0xAD, 0x05, 0x52, 0xAB, 0x32, 0x3D, 0xB5, 0xFA, 0xFD, 0x23, 0x87, 0x60,
0x53, 0x31, 0x7B, 0x48, 0x3E, 0x00, 0xDF, 0x82, 0x9E, 0x5C, 0x57, 0xBB,
0xCA, 0x6F, 0x8C, 0xA0, 0x1A, 0x87, 0x56, 0x2E, 0xDF, 0x17, 0x69, 0xDB,
0xD5, 0x42, 0xA8, 0xF6, 0x28, 0x7E, 0xFF, 0xC3, 0xAC, 0x67, 0x32, 0xC6,
0x8C, 0x4F, 0x55, 0x73, 0x69, 0x5B, 0x27, 0xB0, 0xBB, 0xCA, 0x58, 0xC8,
0xE1, 0xFF, 0xA3, 0x5D, 0xB8, 0xF0, 0x11, 0xA0, 0x10, 0xFA, 0x3D, 0x98,
0xFD, 0x21, 0x83, 0xB8, 0x4A, 0xFC, 0xB5, 0x6C, 0x2D, 0xD1, 0xD3, 0x5B,
0x9A, 0x53, 0xE4, 0x79, 0xB6, 0xF8, 0x45, 0x65, 0xD2, 0x8E, 0x49, 0xBC,
0x4B, 0xFB, 0x97, 0x90, 0xE1, 0xDD, 0xF2, 0xDA, 0xA4, 0xCB, 0x7E, 0x33,
0x62, 0xFB, 0x13, 0x41, 0xCE, 0xE4, 0xC6, 0xE8, 0xEF, 0x20, 0xCA, 0xDA,
0x36, 0x77, 0x4C, 0x01, 0xD0, 0x7E, 0x9E, 0xFE, 0x2B, 0xF1, 0x1F, 0xB4,
0x95, 0xDB, 0xDA, 0x4D, 0xAE, 0x90, 0x91, 0x98, 0xEA, 0xAD, 0x8E, 0x71,
0x6B, 0x93, 0xD5, 0xA0, 0xD0, 0x8E, 0xD1, 0xD0, 0xAF, 0xC7, 0x25, 0xE0,
0x8E, 0x3C, 0x5B, 0x2F, 0x8E, 0x75, 0x94, 0xB7, 0x8F, 0xF6, 0xE2, 0xFB,
0xF2, 0x12, 0x2B, 0x64, 0x88, 0x88, 0xB8, 0x12, 0x90, 0x0D, 0xF0, 0x1C,
0x4F, 0xAD, 0x5E, 0xA0, 0x68, 0x8F, 0xC3, 0x1C, 0xD1, 0xCF, 0xF1, 0x91,
0xB3, 0xA8, 0xC1, 0xAD, 0x2F, 0x2F, 0x22, 0x18, 0xBE, 0x0E, 0x17, 0x77,
0xEA, 0x75, 0x2D, 0xFE, 0x8B, 0x02, 0x1F, 0xA1, 0xE5, 0xA0, 0xCC, 0x0F,
0xB5, 0x6F, 0x74, 0xE8, 0x18, 0xAC, 0xF3, 0xD6, 0xCE, 0x89, 0xE2, 0x99,
0xB4, 0xA8, 0x4F, 0xE0, 0xFD, 0x13, 0xE0, 0xB7, 0x7C, 0xC4, 0x3B, 0x81,
0xD2, 0xAD, 0xA8, 0xD9, 0x16, 0x5F, 0xA2, 0x66, 0x80, 0x95, 0x77, 0x05,
0x93, 0xCC, 0x73, 0x14, 0x21, 0x1A, 0x14, 0x77, 0xE6, 0xAD, 0x20, 0x65,
0x77, 0xB5, 0xFA, 0x86, 0xC7, 0x54, 0x42, 0xF5, 0xFB, 0x9D, 0x35, 0xCF,
0xEB, 0xCD, 0xAF, 0x0C, 0x7B, 0x3E, 0x89, 0xA0, 0xD6, 0x41, 0x1B, 0xD3,
0xAE, 0x1E, 0x7E, 0x49, 0x00, 0x25, 0x0E, 0x2D, 0x20, 0x71, 0xB3, 0x5E,
0x22, 0x68, 0x00, 0xBB, 0x57, 0xB8, 0xE0, 0xAF, 0x24, 0x64, 0x36, 0x9B,
0xF0, 0x09, 0xB9, 0x1E, 0x55, 0x63, 0x91, 0x1D, 0x59, 0xDF, 0xA6, 0xAA,
0x78, 0xC1, 0x43, 0x89, 0xD9, 0x5A, 0x53, 0x7F, 0x20, 0x7D, 0x5B, 0xA2,
0x02, 0xE5, 0xB9, 0xC5, 0x83, 0x26, 0x03, 0x76, 0x62, 0x95, 0xCF, 0xA9,
0x11, 0xC8, 0x19, 0x68, 0x4E, 0x73, 0x4A, 0x41, 0xB3, 0x47, 0x2D, 0xCA,
0x7B, 0x14, 0xA9, 0x4A, 0x1B, 0x51, 0x00, 0x52, 0x9A, 0x53, 0x29, 0x15,
0xD6, 0x0F, 0x57, 0x3F, 0xBC, 0x9B, 0xC6, 0xE4, 0x2B, 0x60, 0xA4, 0x76,
0x81, 0xE6, 0x74, 0x00, 0x08, 0xBA, 0x6F, 0xB5, 0x57, 0x1B, 0xE9, 0x1F,
0xF2, 0x96, 0xEC, 0x6B, 0x2A, 0x0D, 0xD9, 0x15, 0xB6, 0x63, 0x65, 0x21,
0xE7, 0xB9, 0xF9, 0xB6, 0xFF, 0x34, 0x05, 0x2E, 0xC5, 0x85, 0x56, 0x64,
0x53, 0xB0, 0x2D, 0x5D, 0xA9, 0x9F, 0x8F, 0xA1, 0x08, 0xBA, 0x47, 0x99,
0x6E, 0x85, 0x07, 0x6A, 0x4B, 0x7A, 0x70, 0xE9, 0xB5, 0xB3, 0x29, 0x44,
0xDB, 0x75, 0x09, 0x2E, 0xC4, 0x19, 0x26, 0x23, 0xAD, 0x6E, 0xA6, 0xB0,
0x49, 0xA7, 0xDF, 0x7D, 0x9C, 0xEE, 0x60, 0xB8, 0x8F, 0xED, 0xB2, 0x66,
0xEC, 0xAA, 0x8C, 0x71, 0x69, 0x9A, 0x18, 0xFF, 0x56, 0x64, 0x52, 0x6C,
0xC2, 0xB1, 0x9E, 0xE1, 0x19, 0x36, 0x02, 0xA5, 0x75, 0x09, 0x4C, 0x29,
0xA0, 0x59, 0x13, 0x40, 0xE4, 0x18, 0x3A, 0x3E, 0x3F, 0x54, 0x98, 0x9A,
0x5B, 0x42, 0x9D, 0x65, 0x6B, 0x8F, 0xE4, 0xD6, 0x99, 0xF7, 0x3F, 0xD6,
0xA1, 0xD2, 0x9C, 0x07, 0xEF, 0xE8, 0x30, 0xF5, 0x4D, 0x2D, 0x38, 0xE6,
0xF0, 0x25, 0x5D, 0xC1, 0x4C, 0xDD, 0x20, 0x86, 0x84, 0x70, 0xEB, 0x26,
0x63, 0x82, 0xE9, 0xC6, 0x02, 0x1E, 0xCC, 0x5E, 0x09, 0x68, 0x6B, 0x3F,
0x3E, 0xBA, 0xEF, 0xC9, 0x3C, 0x97, 0x18, 0x14, 0x6B, 0x6A, 0x70, 0xA1,
0x68, 0x7F, 0x35, 0x84, 0x52, 0xA0, 0xE2, 0x86, 0xB7, 0x9C, 0x53, 0x05,
0xAA, 0x50, 0x07, 0x37, 0x3E, 0x07, 0x84, 0x1C, 0x7F, 0xDE, 0xAE, 0x5C,
0x8E, 0x7D, 0x44, 0xEC, 0x57, 0x16, 0xF2, 0xB8, 0xB0, 0x3A, 0xDA, 0x37,
0xF0, 0x50, 0x0C, 0x0D, 0xF0, 0x1C, 0x1F, 0x04, 0x02, 0x00, 0xB3, 0xFF,
0xAE, 0x0C, 0xF5, 0x1A, 0x3C, 0xB5, 0x74, 0xB2, 0x25, 0x83, 0x7A, 0x58,
0xDC, 0x09, 0x21, 0xBD, 0xD1, 0x91, 0x13, 0xF9, 0x7C, 0xA9, 0x2F, 0xF6,
0x94, 0x32, 0x47, 0x73, 0x22, 0xF5, 0x47, 0x01, 0x3A, 0xE5, 0xE5, 0x81,
0x37, 0xC2, 0xDA, 0xDC, 0xC8, 0xB5, 0x76, 0x34, 0x9A, 0xF3, 0xDD, 0xA7,
0xA9, 0x44, 0x61, 0x46, 0x0F, 0xD0, 0x03, 0x0E, 0xEC, 0xC8, 0xC7, 0x3E,
0xA4, 0x75, 0x1E, 0x41, 0xE2, 0x38, 0xCD, 0x99, 0x3B, 0xEA, 0x0E, 0x2F,
0x32, 0x80, 0xBB, 0xA1, 0x18, 0x3E, 0xB3, 0x31, 0x4E, 0x54, 0x8B, 0x38,
0x4F, 0x6D, 0xB9, 0x08, 0x6F, 0x42, 0x0D, 0x03, 0xF6, 0x0A, 0x04, 0xBF,
0x2C, 0xB8, 0x12, 0x90, 0x24, 0x97, 0x7C, 0x79, 0x56, 0x79, 0xB0, 0x72,
0xBC, 0xAF, 0x89, 0xAF, 0xDE, 0x9A, 0x77, 0x1F, 0xD9, 0x93, 0x08, 0x10,
0xB3, 0x8B, 0xAE, 0x12, 0xDC, 0xCF, 0x3F, 0x2E, 0x55, 0x12, 0x72, 0x1F,
0x2E, 0x6B, 0x71, 0x24, 0x50, 0x1A, 0xDD, 0xE6, 0x9F, 0x84, 0xCD, 0x87,
0x7A, 0x58, 0x47, 0x18, 0x74, 0x08, 0xDA, 0x17, 0xBC, 0x9F, 0x9A, 0xBC,
0xE9, 0x4B, 0x7D, 0x8C, 0xEC, 0x7A, 0xEC, 0x3A, 0xDB, 0x85, 0x1D, 0xFA,
0x63, 0x09, 0x43, 0x66, 0xC4, 0x64, 0xC3, 0xD2, 0xEF, 0x1C, 0x18, 0x47,
0x32, 0x15, 0xD8, 0x08, 0xDD, 0x43, 0x3B, 0x37, 0x24, 0xC2, 0xBA, 0x16,
0x12, 0xA1, 0x4D, 0x43, 0x2A, 0x65, 0xC4, 0x51, 0x50, 0x94, 0x00, 0x02,
0x13, 0x3A, 0xE4, 0xDD, 0x71, 0xDF, 0xF8, 0x9E, 0x10, 0x31, 0x4E, 0x55,
0x81, 0xAC, 0x77, 0xD6, 0x5F, 0x11, 0x19, 0x9B, 0x04, 0x35, 0x56, 0xF1,
0xD7, 0xA3, 0xC7, 0x6B, 0x3C, 0x11, 0x18, 0x3B, 0x59, 0x24, 0xA5, 0x09,
0xF2, 0x8F, 0xE6, 0xED, 0x97, 0xF1, 0xFB, 0xFA, 0x9E, 0xBA, 0xBF, 0x2C,
0x1E, 0x15, 0x3C, 0x6E, 0x86, 0xE3, 0x45, 0x70, 0xEA, 0xE9, 0x6F, 0xB1,
0x86, 0x0E, 0x5E, 0x0A, 0x5A, 0x3E, 0x2A, 0xB3, 0x77, 0x1F, 0xE7, 0x1C,
0x4E, 0x3D, 0x06, 0xFA, 0x29, 0x65, 0xDC, 0xB9, 0x99, 0xE7, 0x1D, 0x0F,
0x80, 0x3E, 0x89, 0xD6, 0x52, 0x66, 0xC8, 0x25, 0x2E, 0x4C, 0xC9, 0x78,
0x9C, 0x10, 0xB3, 0x6A, 0xC6, 0x15, 0x0E, 0xBA, 0x94, 0xE2, 0xEA, 0x78,
0xA6, 0xFC, 0x3C, 0x53, 0x1E, 0x0A, 0x2D, 0xF4, 0xF2, 0xF7, 0x4E, 0xA7,
0x36, 0x1D, 0x2B, 0x3D, 0x19, 0x39, 0x26, 0x0F, 0x19, 0xC2, 0x79, 0x60,
0x52, 0x23, 0xA7, 0x08, 0xF7, 0x13, 0x12, 0xB6, 0xEB, 0xAD, 0xFE, 0x6E,
0xEA, 0xC3, 0x1F, 0x66, 0xE3, 0xBC, 0x45, 0x95, 0xA6, 0x7B, 0xC8, 0x83,
0xB1, 0x7F, 0x37, 0xD1, 0x01, 0x8C, 0xFF, 0x28, 0xC3, 0x32, 0xDD, 0xEF,
0xBE, 0x6C, 0x5A, 0xA5, 0x65, 0x58, 0x21, 0x85, 0x68, 0xAB, 0x97, 0x02,
0xEE, 0xCE, 0xA5, 0x0F, 0xDB, 0x2F, 0x95, 0x3B, 0x2A, 0xEF, 0x7D, 0xAD,
0x5B, 0x6E, 0x2F, 0x84, 0x15, 0x21, 0xB6, 0x28, 0x29, 0x07, 0x61, 0x70,
0xEC, 0xDD, 0x47, 0x75, 0x61, 0x9F, 0x15, 0x10, 0x13, 0xCC, 0xA8, 0x30,
0xEB, 0x61, 0xBD, 0x96, 0x03, 0x34, 0xFE, 0x1E, 0xAA, 0x03, 0x63, 0xCF,
0xB5, 0x73, 0x5C, 0x90, 0x4C, 0x70, 0xA2, 0x39, 0xD5, 0x9E, 0x9E, 0x0B,
0xCB, 0xAA, 0xDE, 0x14, 0xEE, 0xCC, 0x86, 0xBC, 0x60, 0x62, 0x2C, 0xA7,
0x9C, 0xAB, 0x5C, 0xAB, 0xB2, 0xF3, 0x84, 0x6E, 0x64, 0x8B, 0x1E, 0xAF,
0x19, 0xBD, 0xF0, 0xCA, 0xA0, 0x23, 0x69, 0xB9, 0x65, 0x5A, 0xBB, 0x50,
0x40, 0x68, 0x5A, 0x32, 0x3C, 0x2A, 0xB4, 0xB3, 0x31, 0x9E, 0xE9, 0xD5,
0xC0, 0x21, 0xB8, 0xF7, 0x9B, 0x54, 0x0B, 0x19, 0x87, 0x5F, 0xA0, 0x99,
0x95, 0xF7, 0x99, 0x7E, 0x62, 0x3D, 0x7D, 0xA8, 0xF8, 0x37, 0x88, 0x9A,
0x97, 0xE3, 0x2D, 0x77, 0x11, 0xED, 0x93, 0x5F, 0x16, 0x68, 0x12, 0x81,
0x0E, 0x35, 0x88, 0x29, 0xC7, 0xE6, 0x1F, 0xD6, 0x96, 0xDE, 0xDF, 0xA1,
0x78, 0x58, 0xBA, 0x99, 0x57, 0xF5, 0x84, 0xA5, 0x1B, 0x22, 0x72, 0x63,
0x9B, 0x83, 0xC3, 0xFF, 0x1A, 0xC2, 0x46, 0x96, 0xCD, 0xB3, 0x0A, 0xEB,
0x53, 0x2E, 0x30, 0x54, 0x8F, 0xD9, 0x48, 0xE4, 0x6D, 0xBC, 0x31, 0x28,
0x58, 0xEB, 0xF2, 0xEF, 0x34, 0xC6, 0xFF, 0xEA, 0xFE, 0x28, 0xED, 0x61,
0xEE, 0x7C, 0x3C, 0x73, 0x5D, 0x4A, 0x14, 0xD9, 0xE8, 0x64, 0xB7, 0xE3,
0x42, 0x10, 0x5D, 0x14, 0x20, 0x3E, 0x13, 0xE0, 0x45, 0xEE, 0xE2, 0xB6,
0xA3, 0xAA, 0xAB, 0xEA, 0xDB, 0x6C, 0x4F, 0x15, 0xFA, 0xCB, 0x4F, 0xD0,
0xC7, 0x42, 0xF4, 0x42, 0xEF, 0x6A, 0xBB, 0xB5, 0x65, 0x4F, 0x3B, 0x1D,
0x41, 0xCD, 0x21, 0x05, 0xD8, 0x1E, 0x79, 0x9E, 0x86, 0x85, 0x4D, 0xC7,
0xE4, 0x4B, 0x47, 0x6A, 0x3D, 0x81, 0x62, 0x50, 0xCF, 0x62, 0xA1, 0xF2,
0x5B, 0x8D, 0x26, 0x46, 0xFC, 0x88, 0x83, 0xA0, 0xC1, 0xC7, 0xB6, 0xA3,
0x7F, 0x15, 0x24, 0xC3, 0x69, 0xCB, 0x74, 0x92, 0x47, 0x84, 0x8A, 0x0B,
0x56, 0x92, 0xB2, 0x85, 0x09, 0x5B, 0xBF, 0x00, 0xAD, 0x19, 0x48, 0x9D,
0x14, 0x62, 0xB1, 0x74, 0x23, 0x82, 0x0D, 0x00, 0x58, 0x42, 0x8D, 0x2A,
0x0C, 0x55, 0xF5, 0xEA, 0x1D, 0xAD, 0xF4, 0x3E, 0x23, 0x3F, 0x70, 0x61,
0x33, 0x72, 0xF0, 0x92, 0x8D, 0x93, 0x7E, 0x41, 0xD6, 0x5F, 0xEC, 0xF1,
0x6C, 0x22, 0x3B, 0xDB, 0x7C, 0xDE, 0x37, 0x59, 0xCB, 0xEE, 0x74, 0x60,
0x40, 0x85, 0xF2, 0xA7, 0xCE, 0x77, 0x32, 0x6E, 0xA6, 0x07, 0x80, 0x84,
0x19, 0xF8, 0x50, 0x9E, 0xE8, 0xEF, 0xD8, 0x55, 0x61, 0xD9, 0x97, 0x35,
0xA9, 0x69, 0xA7, 0xAA, 0xC5, 0x0C, 0x06, 0xC2, 0x5A, 0x04, 0xAB, 0xFC,
0x80, 0x0B, 0xCA, 0xDC, 0x9E, 0x44, 0x7A, 0x2E, 0xC3, 0x45, 0x34, 0x84,
0xFD, 0xD5, 0x67, 0x05, 0x0E, 0x1E, 0x9E, 0xC9, 0xDB, 0x73, 0xDB, 0xD3,
0x10, 0x55, 0x88, 0xCD, 0x67, 0x5F, 0xDA, 0x79, 0xE3, 0x67, 0x43, 0x40,
0xC5, 0xC4, 0x34, 0x65, 0x71, 0x3E, 0x38, 0xD8, 0x3D, 0x28, 0xF8, 0x9E,
0xF1, 0x6D, 0xFF, 0x20, 0x15, 0x3E, 0x21, 0xE7, 0x8F, 0xB0, 0x3D, 0x4A,
0xE6, 0xE3, 0x9F, 0x2B, 0xDB, 0x83, 0xAD, 0xF7, 0xE9, 0x3D, 0x5A, 0x68,
0x94, 0x81, 0x40, 0xF7, 0xF6, 0x4C, 0x26, 0x1C, 0x94, 0x69, 0x29, 0x34,
0x41, 0x15, 0x20, 0xF7, 0x76, 0x02, 0xD4, 0xF7, 0xBC, 0xF4, 0x6B, 0x2E,
0xD4, 0xA1, 0x00, 0x68, 0xD4, 0x08, 0x24, 0x71, 0x33, 0x20, 0xF4, 0x6A,
0x43, 0xB7, 0xD4, 0xB7, 0x50, 0x00, 0x61, 0xAF, 0x1E, 0x39, 0xF6, 0x2E,
0x97, 0x24, 0x45, 0x46,
};
alignas(16) const unsigned char kRandenRoundKeys[kKeyBytes] = {
0x44, 0x73, 0x70, 0x03, 0x2E, 0x8A, 0x19, 0x13, 0xD3, 0x08, 0xA3, 0x85,
0x88, 0x6A, 0x3F, 0x24, 0x89, 0x6C, 0x4E, 0xEC, 0x98, 0xFA, 0x2E, 0x08,
0xD0, 0x31, 0x9F, 0x29, 0x22, 0x38, 0x09, 0xA4, 0x6C, 0x0C, 0xE9, 0x34,
0xCF, 0x66, 0x54, 0xBE, 0x77, 0x13, 0xD0, 0x38, 0xE6, 0x21, 0x28, 0x45,
0x17, 0x09, 0x47, 0xB5, 0xB5, 0xD5, 0x84, 0x3F, 0xDD, 0x50, 0x7C, 0xC9,
0xB7, 0x29, 0xAC, 0xC0, 0xAC, 0xB5, 0xDF, 0x98, 0xA6, 0x0B, 0x31, 0xD1,
0x1B, 0xFB, 0x79, 0x89, 0xD9, 0xD5, 0x16, 0x92, 0x96, 0x7E, 0x26, 0x6A,
0xED, 0xAF, 0xE1, 0xB8, 0xB7, 0xDF, 0x1A, 0xD0, 0xDB, 0x72, 0xFD, 0x2F,
0xF7, 0x6C, 0x91, 0xB3, 0x47, 0x99, 0xA1, 0x24, 0x99, 0x7F, 0x2C, 0xF1,
0x45, 0x90, 0x7C, 0xBA, 0x69, 0x4E, 0x57, 0x71, 0xD8, 0x20, 0x69, 0x63,
0x16, 0xFC, 0x8E, 0x85, 0xE2, 0xF2, 0x01, 0x08, 0x58, 0xB6, 0x8E, 0x72,
0x8F, 0x74, 0x95, 0x0D, 0x7E, 0x3D, 0x93, 0xF4, 0xA3, 0xFE, 0x58, 0xA4,
0xB5, 0x59, 0x5A, 0xC2, 0x1D, 0xA4, 0x54, 0x7B, 0xEE, 0x4A, 0x15, 0x82,
0x58, 0xCD, 0x8B, 0x71, 0xF0, 0x85, 0x60, 0x28, 0x23, 0xB0, 0xD1, 0xC5,
0x13, 0x60, 0xF2, 0x2A, 0x39, 0xD5, 0x30, 0x9C, 0x0E, 0x18, 0x3A, 0x60,
0xB0, 0xDC, 0x79, 0x8E, 0xEF, 0x38, 0xDB, 0xB8, 0x18, 0x79, 0x41, 0xCA,
0x27, 0x4B, 0x31, 0xBD, 0xC1, 0x77, 0x15, 0xD7, 0x3E, 0x8A, 0x1E, 0xB0,
0x8B, 0x0E, 0x9E, 0x6C, 0x94, 0xAB, 0x55, 0xAA, 0xF3, 0x25, 0x55, 0xE6,
0x60, 0x5C, 0x60, 0x55, 0xDA, 0x2F, 0xAF, 0x78, 0xB6, 0x10, 0xAB, 0x2A,
0x6A, 0x39, 0xCA, 0x55, 0x40, 0x14, 0xE8, 0x63, 0x62, 0x98, 0x48, 0x57,
0x93, 0xE9, 0x72, 0x7C, 0xAF, 0x86, 0x54, 0xA1, 0xCE, 0xE8, 0x41, 0x11,
0x34, 0x5C, 0xCC, 0xB4, 0xF6, 0x31, 0x18, 0x74, 0x5D, 0xC5, 0xA9, 0x2B,
0x2A, 0xBC, 0x6F, 0x63, 0x11, 0x14, 0xEE, 0xB3, 0x5C, 0xCF, 0x24, 0x6C,
0x33, 0xBA, 0xD6, 0xAF, 0x1E, 0x93, 0x87, 0x9B, 0x16, 0x3E, 0x5C, 0xCE,
0xAF, 0xB9, 0x4B, 0x6B, 0x98, 0x48, 0x8F, 0x3B, 0x77, 0x86, 0x95, 0x28,
0x81, 0x53, 0x32, 0x7A, 0x91, 0xA9, 0x21, 0xFB, 0xCC, 0x09, 0xD8, 0x61,
0x93, 0x21, 0x28, 0x66, 0x1B, 0xE8, 0xBF, 0xC4, 0xB1, 0x75, 0x85, 0xE9,
0x5D, 0x5D, 0x84, 0xEF, 0x32, 0x80, 0xEC, 0x5D, 0x60, 0xAC, 0x7C, 0x48,
0xC5, 0xAC, 0x96, 0xD3, 0x81, 0x3E, 0x89, 0x23, 0x88, 0x1B, 0x65, 0xEB,
0x02, 0x23, 0x26, 0xDC, 0x04, 0x20, 0x84, 0xA4, 0x82, 0x44, 0x0B, 0x2E,
0x39, 0x42, 0xF4, 0x83, 0xF3, 0x6F, 0x6D, 0x0F, 0x9A, 0x6C, 0xE9, 0xF6,
0x42, 0x68, 0xC6, 0x21, 0x5E, 0x9B, 0x1F, 0x9E, 0x4A, 0xF0, 0xC8, 0x69,
0x68, 0x2F, 0x54, 0xD8, 0xD2, 0xA0, 0x51, 0x6A, 0xF0, 0x88, 0xD3, 0xAB,
0x61, 0x9C, 0x0C, 0x67, 0xE4, 0x3B, 0x7A, 0x13, 0x6C, 0x0B, 0xEF, 0x6E,
0xA3, 0x33, 0x51, 0xAB, 0x28, 0xA7, 0x0F, 0x96, 0x76, 0x01, 0xAF, 0x39,
0x1D, 0x65, 0xF1, 0xA1, 0x98, 0x2A, 0xFB, 0x7E, 0x50, 0xF0, 0x3B, 0xBA,
0xB4, 0x9F, 0x6F, 0x45, 0x19, 0x86, 0xEE, 0x8C, 0x88, 0x0E, 0x43, 0x82,
0x3E, 0x59, 0xCA, 0x66, 0x73, 0x20, 0xC1, 0x85, 0xD8, 0x75, 0x6F, 0xE0,
0xBE, 0x5E, 0x8B, 0x3B, 0xC3, 0xA5, 0x84, 0x7D, 0x06, 0x77, 0x3F, 0x36,
0x62, 0xAA, 0xD3, 0x4E, 0xA6, 0x6A, 0xC1, 0x56, 0x9F, 0x44, 0x1A, 0x40,
0x48, 0x12, 0x0A, 0xD0, 0x24, 0xD7, 0xD0, 0x37, 0x3D, 0x02, 0x9B, 0x42,
0x72, 0xDF, 0xFE, 0x1B, 0x7B, 0x1B, 0x99, 0x80, 0xC9, 0x72, 0x53, 0x07,
0x9B, 0xC0, 0xF1, 0x49, 0xD3, 0xEA, 0x0F, 0xDB, 0x3B, 0x4C, 0x79, 0xB6,
0x1A, 0x50, 0xFE, 0xE3, 0xF7, 0xDE, 0xE8, 0xF6, 0xD8, 0x79, 0xD4, 0x25,
0xC4, 0x60, 0x9F, 0x40, 0xB6, 0x4F, 0xA9, 0xC1, 0xBA, 0x06, 0xC0, 0x04,
0xBD, 0xE0, 0x6C, 0x97, 0xB5, 0x53, 0x6C, 0x3E, 0xAF, 0x6F, 0xFB, 0x68,
0x63, 0x24, 0x6A, 0x19, 0xC2, 0x9E, 0x5C, 0x5E, 0x2C, 0x95, 0x30, 0x9B,
0x1F, 0x51, 0xFC, 0x6D, 0x6F, 0xEC, 0x52, 0x3B, 0xEB, 0xB2, 0x39, 0x13,
0xFD, 0x4A, 0x33, 0xDE, 0x04, 0xD0, 0xE3, 0xBE, 0x09, 0xBD, 0x5E, 0xAF,
0x44, 0x45, 0x81, 0xCC, 0x0F, 0x74, 0xC8, 0x45, 0x57, 0xA8, 0xCB, 0xC0,
0xB3, 0x4B, 0x2E, 0x19, 0x07, 0x28, 0x0F, 0x66, 0x0A, 0x32, 0x60, 0x1A,
0xBD, 0xC0, 0x79, 0x55, 0xDB, 0xFB, 0xD3, 0xB9, 0x39, 0x5F, 0x0B, 0xD2,
0xCC, 0xA3, 0x1F, 0xFB, 0xFE, 0x25, 0x9F, 0x67, 0x79, 0x72, 0x2C, 0x40,
0xC6, 0x00, 0xA1, 0xD6, 0x15, 0x6B, 0x61, 0xFD, 0xDF, 0x16, 0x75, 0x3C,
0xF8, 0x22, 0x32, 0xDB, 0xF8, 0xE9, 0xA5, 0x8E, 0x60, 0x87, 0x23, 0xFD,
0xFA, 0xB5, 0x3D, 0x32, 0xAB, 0x52, 0x05, 0xAD, 0xC8, 0x1E, 0x50, 0x2F,
0xA0, 0x8C, 0x6F, 0xCA, 0xBB, 0x57, 0x5C, 0x9E, 0x82, 0xDF, 0x00, 0x3E,
0x48, 0x7B, 0x31, 0x53, 0xC3, 0xFF, 0x7E, 0x28, 0xF6, 0xA8, 0x42, 0xD5,
0xDB, 0x69, 0x17, 0xDF, 0x2E, 0x56, 0x87, 0x1A, 0xC8, 0x58, 0xCA, 0xBB,
0xB0, 0x27, 0x5B, 0x69, 0x73, 0x55, 0x4F, 0x8C, 0xC6, 0x32, 0x67, 0xAC,
0xB8, 0x83, 0x21, 0xFD, 0x98, 0x3D, 0xFA, 0x10, 0xA0, 0x11, 0xF0, 0xB8,
0x5D, 0xA3, 0xFF, 0xE1, 0x65, 0x45, 0xF8, 0xB6, 0x79, 0xE4, 0x53, 0x9A,
0x5B, 0xD3, 0xD1, 0x2D, 0x6C, 0xB5, 0xFC, 0x4A, 0x33, 0x7E, 0xCB, 0xA4,
0xDA, 0xF2, 0xDD, 0xE1, 0x90, 0x97, 0xFB, 0x4B, 0xBC, 0x49, 0x8E, 0xD2,
0x01, 0x4C, 0x77, 0x36, 0xDA, 0xCA, 0x20, 0xEF, 0xE8, 0xC6, 0xE4, 0xCE,
0x41, 0x13, 0xFB, 0x62, 0x98, 0x91, 0x90, 0xAE, 0x4D, 0xDA, 0xDB, 0x95,
0xB4, 0x1F, 0xF1, 0x2B, 0xFE, 0x9E, 0x7E, 0xD0, 0xE0, 0x25, 0xC7, 0xAF,
0xD0, 0xD1, 0x8E, 0xD0, 0xA0, 0xD5, 0x93, 0x6B, 0x71, 0x8E, 0xAD, 0xEA,
0x64, 0x2B, 0x12, 0xF2, 0xFB, 0xE2, 0xF6, 0x8F, 0xB7, 0x94, 0x75, 0x8E,
0x2F, 0x5B, 0x3C, 0x8E, 0x1C, 0xC3, 0x8F, 0x68, 0xA0, 0x5E, 0xAD, 0x4F,
0x1C, 0xF0, 0x0D, 0x90, 0x12, 0xB8, 0x88, 0x88, 0x77, 0x17, 0x0E, 0xBE,
0x18, 0x22, 0x2F, 0x2F, 0xAD, 0xC1, 0xA8, 0xB3, 0x91, 0xF1, 0xCF, 0xD1,
0xE8, 0x74, 0x6F, 0xB5, 0x0F, 0xCC, 0xA0, 0xE5, 0xA1, 0x1F, 0x02, 0x8B,
0xFE, 0x2D, 0x75, 0xEA, 0xB7, 0xE0, 0x13, 0xFD, 0xE0, 0x4F, 0xA8, 0xB4,
0x99, 0xE2, 0x89, 0xCE, 0xD6, 0xF3, 0xAC, 0x18, 0x05, 0x77, 0x95, 0x80,
0x66, 0xA2, 0x5F, 0x16, 0xD9, 0xA8, 0xAD, 0xD2, 0x81, 0x3B, 0xC4, 0x7C,
0x86, 0xFA, 0xB5, 0x77, 0x65, 0x20, 0xAD, 0xE6, 0x77, 0x14, 0x1A, 0x21,
0x14, 0x73, 0xCC, 0x93, 0xA0, 0x89, 0x3E, 0x7B, 0x0C, 0xAF, 0xCD, 0xEB,
0xCF, 0x35, 0x9D, 0xFB, 0xF5, 0x42, 0x54, 0xC7, 0x5E, 0xB3, 0x71, 0x20,
0x2D, 0x0E, 0x25, 0x00, 0x49, 0x7E, 0x1E, 0xAE, 0xD3, 0x1B, 0x41, 0xD6,
0x1E, 0xB9, 0x09, 0xF0, 0x9B, 0x36, 0x64, 0x24, 0xAF, 0xE0, 0xB8, 0x57,
0xBB, 0x00, 0x68, 0x22, 0x7F, 0x53, 0x5A, 0xD9, 0x89, 0x43, 0xC1, 0x78,
0xAA, 0xA6, 0xDF, 0x59, 0x1D, 0x91, 0x63, 0x55, 0xA9, 0xCF, 0x95, 0x62,
0x76, 0x03, 0x26, 0x83, 0xC5, 0xB9, 0xE5, 0x02, 0xA2, 0x5B, 0x7D, 0x20,
0x4A, 0xA9, 0x14, 0x7B, 0xCA, 0x2D, 0x47, 0xB3, 0x41, 0x4A, 0x73, 0x4E,
0x68, 0x19, 0xC8, 0x11, 0xE4, 0xC6, 0x9B, 0xBC, 0x3F, 0x57, 0x0F, 0xD6,
0x15, 0x29, 0x53, 0x9A, 0x52, 0x00, 0x51, 0x1B, 0x1F, 0xE9, 0x1B, 0x57,
0xB5, 0x6F, 0xBA, 0x08, 0x00, 0x74, 0xE6, 0x81, 0x76, 0xA4, 0x60, 0x2B,
0xB6, 0xF9, 0xB9, 0xE7, 0x21, 0x65, 0x63, 0xB6, 0x15, 0xD9, 0x0D, 0x2A,
0x6B, 0xEC, 0x96, 0xF2, 0xA1, 0x8F, 0x9F, 0xA9, 0x5D, 0x2D, 0xB0, 0x53,
0x64, 0x56, 0x85, 0xC5, 0x2E, 0x05, 0x34, 0xFF, 0x44, 0x29, 0xB3, 0xB5,
0xE9, 0x70, 0x7A, 0x4B, 0x6A, 0x07, 0x85, 0x6E, 0x99, 0x47, 0xBA, 0x08,
0x7D, 0xDF, 0xA7, 0x49, 0xB0, 0xA6, 0x6E, 0xAD, 0x23, 0x26, 0x19, 0xC4,
0x2E, 0x09, 0x75, 0xDB, 0xFF, 0x18, 0x9A, 0x69, 0x71, 0x8C, 0xAA, 0xEC,
0x66, 0xB2, 0xED, 0x8F, 0xB8, 0x60, 0xEE, 0x9C, 0x29, 0x4C, 0x09, 0x75,
0xA5, 0x02, 0x36, 0x19, 0xE1, 0x9E, 0xB1, 0xC2, 0x6C, 0x52, 0x64, 0x56,
0x65, 0x9D, 0x42, 0x5B, 0x9A, 0x98, 0x54, 0x3F, 0x3E, 0x3A, 0x18, 0xE4,
0x40, 0x13, 0x59, 0xA0, 0xF5, 0x30, 0xE8, 0xEF, 0x07, 0x9C, 0xD2, 0xA1,
0xD6, 0x3F, 0xF7, 0x99, 0xD6, 0xE4, 0x8F, 0x6B, 0x26, 0xEB, 0x70, 0x84,
0x86, 0x20, 0xDD, 0x4C, 0xC1, 0x5D, 0x25, 0xF0, 0xE6, 0x38, 0x2D, 0x4D,
0xC9, 0xEF, 0xBA, 0x3E, 0x3F, 0x6B, 0x68, 0x09, 0x5E, 0xCC, 0x1E, 0x02,
0xC6, 0xE9, 0x82, 0x63, 0x86, 0xE2, 0xA0, 0x52, 0x84, 0x35, 0x7F, 0x68,
0xA1, 0x70, 0x6A, 0x6B, 0x14, 0x18, 0x97, 0x3C, 0x5C, 0xAE, 0xDE, 0x7F,
0x1C, 0x84, 0x07, 0x3E, 0x37, 0x07, 0x50, 0xAA, 0x05, 0x53, 0x9C, 0xB7,
0x0D, 0x0C, 0x50, 0xF0, 0x37, 0xDA, 0x3A, 0xB0, 0xB8, 0xF2, 0x16, 0x57,
0xEC, 0x44, 0x7D, 0x8E, 0xB2, 0x74, 0xB5, 0x3C, 0x1A, 0xF5, 0x0C, 0xAE,
0xFF, 0xB3, 0x00, 0x02, 0x04, 0x1F, 0x1C, 0xF0, 0xF6, 0x2F, 0xA9, 0x7C,
0xF9, 0x13, 0x91, 0xD1, 0xBD, 0x21, 0x09, 0xDC, 0x58, 0x7A, 0x83, 0x25,
0xDC, 0xDA, 0xC2, 0x37, 0x81, 0xE5, 0xE5, 0x3A, 0x01, 0x47, 0xF5, 0x22,
0x73, 0x47, 0x32, 0x94, 0x0E, 0x03, 0xD0, 0x0F, 0x46, 0x61, 0x44, 0xA9,
0xA7, 0xDD, 0xF3, 0x9A, 0x34, 0x76, 0xB5, 0xC8, 0x2F, 0x0E, 0xEA, 0x3B,
0x99, 0xCD, 0x38, 0xE2, 0x41, 0x1E, 0x75, 0xA4, 0x3E, 0xC7, 0xC8, 0xEC,
0x08, 0xB9, 0x6D, 0x4F, 0x38, 0x8B, 0x54, 0x4E, 0x31, 0xB3, 0x3E, 0x18,
0xA1, 0xBB, 0x80, 0x32, 0x79, 0x7C, 0x97, 0x24, 0x90, 0x12, 0xB8, 0x2C,
0xBF, 0x04, 0x0A, 0xF6, 0x03, 0x0D, 0x42, 0x6F, 0x10, 0x08, 0x93, 0xD9,
0x1F, 0x77, 0x9A, 0xDE, 0xAF, 0x89, 0xAF, 0xBC, 0x72, 0xB0, 0x79, 0x56,
0x24, 0x71, 0x6B, 0x2E, 0x1F, 0x72, 0x12, 0x55, 0x2E, 0x3F, 0xCF, 0xDC,
0x12, 0xAE, 0x8B, 0xB3, 0x17, 0xDA, 0x08, 0x74, 0x18, 0x47, 0x58, 0x7A,
0x87, 0xCD, 0x84, 0x9F, 0xE6, 0xDD, 0x1A, 0x50, 0xFA, 0x1D, 0x85, 0xDB,
0x3A, 0xEC, 0x7A, 0xEC, 0x8C, 0x7D, 0x4B, 0xE9, 0xBC, 0x9A, 0x9F, 0xBC,
0x08, 0xD8, 0x15, 0x32, 0x47, 0x18, 0x1C, 0xEF, 0xD2, 0xC3, 0x64, 0xC4,
0x66, 0x43, 0x09, 0x63, 0x51, 0xC4, 0x65, 0x2A, 0x43, 0x4D, 0xA1, 0x12,
0x16, 0xBA, 0xC2, 0x24, 0x37, 0x3B, 0x43, 0xDD, 0x55, 0x4E, 0x31, 0x10,
0x9E, 0xF8, 0xDF, 0x71, 0xDD, 0xE4, 0x3A, 0x13, 0x02, 0x00, 0x94, 0x50,
0x6B, 0xC7, 0xA3, 0xD7, 0xF1, 0x56, 0x35, 0x04, 0x9B, 0x19, 0x11, 0x5F,
0xD6, 0x77, 0xAC, 0x81, 0xFA, 0xFB, 0xF1, 0x97, 0xED, 0xE6, 0x8F, 0xF2,
0x09, 0xA5, 0x24, 0x59, 0x3B, 0x18, 0x11, 0x3C, 0xB1, 0x6F, 0xE9, 0xEA,
0x70, 0x45, 0xE3, 0x86, 0x6E, 0x3C, 0x15, 0x1E, 0x2C, 0xBF, 0xBA, 0x9E,
0xFA, 0x06, 0x3D, 0x4E, 0x1C, 0xE7, 0x1F, 0x77, 0xB3, 0x2A, 0x3E, 0x5A,
0x0A, 0x5E, 0x0E, 0x86, 0x25, 0xC8, 0x66, 0x52, 0xD6, 0x89, 0x3E, 0x80,
0x0F, 0x1D, 0xE7, 0x99, 0xB9, 0xDC, 0x65, 0x29, 0x78, 0xEA, 0xE2, 0x94,
0xBA, 0x0E, 0x15, 0xC6, 0x6A, 0xB3, 0x10, 0x9C, 0x78, 0xC9, 0x4C, 0x2E,
0x3D, 0x2B, 0x1D, 0x36, 0xA7, 0x4E, 0xF7, 0xF2, 0xF4, 0x2D, 0x0A, 0x1E,
0x53, 0x3C, 0xFC, 0xA6, 0xB6, 0x12, 0x13, 0xF7, 0x08, 0xA7, 0x23, 0x52,
0x60, 0x79, 0xC2, 0x19, 0x0F, 0x26, 0x39, 0x19, 0x83, 0xC8, 0x7B, 0xA6,
0x95, 0x45, 0xBC, 0xE3, 0x66, 0x1F, 0xC3, 0xEA, 0x6E, 0xFE, 0xAD, 0xEB,
0xA5, 0x5A, 0x6C, 0xBE, 0xEF, 0xDD, 0x32, 0xC3, 0x28, 0xFF, 0x8C, 0x01,
0xD1, 0x37, 0x7F, 0xB1, 0x3B, 0x95, 0x2F, 0xDB, 0x0F, 0xA5, 0xCE, 0xEE,
0x02, 0x97, 0xAB, 0x68, 0x85, 0x21, 0x58, 0x65, 0x70, 0x61, 0x07, 0x29,
0x28, 0xB6, 0x21, 0x15, 0x84, 0x2F, 0x6E, 0x5B, 0xAD, 0x7D, 0xEF, 0x2A,
0x96, 0xBD, 0x61, 0xEB, 0x30, 0xA8, 0xCC, 0x13, 0x10, 0x15, 0x9F, 0x61,
0x75, 0x47, 0xDD, 0xEC, 0x39, 0xA2, 0x70, 0x4C, 0x90, 0x5C, 0x73, 0xB5,
0xCF, 0x63, 0x03, 0xAA, 0x1E, 0xFE, 0x34, 0x03, 0xA7, 0x2C, 0x62, 0x60,
0xBC, 0x86, 0xCC, 0xEE, 0x14, 0xDE, 0xAA, 0xCB, 0x0B, 0x9E, 0x9E, 0xD5,
0xCA, 0xF0, 0xBD, 0x19, 0xAF, 0x1E, 0x8B, 0x64, 0x6E, 0x84, 0xF3, 0xB2,
0xAB, 0x5C, 0xAB, 0x9C, 0xB3, 0xB4, 0x2A, 0x3C, 0x32, 0x5A, 0x68, 0x40,
0x50, 0xBB, 0x5A, 0x65, 0xB9, 0x69, 0x23, 0xA0, 0x99, 0xA0, 0x5F, 0x87,
0x19, 0x0B, 0x54, 0x9B, 0xF7, 0xB8, 0x21, 0xC0, 0xD5, 0xE9, 0x9E, 0x31,
0x77, 0x2D, 0xE3, 0x97, 0x9A, 0x88, 0x37, 0xF8, 0xA8, 0x7D, 0x3D, 0x62,
0x7E, 0x99, 0xF7, 0x95, 0xD6, 0x1F, 0xE6, 0xC7, 0x29, 0x88, 0x35, 0x0E,
0x81, 0x12, 0x68, 0x16, 0x5F, 0x93, 0xED, 0x11, 0x63, 0x72, 0x22, 0x1B,
0xA5, 0x84, 0xF5, 0x57, 0x99, 0xBA, 0x58, 0x78, 0xA1, 0xDF, 0xDE, 0x96,
0x54, 0x30, 0x2E, 0x53, 0xEB, 0x0A, 0xB3, 0xCD, 0x96, 0x46, 0xC2, 0x1A,
0xFF, 0xC3, 0x83, 0x9B, 0xEA, 0xFF, 0xC6, 0x34, 0xEF, 0xF2, 0xEB, 0x58,
0x28, 0x31, 0xBC, 0x6D, 0xE4, 0x48, 0xD9, 0x8F, 0xE3, 0xB7, 0x64, 0xE8,
0xD9, 0x14, 0x4A, 0x5D, 0x73, 0x3C, 0x7C, 0xEE, 0x61, 0xED, 0x28, 0xFE,
0xEA, 0xAB, 0xAA, 0xA3, 0xB6, 0xE2, 0xEE, 0x45, 0xE0, 0x13, 0x3E, 0x20,
0x14, 0x5D, 0x10, 0x42, 0xB5, 0xBB, 0x6A, 0xEF, 0x42, 0xF4, 0x42, 0xC7,
0xD0, 0x4F, 0xCB, 0xFA, 0x15, 0x4F, 0x6C, 0xDB, 0xC7, 0x4D, 0x85, 0x86,
0x9E, 0x79, 0x1E, 0xD8, 0x05, 0x21, 0xCD, 0x41, 0x1D, 0x3B, 0x4F, 0x65,
0x46, 0x26, 0x8D, 0x5B, 0xF2, 0xA1, 0x62, 0xCF, 0x50, 0x62, 0x81, 0x3D,
0x6A, 0x47, 0x4B, 0xE4, 0x92, 0x74, 0xCB, 0x69, 0xC3, 0x24, 0x15, 0x7F,
0xA3, 0xB6, 0xC7, 0xC1, 0xA0, 0x83, 0x88, 0xFC, 0x9D, 0x48, 0x19, 0xAD,
0x00, 0xBF, 0x5B, 0x09, 0x85, 0xB2, 0x92, 0x56, 0x0B, 0x8A, 0x84, 0x47,
0xEA, 0xF5, 0x55, 0x0C, 0x2A, 0x8D, 0x42, 0x58, 0x00, 0x0D, 0x82, 0x23,
0x74, 0xB1, 0x62, 0x14, 0x41, 0x7E, 0x93, 0x8D, 0x92, 0xF0, 0x72, 0x33,
0x61, 0x70, 0x3F, 0x23, 0x3E, 0xF4, 0xAD, 0x1D, 0x60, 0x74, 0xEE, 0xCB,
0x59, 0x37, 0xDE, 0x7C, 0xDB, 0x3B, 0x22, 0x6C, 0xF1, 0xEC, 0x5F, 0xD6,
0x9E, 0x50, 0xF8, 0x19, 0x84, 0x80, 0x07, 0xA6, 0x6E, 0x32, 0x77, 0xCE,
0xA7, 0xF2, 0x85, 0x40, 0xC2, 0x06, 0x0C, 0xC5, 0xAA, 0xA7, 0x69, 0xA9,
0x35, 0x97, 0xD9, 0x61, 0x55, 0xD8, 0xEF, 0xE8, 0x84, 0x34, 0x45, 0xC3,
0x2E, 0x7A, 0x44, 0x9E, 0xDC, 0xCA, 0x0B, 0x80, 0xFC, 0xAB, 0x04, 0x5A,
0xCD, 0x88, 0x55, 0x10, 0xD3, 0xDB, 0x73, 0xDB, 0xC9, 0x9E, 0x1E, 0x0E,
0x05, 0x67, 0xD5, 0xFD, 0xD8, 0x38, 0x3E, 0x71, 0x65, 0x34, 0xC4, 0xC5,
0x40, 0x43, 0x67, 0xE3, 0x79, 0xDA, 0x5F, 0x67, 0x4A, 0x3D, 0xB0, 0x8F,
0xE7, 0x21, 0x3E, 0x15, 0x20, 0xFF, 0x6D, 0xF1, 0x9E, 0xF8, 0x28, 0x3D,
0xF7, 0x40, 0x81, 0x94, 0x68, 0x5A, 0x3D, 0xE9, 0xF7, 0xAD, 0x83, 0xDB,
0x2B, 0x9F, 0xE3, 0xE6, 0xF7, 0xD4, 0x02, 0x76, 0xF7, 0x20, 0x15, 0x41,
0x34, 0x29, 0x69, 0x94, 0x1C, 0x26, 0x4C, 0xF6, 0x6A, 0xF4, 0x20, 0x33,
0x71, 0x24, 0x08, 0xD4, 0x68, 0x00, 0xA1, 0xD4, 0x2E, 0x6B, 0xF4, 0xBC,
0x46, 0x45, 0x24, 0x97, 0x2E, 0xF6, 0x39, 0x1E, 0xAF, 0x61, 0x00, 0x50,
0xB7, 0xD4, 0xB7, 0x43,
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl

View File

@@ -0,0 +1,471 @@
// 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.
#include "absl/random/internal/randen_slow.h"
#include <cstddef>
#include <cstdint>
#include <cstring>
#include "absl/base/attributes.h"
#include "absl/base/internal/endian.h"
#include "absl/numeric/int128.h"
#include "absl/random/internal/platform.h"
#include "absl/random/internal/randen_traits.h"
#if ABSL_HAVE_ATTRIBUTE(always_inline) || \
(defined(__GNUC__) && !defined(__clang__))
#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE \
__attribute__((always_inline))
#elif defined(_MSC_VER)
// We can achieve something similar to attribute((always_inline)) with MSVC by
// using the __forceinline keyword, however this is not perfect. MSVC is
// much less aggressive about inlining, and even with the __forceinline keyword.
#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE __forceinline
#else
#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE
#endif
namespace {
// AES portions based on rijndael-alg-fst.c,
// https://fastcrypto.org/front/misc/rijndael-alg-fst.c, and modified for
// platform-endianness.
//
// Implementation of
// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
constexpr uint32_t te0[256] = {
0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6,
0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,
0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551,
0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637,
0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d,
0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,
0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a,
0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d,
0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5,
0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,
0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264,
0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531,
0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac,
0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,
0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199,
0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c,
0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7,
0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c,
};
constexpr uint32_t te1[256] = {
0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd,
0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,
0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, 0xcaca8f45, 0x82821f9d,
0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,
0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,
0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a,
0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, 0x3434685c, 0xa5a551f4,
0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f,
0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1,
0x05050a0f, 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b, 0x83831d9e,
0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb,
0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e,
0x2f2f5e71, 0x84841397, 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c,
0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,
0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a,
0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7,
0x33336655, 0x85851194, 0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81,
0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe,
0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030, 0xffffe51a,
0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f,
0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, 0xc4c49357, 0xa7a755f2,
0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695,
0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,
0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c,
0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, 0xe0e0db3b, 0x32326456,
0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4,
0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4,
0xe4e4d337, 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, 0x5656acfa,
0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018,
0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1,
0xb4b473c7, 0xc6c69751, 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21,
0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,
0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12,
0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958,
0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233,
0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22,
0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731,
0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,
0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a,
};
constexpr uint32_t te2[256] = {
0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b,
0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,
0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, 0xca8f45ca, 0x821f9d82,
0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,
0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,
0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26,
0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, 0x34685c34, 0xa551f4a5,
0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15,
0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196,
0x050a0f05, 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09, 0x831d9e83,
0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0,
0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3,
0x2f5e712f, 0x84139784, 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced,
0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,
0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf,
0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d,
0x33665533, 0x85119485, 0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f,
0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3,
0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010, 0xffe51aff,
0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec,
0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, 0xc49357c4, 0xa755f2a7,
0x7efc827e, 0x3d7a473d, 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573,
0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,
0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14,
0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, 0xe0db3be0, 0x32645632,
0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c,
0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495,
0xe4d337e4, 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, 0x56acfa56,
0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808,
0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, 0x1c38241c, 0xa657f1a6,
0xb473c7b4, 0xc69751c6, 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f,
0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,
0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e,
0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1,
0x1d3a271d, 0x9e27b99e, 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311,
0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e,
0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6,
0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,
0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16,
};
constexpr uint32_t te3[256] = {
0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b,
0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,
0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, 0x8f45caca, 0x1f9d8282,
0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,
0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,
0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626,
0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, 0x685c3434, 0x51f4a5a5,
0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515,
0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696,
0x0a0f0505, 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, 0x1d9e8383,
0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0,
0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3,
0x5e712f2f, 0x13978484, 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded,
0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,
0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf,
0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d,
0x66553333, 0x11948585, 0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f,
0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3,
0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010, 0xe51affff,
0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec,
0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, 0x9357c4c4, 0x55f2a7a7,
0xfc827e7e, 0x7a473d3d, 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373,
0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,
0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414,
0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, 0xdb3be0e0, 0x64563232,
0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c,
0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595,
0xd337e4e4, 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, 0xacfa5656,
0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808,
0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, 0x38241c1c, 0x57f1a6a6,
0x73c7b4b4, 0x9751c6c6, 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f,
0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,
0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e,
0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1,
0x3a271d1d, 0x27b99e9e, 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111,
0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e,
0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6,
0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,
0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616,
};
// Software implementation of the Vector128 class, using uint32_t
// as an underlying vector register.
struct alignas(16) Vector128 {
uint32_t s[4];
};
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128
Vector128Load(const void* from) {
Vector128 result;
std::memcpy(result.s, from, sizeof(Vector128));
return result;
}
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Vector128Store(
const Vector128& v, void* to) {
std::memcpy(to, v.s, sizeof(Vector128));
}
// One round of AES. "round_key" is a public constant for breaking the
// symmetry of AES (ensures previously equal columns differ afterwards).
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128
AesRound(const Vector128& state, const Vector128& round_key) {
Vector128 result;
#ifdef ABSL_IS_LITTLE_ENDIAN
result.s[0] = round_key.s[0] ^ //
te0[uint8_t(state.s[0])] ^ //
te1[uint8_t(state.s[1] >> 8)] ^ //
te2[uint8_t(state.s[2] >> 16)] ^ //
te3[uint8_t(state.s[3] >> 24)];
result.s[1] = round_key.s[1] ^ //
te0[uint8_t(state.s[1])] ^ //
te1[uint8_t(state.s[2] >> 8)] ^ //
te2[uint8_t(state.s[3] >> 16)] ^ //
te3[uint8_t(state.s[0] >> 24)];
result.s[2] = round_key.s[2] ^ //
te0[uint8_t(state.s[2])] ^ //
te1[uint8_t(state.s[3] >> 8)] ^ //
te2[uint8_t(state.s[0] >> 16)] ^ //
te3[uint8_t(state.s[1] >> 24)];
result.s[3] = round_key.s[3] ^ //
te0[uint8_t(state.s[3])] ^ //
te1[uint8_t(state.s[0] >> 8)] ^ //
te2[uint8_t(state.s[1] >> 16)] ^ //
te3[uint8_t(state.s[2] >> 24)];
#else
result.s[0] = round_key.s[0] ^ //
te0[uint8_t(state.s[0])] ^ //
te1[uint8_t(state.s[3] >> 8)] ^ //
te2[uint8_t(state.s[2] >> 16)] ^ //
te3[uint8_t(state.s[1] >> 24)];
result.s[1] = round_key.s[1] ^ //
te0[uint8_t(state.s[1])] ^ //
te1[uint8_t(state.s[0] >> 8)] ^ //
te2[uint8_t(state.s[3] >> 16)] ^ //
te3[uint8_t(state.s[2] >> 24)];
result.s[2] = round_key.s[2] ^ //
te0[uint8_t(state.s[2])] ^ //
te1[uint8_t(state.s[1] >> 8)] ^ //
te2[uint8_t(state.s[0] >> 16)] ^ //
te3[uint8_t(state.s[3] >> 24)];
result.s[3] = round_key.s[3] ^ //
te0[uint8_t(state.s[3])] ^ //
te1[uint8_t(state.s[2] >> 8)] ^ //
te2[uint8_t(state.s[1] >> 16)] ^ //
te3[uint8_t(state.s[0] >> 24)];
#endif
return result;
}
using ::absl::random_internal::RandenTraits;
// The improved Feistel block shuffle function for 16 blocks.
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void BlockShuffle(
absl::uint128* state) {
static_assert(RandenTraits::kFeistelBlocks == 16,
"Feistel block shuffle only works for 16 blocks.");
constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = {
7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};
// The fully unrolled loop without the memcpy improves the speed by about
// 30% over the equivalent:
#if 0
absl::uint128 source[RandenTraits::kFeistelBlocks];
std::memcpy(source, state, sizeof(source));
for (size_t i = 0; i < RandenTraits::kFeistelBlocks; i++) {
const absl::uint128 v0 = source[shuffle[i]];
state[i] = v0;
}
return;
#endif
const absl::uint128 v0 = state[shuffle[0]];
const absl::uint128 v1 = state[shuffle[1]];
const absl::uint128 v2 = state[shuffle[2]];
const absl::uint128 v3 = state[shuffle[3]];
const absl::uint128 v4 = state[shuffle[4]];
const absl::uint128 v5 = state[shuffle[5]];
const absl::uint128 v6 = state[shuffle[6]];
const absl::uint128 v7 = state[shuffle[7]];
const absl::uint128 w0 = state[shuffle[8]];
const absl::uint128 w1 = state[shuffle[9]];
const absl::uint128 w2 = state[shuffle[10]];
const absl::uint128 w3 = state[shuffle[11]];
const absl::uint128 w4 = state[shuffle[12]];
const absl::uint128 w5 = state[shuffle[13]];
const absl::uint128 w6 = state[shuffle[14]];
const absl::uint128 w7 = state[shuffle[15]];
state[0] = v0;
state[1] = v1;
state[2] = v2;
state[3] = v3;
state[4] = v4;
state[5] = v5;
state[6] = v6;
state[7] = v7;
state[8] = w0;
state[9] = w1;
state[10] = w2;
state[11] = w3;
state[12] = w4;
state[13] = w5;
state[14] = w6;
state[15] = w7;
}
// Feistel round function using two AES subrounds. Very similar to F()
// from Simpira v2, but with independent subround keys. Uses 17 AES rounds
// per 16 bytes (vs. 10 for AES-CTR). Computing eight round functions in
// parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel
// XORs are 'free' (included in the second AES instruction).
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE const absl::uint128*
FeistelRound(absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT state,
const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
for (size_t branch = 0; branch < RandenTraits::kFeistelBlocks; branch += 4) {
const Vector128 s0 = Vector128Load(state + branch);
const Vector128 s1 = Vector128Load(state + branch + 1);
const Vector128 f0 = AesRound(s0, Vector128Load(keys));
keys++;
const Vector128 o1 = AesRound(f0, s1);
Vector128Store(o1, state + branch + 1);
// Manually unroll this loop once. about 10% better than not unrolled.
const Vector128 s2 = Vector128Load(state + branch + 2);
const Vector128 s3 = Vector128Load(state + branch + 3);
const Vector128 f2 = AesRound(s2, Vector128Load(keys));
keys++;
const Vector128 o3 = AesRound(f2, s3);
Vector128Store(o3, state + branch + 3);
}
return keys;
}
// Cryptographic permutation based via type-2 Generalized Feistel Network.
// Indistinguishable from ideal by chosen-ciphertext adversaries using less than
// 2^64 queries if the round function is a PRF. This is similar to the b=8 case
// of Simpira v2, but more efficient than its generic construction for b=16.
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Permute(
absl::uint128* state,
const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {
keys = FeistelRound(state, keys);
BlockShuffle(state);
}
}
// Enables native loads in the round loop by pre-swapping.
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void SwapEndian(
absl::uint128* state) {
#ifdef ABSL_IS_BIG_ENDIAN
for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {
uint64_t new_lo = absl::little_endian::ToHost64(
static_cast<uint64_t>(state[block] >> 64));
uint64_t new_hi = absl::little_endian::ToHost64(
static_cast<uint64_t>((state[block] << 64) >> 64));
state[block] = (static_cast<absl::uint128>(new_hi) << 64) | new_lo;
}
#else
// Avoid warning about unused variable.
(void)state;
#endif
}
} // namespace
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
const void* RandenSlow::GetKeys() {
// Round keys for one AES per Feistel round and branch.
// The canonical implementation uses first digits of Pi.
#ifdef ABSL_IS_LITTLE_ENDIAN
return kRandenRoundKeys;
#else
return kRandenRoundKeysBE;
#endif
}
void RandenSlow::Absorb(const void* seed_void, void* state_void) {
auto* state =
reinterpret_cast<uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(state_void);
const auto* seed =
reinterpret_cast<const uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(
seed_void);
constexpr size_t kCapacityBlocks =
RandenTraits::kCapacityBytes / sizeof(uint64_t);
static_assert(
kCapacityBlocks * sizeof(uint64_t) == RandenTraits::kCapacityBytes,
"Not i*V");
for (size_t i = kCapacityBlocks;
i < RandenTraits::kStateBytes / sizeof(uint64_t); ++i) {
state[i] ^= seed[i - kCapacityBlocks];
}
}
void RandenSlow::Generate(const void* keys_void, void* state_void) {
static_assert(RandenTraits::kCapacityBytes == sizeof(absl::uint128),
"Capacity mismatch");
auto* state = reinterpret_cast<absl::uint128*>(state_void);
const auto* keys = reinterpret_cast<const absl::uint128*>(keys_void);
const absl::uint128 prev_inner = state[0];
SwapEndian(state);
Permute(state, keys);
SwapEndian(state);
// Ensure backtracking resistance.
*state ^= prev_inner;
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl

View File

@@ -0,0 +1,40 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_
#include <cstddef>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RANDen = RANDom generator or beetroots in Swiss High German.
// RandenSlow implements the basic state manipulation methods for
// architectures lacking AES hardware acceleration intrinsics.
class RandenSlow {
public:
static void Generate(const void* keys, void* state_void);
static void Absorb(const void* seed_void, void* state_void);
static const void* GetKeys();
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_

View File

@@ -0,0 +1,88 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_
// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
// symbols from arbitrary system and other headers, since it may be built
// with different flags from other targets, using different levels of
// optimization, potentially introducing ODR violations.
#include <cstddef>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RANDen = RANDom generator or beetroots in Swiss High German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
// High-level summary:
// 1) Reverie (see "A Robust and Sponge-Like PRNG with Improved Efficiency") is
// a sponge-like random generator that requires a cryptographic permutation.
// It improves upon "Provably Robust Sponge-Based PRNGs and KDFs" by
// achieving backtracking resistance with only one Permute() per buffer.
//
// 2) "Simpira v2: A Family of Efficient Permutations Using the AES Round
// Function" constructs up to 1024-bit permutations using an improved
// Generalized Feistel network with 2-round AES-128 functions. This Feistel
// block shuffle achieves diffusion faster and is less vulnerable to
// sliced-biclique attacks than the Type-2 cyclic shuffle.
//
// 3) "Improving the Generalized Feistel" and "New criterion for diffusion
// property" extends the same kind of improved Feistel block shuffle to 16
// branches, which enables a 2048-bit permutation.
//
// Combine these three ideas and also change Simpira's subround keys from
// structured/low-entropy counters to digits of Pi (or other random source).
// RandenTraits contains the basic algorithm traits, such as the size of the
// state, seed, sponge, etc.
struct RandenTraits {
// Size of the entire sponge / state for the randen PRNG.
static constexpr size_t kStateBytes = 256; // 2048-bit
// Size of the 'inner' (inaccessible) part of the sponge. Larger values would
// require more frequent calls to RandenGenerate.
static constexpr size_t kCapacityBytes = 16; // 128-bit
// Size of the default seed consumed by the sponge.
static constexpr size_t kSeedBytes = kStateBytes - kCapacityBytes;
// Assuming 128-bit blocks, the number of blocks in the state.
// Largest size for which security proofs are known.
static constexpr size_t kFeistelBlocks = 16;
// Ensures SPRP security and two full subblock diffusions.
// Must be > 4 * log2(kFeistelBlocks).
static constexpr size_t kFeistelRounds = 16 + 1;
// Size of the key. A 128-bit key block is used for every-other
// feistel block (Type-2 generalized Feistel network) in each round.
static constexpr size_t kKeyBytes = 16 * kFeistelRounds * kFeistelBlocks / 2;
};
// Randen key arrays. In randen_round_keys.cc
extern const unsigned char kRandenRoundKeys[RandenTraits::kKeyBytes];
extern const unsigned char kRandenRoundKeysBE[RandenTraits::kKeyBytes];
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_

View File

@@ -0,0 +1,165 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_
#define ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_
#include <cstdint>
#include <cstdlib>
#include <initializer_list>
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>
#include <vector>
#include "absl/container/inlined_vector.h"
#include "absl/meta/type_traits.h"
#include "absl/random/internal/seed_material.h"
#include "absl/types/optional.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// This class conforms to the C++ Standard "Seed Sequence" concept
// [rand.req.seedseq].
//
// A `SaltedSeedSeq` is meant to wrap an existing seed sequence and modify
// generated sequence by mixing with extra entropy. This entropy may be
// build-dependent or process-dependent. The implementation may change to be
// have either or both kinds of entropy. If salt is not available sequence is
// not modified.
template <typename SSeq>
class SaltedSeedSeq {
public:
using inner_sequence_type = SSeq;
using result_type = typename SSeq::result_type;
SaltedSeedSeq() : seq_(absl::make_unique<SSeq>()) {}
template <typename Iterator>
SaltedSeedSeq(Iterator begin, Iterator end)
: seq_(absl::make_unique<SSeq>(begin, end)) {}
template <typename T>
SaltedSeedSeq(std::initializer_list<T> il)
: SaltedSeedSeq(il.begin(), il.end()) {}
SaltedSeedSeq(const SaltedSeedSeq&) = delete;
SaltedSeedSeq& operator=(const SaltedSeedSeq&) = delete;
SaltedSeedSeq(SaltedSeedSeq&&) = default;
SaltedSeedSeq& operator=(SaltedSeedSeq&&) = default;
template <typename RandomAccessIterator>
void generate(RandomAccessIterator begin, RandomAccessIterator end) {
using U = typename std::iterator_traits<RandomAccessIterator>::value_type;
// The common case is that generate is called with ContiguousIterators
// to uint arrays. Such contiguous memory regions may be optimized,
// which we detect here.
using TagType = absl::conditional_t<
(std::is_same<U, uint32_t>::value &&
(std::is_pointer<RandomAccessIterator>::value ||
std::is_same<RandomAccessIterator,
typename std::vector<U>::iterator>::value)),
ContiguousAndUint32Tag, DefaultTag>;
if (begin != end) {
generate_impl(TagType{}, begin, end, std::distance(begin, end));
}
}
template <typename OutIterator>
void param(OutIterator out) const {
seq_->param(out);
}
size_t size() const { return seq_->size(); }
private:
struct ContiguousAndUint32Tag {};
struct DefaultTag {};
// Generate which requires the iterators are contiguous pointers to uint32_t.
// Fills the initial seed buffer the underlying SSeq::generate() call,
// then mixes in the salt material.
template <typename Contiguous>
void generate_impl(ContiguousAndUint32Tag, Contiguous begin, Contiguous end,
size_t n) {
seq_->generate(begin, end);
const uint32_t salt = absl::random_internal::GetSaltMaterial().value_or(0);
auto span = absl::Span<uint32_t>(&*begin, n);
MixIntoSeedMaterial(absl::MakeConstSpan(&salt, 1), span);
}
// The uncommon case for generate is that it is called with iterators over
// some other buffer type which is assignable from a 32-bit value. In this
// case we allocate a temporary 32-bit buffer and then copy-assign back
// to the initial inputs.
template <typename RandomAccessIterator>
void generate_impl(DefaultTag, RandomAccessIterator begin,
RandomAccessIterator, size_t n) {
// Allocates a seed buffer of `n` elements, generates the seed, then
// copies the result into the `out` iterator.
absl::InlinedVector<uint32_t, 8> data(n, 0);
generate_impl(ContiguousAndUint32Tag{}, data.begin(), data.end(), n);
std::copy(data.begin(), data.end(), begin);
}
// Because [rand.req.seedseq] is not required to be copy-constructible,
// copy-assignable nor movable, we wrap it with unique pointer to be able
// to move SaltedSeedSeq.
std::unique_ptr<SSeq> seq_;
};
// is_salted_seed_seq indicates whether the type is a SaltedSeedSeq.
template <typename T, typename = void>
struct is_salted_seed_seq : public std::false_type {};
template <typename T>
struct is_salted_seed_seq<
T, typename std::enable_if<std::is_same<
T, SaltedSeedSeq<typename T::inner_sequence_type>>::value>::type>
: public std::true_type {};
// MakeSaltedSeedSeq returns a salted variant of the seed sequence.
// When provided with an existing SaltedSeedSeq, returns the input parameter,
// otherwise constructs a new SaltedSeedSeq which embodies the original
// non-salted seed parameters.
template <
typename SSeq, //
typename EnableIf = absl::enable_if_t<is_salted_seed_seq<SSeq>::value>>
SSeq MakeSaltedSeedSeq(SSeq&& seq) {
return SSeq(std::forward<SSeq>(seq));
}
template <
typename SSeq, //
typename EnableIf = absl::enable_if_t<!is_salted_seed_seq<SSeq>::value>>
SaltedSeedSeq<typename std::decay<SSeq>::type> MakeSaltedSeedSeq(SSeq&& seq) {
using sseq_type = typename std::decay<SSeq>::type;
using result_type = typename sseq_type::result_type;
absl::InlinedVector<result_type, 8> data;
seq.param(std::back_inserter(data));
return SaltedSeedSeq<sseq_type>(data.begin(), data.end());
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_

View File

@@ -0,0 +1,267 @@
// 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.
#include "absl/random/internal/seed_material.h"
#include <fcntl.h>
#ifndef _WIN32
#include <unistd.h>
#else
#include <io.h>
#endif
#include <algorithm>
#include <cerrno>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include "absl/base/dynamic_annotations.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#if defined(__native_client__)
#include <nacl/nacl_random.h>
#define ABSL_RANDOM_USE_NACL_SECURE_RANDOM 1
#elif defined(_WIN32)
#include <windows.h>
#define ABSL_RANDOM_USE_BCRYPT 1
#pragma comment(lib, "bcrypt.lib")
#elif defined(__Fuchsia__)
#include <zircon/syscalls.h>
#endif
#if defined(__GLIBC__) && \
(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
// glibc >= 2.25 has getentropy()
#define ABSL_RANDOM_USE_GET_ENTROPY 1
#endif
#if defined(__EMSCRIPTEN__)
#include <sys/random.h>
// Emscripten has getentropy, but it resides in a different header.
#define ABSL_RANDOM_USE_GET_ENTROPY 1
#endif
#if defined(ABSL_RANDOM_USE_BCRYPT)
#include <bcrypt.h>
#ifndef BCRYPT_SUCCESS
#define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
// Also link bcrypt; this can be done via linker options or:
// #pragma comment(lib, "bcrypt.lib")
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
namespace {
// Read OS Entropy for random number seeds.
// TODO(absl-team): Possibly place a cap on how much entropy may be read at a
// time.
#if defined(ABSL_RANDOM_USE_BCRYPT)
// On Windows potentially use the BCRYPT CNG API to read available entropy.
bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
BCRYPT_ALG_HANDLE hProvider;
NTSTATUS ret;
ret = BCryptOpenAlgorithmProvider(&hProvider, BCRYPT_RNG_ALGORITHM,
MS_PRIMITIVE_PROVIDER, 0);
if (!(BCRYPT_SUCCESS(ret))) {
ABSL_RAW_LOG(ERROR, "Failed to open crypto provider.");
return false;
}
ret = BCryptGenRandom(
hProvider, // provider
reinterpret_cast<UCHAR*>(values.data()), // buffer
static_cast<ULONG>(sizeof(uint32_t) * values.size()), // bytes
0); // flags
BCryptCloseAlgorithmProvider(hProvider, 0);
return BCRYPT_SUCCESS(ret);
}
#elif defined(ABSL_RANDOM_USE_NACL_SECURE_RANDOM)
// On NaCL use nacl_secure_random to acquire bytes.
bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
auto buffer = reinterpret_cast<uint8_t*>(values.data());
size_t buffer_size = sizeof(uint32_t) * values.size();
uint8_t* output_ptr = buffer;
while (buffer_size > 0) {
size_t nread = 0;
const int error = nacl_secure_random(output_ptr, buffer_size, &nread);
if (error != 0 || nread > buffer_size) {
ABSL_RAW_LOG(ERROR, "Failed to read secure_random seed data: %d", error);
return false;
}
output_ptr += nread;
buffer_size -= nread;
}
return true;
}
#elif defined(__Fuchsia__)
bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
auto buffer = reinterpret_cast<uint8_t*>(values.data());
size_t buffer_size = sizeof(uint32_t) * values.size();
zx_cprng_draw(buffer, buffer_size);
return true;
}
#else
#if defined(ABSL_RANDOM_USE_GET_ENTROPY)
// On *nix, use getentropy() if supported. Note that libc may support
// getentropy(), but the kernel may not, in which case this function will return
// false.
bool ReadSeedMaterialFromGetEntropy(absl::Span<uint32_t> values) {
auto buffer = reinterpret_cast<uint8_t*>(values.data());
size_t buffer_size = sizeof(uint32_t) * values.size();
while (buffer_size > 0) {
// getentropy() has a maximum permitted length of 256.
size_t to_read = std::min<size_t>(buffer_size, 256);
int result = getentropy(buffer, to_read);
if (result < 0) {
return false;
}
// https://github.com/google/sanitizers/issues/1173
// MemorySanitizer can't see through getentropy().
ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(buffer, to_read);
buffer += to_read;
buffer_size -= to_read;
}
return true;
}
#endif // defined(ABSL_RANDOM_GETENTROPY)
// On *nix, read entropy from /dev/urandom.
bool ReadSeedMaterialFromDevURandom(absl::Span<uint32_t> values) {
const char kEntropyFile[] = "/dev/urandom";
auto buffer = reinterpret_cast<uint8_t*>(values.data());
size_t buffer_size = sizeof(uint32_t) * values.size();
int dev_urandom = open(kEntropyFile, O_RDONLY);
bool success = (-1 != dev_urandom);
if (!success) {
return false;
}
while (success && buffer_size > 0) {
ssize_t bytes_read = read(dev_urandom, buffer, buffer_size);
int read_error = errno;
success = (bytes_read > 0);
if (success) {
buffer += bytes_read;
buffer_size -= static_cast<size_t>(bytes_read);
} else if (bytes_read == -1 && read_error == EINTR) {
success = true; // Need to try again.
}
}
close(dev_urandom);
return success;
}
bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
#if defined(ABSL_RANDOM_USE_GET_ENTROPY)
if (ReadSeedMaterialFromGetEntropy(values)) {
return true;
}
#endif
// Libc may support getentropy, but the kernel may not, so we still have
// to fallback to ReadSeedMaterialFromDevURandom().
return ReadSeedMaterialFromDevURandom(values);
}
#endif
} // namespace
bool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values) {
assert(values.data() != nullptr);
if (values.data() == nullptr) {
return false;
}
if (values.empty()) {
return true;
}
return ReadSeedMaterialFromOSEntropyImpl(values);
}
void MixIntoSeedMaterial(absl::Span<const uint32_t> sequence,
absl::Span<uint32_t> seed_material) {
// Algorithm is based on code available at
// https://gist.github.com/imneme/540829265469e673d045
constexpr uint32_t kInitVal = 0x43b0d7e5;
constexpr uint32_t kHashMul = 0x931e8875;
constexpr uint32_t kMixMulL = 0xca01f9dd;
constexpr uint32_t kMixMulR = 0x4973f715;
constexpr uint32_t kShiftSize = sizeof(uint32_t) * 8 / 2;
uint32_t hash_const = kInitVal;
auto hash = [&](uint32_t value) {
value ^= hash_const;
hash_const *= kHashMul;
value *= hash_const;
value ^= value >> kShiftSize;
return value;
};
auto mix = [&](uint32_t x, uint32_t y) {
uint32_t result = kMixMulL * x - kMixMulR * y;
result ^= result >> kShiftSize;
return result;
};
for (const auto& seq_val : sequence) {
for (auto& elem : seed_material) {
elem = mix(elem, hash(seq_val));
}
}
}
absl::optional<uint32_t> GetSaltMaterial() {
// Salt must be common for all generators within the same process so read it
// only once and store in static variable.
static const auto salt_material = []() -> absl::optional<uint32_t> {
uint32_t salt_value = 0;
if (random_internal::ReadSeedMaterialFromOSEntropy(
MakeSpan(&salt_value, 1))) {
return salt_value;
}
return absl::nullopt;
}();
return salt_material;
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl

View File

@@ -0,0 +1,104 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_
#define ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/types/optional.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Returns the number of 32-bit blocks needed to contain the given number of
// bits.
constexpr size_t SeedBitsToBlocks(size_t seed_size) {
return (seed_size + 31) / 32;
}
// Amount of entropy (measured in bits) used to instantiate a Seed Sequence,
// with which to create a URBG.
constexpr size_t kEntropyBitsNeeded = 256;
// Amount of entropy (measured in 32-bit blocks) used to instantiate a Seed
// Sequence, with which to create a URBG.
constexpr size_t kEntropyBlocksNeeded =
random_internal::SeedBitsToBlocks(kEntropyBitsNeeded);
static_assert(kEntropyBlocksNeeded > 0,
"Entropy used to seed URBGs must be nonzero.");
// Attempts to fill a span of uint32_t-values using an OS-provided source of
// true entropy (eg. /dev/urandom) into an array of uint32_t blocks of data. The
// resulting array may be used to initialize an instance of a class conforming
// to the C++ Standard "Seed Sequence" concept [rand.req.seedseq].
//
// If values.data() == nullptr, the behavior is undefined.
ABSL_MUST_USE_RESULT
bool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values);
// Attempts to fill a span of uint32_t-values using variates generated by an
// existing instance of a class conforming to the C++ Standard "Uniform Random
// Bit Generator" concept [rand.req.urng]. The resulting data may be used to
// initialize an instance of a class conforming to the C++ Standard
// "Seed Sequence" concept [rand.req.seedseq].
//
// If urbg == nullptr or values.data() == nullptr, the behavior is undefined.
template <typename URBG>
ABSL_MUST_USE_RESULT bool ReadSeedMaterialFromURBG(
URBG* urbg, absl::Span<uint32_t> values) {
random_internal::FastUniformBits<uint32_t> distr;
assert(urbg != nullptr && values.data() != nullptr);
if (urbg == nullptr || values.data() == nullptr) {
return false;
}
for (uint32_t& seed_value : values) {
seed_value = distr(*urbg);
}
return true;
}
// Mixes given sequence of values with into given sequence of seed material.
// Time complexity of this function is O(sequence.size() *
// seed_material.size()).
//
// Algorithm is based on code available at
// https://gist.github.com/imneme/540829265469e673d045
// by Melissa O'Neill.
void MixIntoSeedMaterial(absl::Span<const uint32_t> sequence,
absl::Span<uint32_t> seed_material);
// Returns salt value.
//
// Salt is obtained only once and stored in static variable.
//
// May return empty value if optaining the salt was not possible.
absl::optional<uint32_t> GetSaltMaterial();
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_

149
Pods/abseil/absl/random/internal/traits.h generated Normal file
View File

@@ -0,0 +1,149 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_TRAITS_H_
#define ABSL_RANDOM_INTERNAL_TRAITS_H_
#include <cstdint>
#include <limits>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// random_internal::is_widening_convertible<A, B>
//
// Returns whether a type A is widening-convertible to a type B.
//
// A is widening-convertible to B means:
// A a = <any number>;
// B b = a;
// A c = b;
// EXPECT_EQ(a, c);
template <typename A, typename B>
class is_widening_convertible {
// As long as there are enough bits in the exact part of a number:
// - unsigned can fit in float, signed, unsigned
// - signed can fit in float, signed
// - float can fit in float
// So we define rank to be:
// - rank(float) -> 2
// - rank(signed) -> 1
// - rank(unsigned) -> 0
template <class T>
static constexpr int rank() {
return !std::numeric_limits<T>::is_integer +
std::numeric_limits<T>::is_signed;
}
public:
// If an arithmetic-type B can represent at least as many digits as a type A,
// and B belongs to a rank no lower than A, then A can be safely represented
// by B through a widening-conversion.
static constexpr bool value =
std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits &&
rank<A>() <= rank<B>();
};
template <typename T>
struct IsIntegral : std::is_integral<T> {};
template <>
struct IsIntegral<absl::int128> : std::true_type {};
template <>
struct IsIntegral<absl::uint128> : std::true_type {};
template <typename T>
struct MakeUnsigned : std::make_unsigned<T> {};
template <>
struct MakeUnsigned<absl::int128> {
using type = absl::uint128;
};
template <>
struct MakeUnsigned<absl::uint128> {
using type = absl::uint128;
};
template <typename T>
struct IsUnsigned : std::is_unsigned<T> {};
template <>
struct IsUnsigned<absl::int128> : std::false_type {};
template <>
struct IsUnsigned<absl::uint128> : std::true_type {};
// unsigned_bits<N>::type returns the unsigned int type with the indicated
// number of bits.
template <size_t N>
struct unsigned_bits;
template <>
struct unsigned_bits<8> {
using type = uint8_t;
};
template <>
struct unsigned_bits<16> {
using type = uint16_t;
};
template <>
struct unsigned_bits<32> {
using type = uint32_t;
};
template <>
struct unsigned_bits<64> {
using type = uint64_t;
};
template <>
struct unsigned_bits<128> {
using type = absl::uint128;
};
// 256-bit wrapper for wide multiplications.
struct U256 {
uint128 hi;
uint128 lo;
};
template <>
struct unsigned_bits<256> {
using type = U256;
};
template <typename IntType>
struct make_unsigned_bits {
using type = typename unsigned_bits<
std::numeric_limits<typename MakeUnsigned<IntType>::type>::digits>::type;
};
template <typename T>
int BitWidth(T v) {
// Workaround for bit_width not supporting int128.
// Don't hardcode `64` to make sure this code does not trigger compiler
// warnings in smaller types.
constexpr int half_bits = sizeof(T) * 8 / 2;
if (sizeof(T) == 16 && (v >> half_bits) != 0) {
return bit_width(static_cast<uint64_t>(v >> half_bits)) + half_bits;
} else {
return bit_width(static_cast<uint64_t>(v));
}
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_TRAITS_H_

View File

@@ -0,0 +1,244 @@
// Copyright 2019 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.
//
#ifndef ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_
#define ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_
#include <cmath>
#include <limits>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/meta/type_traits.h"
#include "absl/random/internal/traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
template <typename IntType>
class uniform_int_distribution;
template <typename RealType>
class uniform_real_distribution;
// Interval tag types which specify whether the interval is open or closed
// on either boundary.
namespace random_internal {
template <typename T>
struct TagTypeCompare {};
template <typename T>
constexpr bool operator==(TagTypeCompare<T>, TagTypeCompare<T>) {
// Tags are mono-states. They always compare equal.
return true;
}
template <typename T>
constexpr bool operator!=(TagTypeCompare<T>, TagTypeCompare<T>) {
return false;
}
} // namespace random_internal
struct IntervalClosedClosedTag
: public random_internal::TagTypeCompare<IntervalClosedClosedTag> {};
struct IntervalClosedOpenTag
: public random_internal::TagTypeCompare<IntervalClosedOpenTag> {};
struct IntervalOpenClosedTag
: public random_internal::TagTypeCompare<IntervalOpenClosedTag> {};
struct IntervalOpenOpenTag
: public random_internal::TagTypeCompare<IntervalOpenOpenTag> {};
namespace random_internal {
// In the absence of an explicitly provided return-type, the template
// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
// the data-types of the endpoint-arguments {A lo, B hi}.
//
// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
// return-type, if one type can be implicitly converted into the other, in a
// lossless way. The template "is_widening_convertible" implements the
// compile-time logic for deciding if such a conversion is possible.
//
// If no such conversion between {A, B} exists, then the overload for
// absl::Uniform() will be discarded, and the call will be ill-formed.
// Return-type for absl::Uniform() when the return-type is inferred.
template <typename A, typename B>
using 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>;
// The functions
// uniform_lower_bound(tag, a, b)
// and
// uniform_upper_bound(tag, a, b)
// are used as implementation-details for absl::Uniform().
//
// Conceptually,
// [a, b] == [uniform_lower_bound(IntervalClosedClosed, a, b),
// uniform_upper_bound(IntervalClosedClosed, a, b)]
// (a, b) == [uniform_lower_bound(IntervalOpenOpen, a, b),
// uniform_upper_bound(IntervalOpenOpen, a, b)]
// [a, b) == [uniform_lower_bound(IntervalClosedOpen, a, b),
// uniform_upper_bound(IntervalClosedOpen, a, b)]
// (a, b] == [uniform_lower_bound(IntervalOpenClosed, a, b),
// uniform_upper_bound(IntervalOpenClosed, a, b)]
//
template <typename IntType, typename Tag>
typename 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) {
return a < (std::numeric_limits<IntType>::max)() ? (a + 1) : a;
}
template <typename FloatType, typename Tag>
typename absl::enable_if_t<
absl::conjunction<
std::is_floating_point<FloatType>,
absl::disjunction<std::is_same<Tag, IntervalOpenClosedTag>,
std::is_same<Tag, IntervalOpenOpenTag>>>::value,
FloatType>
uniform_lower_bound(Tag, FloatType a, FloatType b) {
return std::nextafter(a, b);
}
template <typename NumType, typename Tag>
typename absl::enable_if_t<
absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
std::is_same<Tag, IntervalClosedOpenTag>>::value,
NumType>
uniform_lower_bound(Tag, NumType a, NumType) {
return a;
}
template <typename IntType, typename Tag>
typename 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) {
return b > (std::numeric_limits<IntType>::min)() ? (b - 1) : b;
}
template <typename FloatType, typename Tag>
typename absl::enable_if_t<
absl::conjunction<
std::is_floating_point<FloatType>,
absl::disjunction<std::is_same<Tag, IntervalClosedOpenTag>,
std::is_same<Tag, IntervalOpenOpenTag>>>::value,
FloatType>
uniform_upper_bound(Tag, FloatType, FloatType b) {
return b;
}
template <typename IntType, typename Tag>
typename absl::enable_if_t<
absl::conjunction<
IsIntegral<IntType>,
absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
std::is_same<Tag, IntervalOpenClosedTag>>>::value,
IntType>
uniform_upper_bound(Tag, IntType, IntType b) {
return b;
}
template <typename FloatType, typename Tag>
typename absl::enable_if_t<
absl::conjunction<
std::is_floating_point<FloatType>,
absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
std::is_same<Tag, IntervalOpenClosedTag>>>::value,
FloatType>
uniform_upper_bound(Tag, FloatType, FloatType b) {
return std::nextafter(b, (std::numeric_limits<FloatType>::max)());
}
// Returns whether the bounds are valid for the underlying distribution.
// Inputs must have already been resolved via uniform_*_bound calls.
//
// The c++ standard constraints in [rand.dist.uni.int] are listed as:
// requires: lo <= hi.
//
// In the uniform_int_distrubtion, {lo, hi} are closed, closed. Thus:
// [0, 0] is legal.
// [0, 0) is not legal, but [0, 1) is, which translates to [0, 0].
// (0, 1) is not legal, but (0, 2) is, which translates to [1, 1].
// (0, 0] is not legal, but (0, 1] is, which translates to [1, 1].
//
// The c++ standard constraints in [rand.dist.uni.real] are listed as:
// requires: lo <= hi.
// requires: (hi - lo) <= numeric_limits<T>::max()
//
// In the uniform_real_distribution, {lo, hi} are closed, open, Thus:
// [0, 0] is legal, which is [0, 0+epsilon).
// [0, 0) is legal.
// (0, 0) is not legal, but (0-epsilon, 0+epsilon) is.
// (0, 0] is not legal, but (0, 0+epsilon] is.
//
template <typename FloatType>
absl::enable_if_t<std::is_floating_point<FloatType>::value, bool>
is_uniform_range_valid(FloatType a, FloatType b) {
return a <= b && std::isfinite(b - a);
}
template <typename IntType>
absl::enable_if_t<IsIntegral<IntType>::value, bool>
is_uniform_range_valid(IntType a, IntType b) {
return a <= b;
}
// UniformDistribution selects either absl::uniform_int_distribution
// or absl::uniform_real_distribution depending on the NumType parameter.
template <typename NumType>
using UniformDistribution =
typename std::conditional<IsIntegral<NumType>::value,
absl::uniform_int_distribution<NumType>,
absl::uniform_real_distribution<NumType>>::type;
// UniformDistributionWrapper is used as the underlying distribution type
// by the absl::Uniform template function. It selects the proper Abseil
// uniform distribution and provides constructor overloads that match the
// expected parameter order as well as adjusting distribution bounds based
// on the tag.
template <typename NumType>
struct UniformDistributionWrapper : public UniformDistribution<NumType> {
template <typename TagType>
explicit UniformDistributionWrapper(TagType, NumType lo, NumType hi)
: UniformDistribution<NumType>(
uniform_lower_bound<NumType>(TagType{}, lo, hi),
uniform_upper_bound<NumType>(TagType{}, lo, hi)) {}
explicit UniformDistributionWrapper(NumType lo, NumType hi)
: UniformDistribution<NumType>(
uniform_lower_bound<NumType>(IntervalClosedOpenTag(), lo, hi),
uniform_upper_bound<NumType>(IntervalClosedOpenTag(), lo, hi)) {}
explicit UniformDistributionWrapper()
: UniformDistribution<NumType>(std::numeric_limits<NumType>::lowest(),
(std::numeric_limits<NumType>::max)()) {}
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_

View File

@@ -0,0 +1,96 @@
// 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.
#ifndef ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
#define ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
#include <cstdint>
#include <limits>
#include <type_traits>
#if (defined(_WIN32) || defined(_WIN64)) && defined(_M_IA64)
#include <intrin.h> // NOLINT(build/include_order)
#pragma intrinsic(_umul128)
#define ABSL_INTERNAL_USE_UMUL128 1
#endif
#include "absl/base/config.h"
#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
#include "absl/random/internal/traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// wide_multiply<T> multiplies two N-bit values to a 2N-bit result.
template <typename UIntType>
struct wide_multiply {
static constexpr size_t kN = std::numeric_limits<UIntType>::digits;
using input_type = UIntType;
using result_type = typename random_internal::unsigned_bits<kN * 2>::type;
static result_type multiply(input_type a, input_type b) {
return static_cast<result_type>(a) * b;
}
static input_type hi(result_type r) {
return static_cast<input_type>(r >> kN);
}
static input_type lo(result_type r) { return static_cast<input_type>(r); }
static_assert(std::is_unsigned<UIntType>::value,
"Class-template wide_multiply<> argument must be unsigned.");
};
// MultiplyU128ToU256 multiplies two 128-bit values to a 256-bit value.
inline U256 MultiplyU128ToU256(uint128 a, uint128 b) {
const uint128 a00 = static_cast<uint64_t>(a);
const uint128 a64 = a >> 64;
const uint128 b00 = static_cast<uint64_t>(b);
const uint128 b64 = b >> 64;
const uint128 c00 = a00 * b00;
const uint128 c64a = a00 * b64;
const uint128 c64b = a64 * b00;
const uint128 c128 = a64 * b64;
const uint64_t carry =
static_cast<uint64_t>(((c00 >> 64) + static_cast<uint64_t>(c64a) +
static_cast<uint64_t>(c64b)) >>
64);
return {c128 + (c64a >> 64) + (c64b >> 64) + carry,
c00 + (c64a << 64) + (c64b << 64)};
}
template <>
struct wide_multiply<uint128> {
using input_type = uint128;
using result_type = U256;
static result_type multiply(input_type a, input_type b) {
return MultiplyU128ToU256(a, b);
}
static input_type hi(result_type r) { return r.hi; }
static input_type lo(result_type r) { return r.lo; }
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_

View File

@@ -0,0 +1,256 @@
// 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.
#ifndef ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_
#define ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_
#include <algorithm>
#include <cassert>
#include <cmath>
#include <istream>
#include <limits>
#include <ostream>
#include <type_traits>
#include "absl/numeric/bits.h"
#include "absl/random/internal/fastmath.h"
#include "absl/random/internal/generate_real.h"
#include "absl/random/internal/iostream_state_saver.h"
#include "absl/random/internal/traits.h"
#include "absl/random/uniform_int_distribution.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// log_uniform_int_distribution:
//
// Returns a random variate R in range [min, max] such that
// floor(log(R-min, base)) is uniformly distributed.
// We ensure uniformity by discretization using the
// boundary sets [0, 1, base, base * base, ... min(base*n, max)]
//
template <typename IntType = int>
class log_uniform_int_distribution {
private:
using unsigned_type =
typename random_internal::make_unsigned_bits<IntType>::type;
public:
using result_type = IntType;
class param_type {
public:
using distribution_type = log_uniform_int_distribution;
explicit param_type(
result_type min = 0,
result_type max = (std::numeric_limits<result_type>::max)(),
result_type base = 2)
: min_(min),
max_(max),
base_(base),
range_(static_cast<unsigned_type>(max_) -
static_cast<unsigned_type>(min_)),
log_range_(0) {
assert(max_ >= min_);
assert(base_ > 1);
if (base_ == 2) {
// Determine where the first set bit is on range(), giving a log2(range)
// value which can be used to construct bounds.
log_range_ = (std::min)(random_internal::BitWidth(range()),
std::numeric_limits<unsigned_type>::digits);
} else {
// NOTE: Computing the logN(x) introduces error from 2 sources:
// 1. Conversion of int to double loses precision for values >=
// 2^53, which may cause some log() computations to operate on
// different values.
// 2. The error introduced by the division will cause the result
// to differ from the expected value.
//
// Thus a result which should equal K may equal K +/- epsilon,
// which can eliminate some values depending on where the bounds fall.
const double inv_log_base = 1.0 / std::log(static_cast<double>(base_));
const double log_range = std::log(static_cast<double>(range()) + 0.5);
log_range_ = static_cast<int>(std::ceil(inv_log_base * log_range));
}
}
result_type(min)() const { return min_; }
result_type(max)() const { return max_; }
result_type base() const { return base_; }
friend bool operator==(const param_type& a, const param_type& b) {
return a.min_ == b.min_ && a.max_ == b.max_ && a.base_ == b.base_;
}
friend bool operator!=(const param_type& a, const param_type& b) {
return !(a == b);
}
private:
friend class log_uniform_int_distribution;
int log_range() const { return log_range_; }
unsigned_type range() const { return range_; }
result_type min_;
result_type max_;
result_type base_;
unsigned_type range_; // max - min
int log_range_; // ceil(logN(range_))
static_assert(random_internal::IsIntegral<IntType>::value,
"Class-template absl::log_uniform_int_distribution<> must be "
"parameterized using an integral type.");
};
log_uniform_int_distribution() : log_uniform_int_distribution(0) {}
explicit log_uniform_int_distribution(
result_type min,
result_type max = (std::numeric_limits<result_type>::max)(),
result_type base = 2)
: param_(min, max, base) {}
explicit log_uniform_int_distribution(const param_type& p) : param_(p) {}
void reset() {}
// generating functions
template <typename URBG>
result_type operator()(URBG& g) { // NOLINT(runtime/references)
return (*this)(g, param_);
}
template <typename URBG>
result_type operator()(URBG& g, // NOLINT(runtime/references)
const param_type& p) {
return static_cast<result_type>((p.min)() + Generate(g, p));
}
result_type(min)() const { return (param_.min)(); }
result_type(max)() const { return (param_.max)(); }
result_type base() const { return param_.base(); }
param_type param() const { return param_; }
void param(const param_type& p) { param_ = p; }
friend bool operator==(const log_uniform_int_distribution& a,
const log_uniform_int_distribution& b) {
return a.param_ == b.param_;
}
friend bool operator!=(const log_uniform_int_distribution& a,
const log_uniform_int_distribution& b) {
return a.param_ != b.param_;
}
private:
// Returns a log-uniform variate in the range [0, p.range()]. The caller
// should add min() to shift the result to the correct range.
template <typename URNG>
unsigned_type Generate(URNG& g, // NOLINT(runtime/references)
const param_type& p);
param_type param_;
};
template <typename IntType>
template <typename URBG>
typename log_uniform_int_distribution<IntType>::unsigned_type
log_uniform_int_distribution<IntType>::Generate(
URBG& g, // NOLINT(runtime/references)
const param_type& p) {
// sample e over [0, log_range]. Map the results of e to this:
// 0 => 0
// 1 => [1, b-1]
// 2 => [b, (b^2)-1]
// n => [b^(n-1)..(b^n)-1]
const int e = absl::uniform_int_distribution<int>(0, p.log_range())(g);
if (e == 0) {
return 0;
}
const int d = e - 1;
unsigned_type base_e, top_e;
if (p.base() == 2) {
base_e = static_cast<unsigned_type>(1) << d;
top_e = (e >= std::numeric_limits<unsigned_type>::digits)
? (std::numeric_limits<unsigned_type>::max)()
: (static_cast<unsigned_type>(1) << e) - 1;
} else {
const double r = std::pow(static_cast<double>(p.base()), d);
const double s = (r * static_cast<double>(p.base())) - 1.0;
base_e =
(r > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))
? (std::numeric_limits<unsigned_type>::max)()
: static_cast<unsigned_type>(r);
top_e =
(s > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))
? (std::numeric_limits<unsigned_type>::max)()
: static_cast<unsigned_type>(s);
}
const unsigned_type lo = (base_e >= p.range()) ? p.range() : base_e;
const unsigned_type hi = (top_e >= p.range()) ? p.range() : top_e;
// choose uniformly over [lo, hi]
return absl::uniform_int_distribution<result_type>(
static_cast<result_type>(lo), static_cast<result_type>(hi))(g);
}
template <typename CharT, typename Traits, typename IntType>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const log_uniform_int_distribution<IntType>& x) {
using stream_type =
typename random_internal::stream_format_type<IntType>::type;
auto saver = random_internal::make_ostream_state_saver(os);
os << static_cast<stream_type>((x.min)()) << os.fill()
<< static_cast<stream_type>((x.max)()) << os.fill()
<< static_cast<stream_type>(x.base());
return os;
}
template <typename CharT, typename Traits, typename IntType>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
log_uniform_int_distribution<IntType>& x) { // NOLINT(runtime/references)
using param_type = typename log_uniform_int_distribution<IntType>::param_type;
using result_type =
typename log_uniform_int_distribution<IntType>::result_type;
using stream_type =
typename random_internal::stream_format_type<IntType>::type;
stream_type min;
stream_type max;
stream_type base;
auto saver = random_internal::make_istream_state_saver(is);
is >> min >> max >> base;
if (!is.fail()) {
x.param(param_type(static_cast<result_type>(min),
static_cast<result_type>(max),
static_cast<result_type>(base)));
}
return is;
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_

View File

@@ -0,0 +1,261 @@
// 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.
#ifndef ABSL_RANDOM_POISSON_DISTRIBUTION_H_
#define ABSL_RANDOM_POISSON_DISTRIBUTION_H_
#include <cassert>
#include <cmath>
#include <istream>
#include <limits>
#include <ostream>
#include <type_traits>
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/random/internal/fastmath.h"
#include "absl/random/internal/generate_real.h"
#include "absl/random/internal/iostream_state_saver.h"
#include "absl/random/internal/traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::poisson_distribution:
// Generates discrete variates conforming to a Poisson distribution.
// p(n) = (mean^n / n!) exp(-mean)
//
// Depending on the parameter, the distribution selects one of the following
// algorithms:
// * The standard algorithm, attributed to Knuth, extended using a split method
// for larger values
// * The "Ratio of Uniforms as a convenient method for sampling from classical
// discrete distributions", Stadlober, 1989.
// http://www.sciencedirect.com/science/article/pii/0377042790903495
//
// NOTE: param_type.mean() is a double, which permits values larger than
// poisson_distribution<IntType>::max(), however this should be avoided and
// the distribution results are limited to the max() value.
//
// The goals of this implementation are to provide good performance while still
// beig thread-safe: This limits the implementation to not using lgamma provided
// by <math.h>.
//
template <typename IntType = int>
class poisson_distribution {
public:
using result_type = IntType;
class param_type {
public:
using distribution_type = poisson_distribution;
explicit param_type(double mean = 1.0);
double mean() const { return mean_; }
friend bool operator==(const param_type& a, const param_type& b) {
return a.mean_ == b.mean_;
}
friend bool operator!=(const param_type& a, const param_type& b) {
return !(a == b);
}
private:
friend class poisson_distribution;
double mean_;
double emu_; // e ^ -mean_
double lmu_; // ln(mean_)
double s_;
double log_k_;
int split_;
static_assert(random_internal::IsIntegral<IntType>::value,
"Class-template absl::poisson_distribution<> must be "
"parameterized using an integral type.");
};
poisson_distribution() : poisson_distribution(1.0) {}
explicit poisson_distribution(double mean) : param_(mean) {}
explicit poisson_distribution(const param_type& p) : param_(p) {}
void reset() {}
// generating functions
template <typename URBG>
result_type operator()(URBG& g) { // NOLINT(runtime/references)
return (*this)(g, param_);
}
template <typename URBG>
result_type operator()(URBG& g, // NOLINT(runtime/references)
const param_type& p);
param_type param() const { return param_; }
void param(const param_type& p) { param_ = p; }
result_type(min)() const { return 0; }
result_type(max)() const { return (std::numeric_limits<result_type>::max)(); }
double mean() const { return param_.mean(); }
friend bool operator==(const poisson_distribution& a,
const poisson_distribution& b) {
return a.param_ == b.param_;
}
friend bool operator!=(const poisson_distribution& a,
const poisson_distribution& b) {
return a.param_ != b.param_;
}
private:
param_type param_;
random_internal::FastUniformBits<uint64_t> fast_u64_;
};
// -----------------------------------------------------------------------------
// Implementation details follow
// -----------------------------------------------------------------------------
template <typename IntType>
poisson_distribution<IntType>::param_type::param_type(double mean)
: mean_(mean), split_(0) {
assert(mean >= 0);
assert(mean <=
static_cast<double>((std::numeric_limits<result_type>::max)()));
// As a defensive measure, avoid large values of the mean. The rejection
// algorithm used does not support very large values well. It my be worth
// changing algorithms to better deal with these cases.
assert(mean <= 1e10);
if (mean_ < 10) {
// For small lambda, use the knuth method.
split_ = 1;
emu_ = std::exp(-mean_);
} else if (mean_ <= 50) {
// Use split-knuth method.
split_ = 1 + static_cast<int>(mean_ / 10.0);
emu_ = std::exp(-mean_ / static_cast<double>(split_));
} else {
// Use ratio of uniforms method.
constexpr double k2E = 0.7357588823428846;
constexpr double kSA = 0.4494580810294493;
lmu_ = std::log(mean_);
double a = mean_ + 0.5;
s_ = kSA + std::sqrt(k2E * a);
const double mode = std::ceil(mean_) - 1;
log_k_ = lmu_ * mode - absl::random_internal::StirlingLogFactorial(mode);
}
}
template <typename IntType>
template <typename URBG>
typename poisson_distribution<IntType>::result_type
poisson_distribution<IntType>::operator()(
URBG& g, // NOLINT(runtime/references)
const param_type& p) {
using random_internal::GeneratePositiveTag;
using random_internal::GenerateRealFromBits;
using random_internal::GenerateSignedTag;
if (p.split_ != 0) {
// Use Knuth's algorithm with range splitting to avoid floating-point
// errors. Knuth's algorithm is: Ui is a sequence of uniform variates on
// (0,1); return the number of variates required for product(Ui) <
// exp(-lambda).
//
// The expected number of variates required for Knuth's method can be
// computed as follows:
// The expected value of U is 0.5, so solving for 0.5^n < exp(-lambda) gives
// the expected number of uniform variates
// required for a given lambda, which is:
// lambda = [2, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17]
// n = [3, 8, 13, 15, 16, 18, 19, 21, 22, 24, 25]
//
result_type n = 0;
for (int split = p.split_; split > 0; --split) {
double r = 1.0;
do {
r *= GenerateRealFromBits<double, GeneratePositiveTag, true>(
fast_u64_(g)); // U(-1, 0)
++n;
} while (r > p.emu_);
--n;
}
return n;
}
// Use ratio of uniforms method.
//
// Let u ~ Uniform(0, 1), v ~ Uniform(-1, 1),
// a = lambda + 1/2,
// s = 1.5 - sqrt(3/e) + sqrt(2(lambda + 1/2)/e),
// x = s * v/u + a.
// P(floor(x) = k | u^2 < f(floor(x))/k), where
// f(m) = lambda^m exp(-lambda)/ m!, for 0 <= m, and f(m) = 0 otherwise,
// and k = max(f).
const double a = p.mean_ + 0.5;
for (;;) {
const double u = GenerateRealFromBits<double, GeneratePositiveTag, false>(
fast_u64_(g)); // U(0, 1)
const double v = GenerateRealFromBits<double, GenerateSignedTag, false>(
fast_u64_(g)); // U(-1, 1)
const double x = std::floor(p.s_ * v / u + a);
if (x < 0) continue; // f(negative) = 0
const double rhs = x * p.lmu_;
// clang-format off
double s = (x <= 1.0) ? 0.0
: (x == 2.0) ? 0.693147180559945
: absl::random_internal::StirlingLogFactorial(x);
// clang-format on
const double lhs = 2.0 * std::log(u) + p.log_k_ + s;
if (lhs < rhs) {
return x > static_cast<double>((max)())
? (max)()
: static_cast<result_type>(x); // f(x)/k >= u^2
}
}
}
template <typename CharT, typename Traits, typename IntType>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const poisson_distribution<IntType>& x) {
auto saver = random_internal::make_ostream_state_saver(os);
os.precision(random_internal::stream_precision_helper<double>::kPrecision);
os << x.mean();
return os;
}
template <typename CharT, typename Traits, typename IntType>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
poisson_distribution<IntType>& x) { // NOLINT(runtime/references)
using param_type = typename poisson_distribution<IntType>::param_type;
auto saver = random_internal::make_istream_state_saver(is);
double mean = random_internal::read_floating_point<double>(is);
if (!is.fail()) {
x.param(param_type(mean));
}
return is;
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_POISSON_DISTRIBUTION_H_

189
Pods/abseil/absl/random/random.h generated Normal file
View File

@@ -0,0 +1,189 @@
// 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: random.h
// -----------------------------------------------------------------------------
//
// This header defines the recommended Uniform Random Bit Generator (URBG)
// types for use within the Abseil Random library. These types are not
// suitable for security-related use-cases, but should suffice for most other
// uses of generating random values.
//
// The Abseil random library provides the following URBG types:
//
// * BitGen, a good general-purpose bit generator, optimized for generating
// random (but not cryptographically secure) values
// * InsecureBitGen, a slightly faster, though less random, bit generator, for
// cases where the existing BitGen is a drag on performance.
#ifndef ABSL_RANDOM_RANDOM_H_
#define ABSL_RANDOM_RANDOM_H_
#include <random>
#include "absl/random/distributions.h" // IWYU pragma: export
#include "absl/random/internal/nonsecure_base.h" // IWYU pragma: export
#include "absl/random/internal/pcg_engine.h" // IWYU pragma: export
#include "absl/random/internal/pool_urbg.h"
#include "absl/random/internal/randen_engine.h"
#include "absl/random/seed_sequences.h" // IWYU pragma: export
namespace absl {
ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// absl::BitGen
// -----------------------------------------------------------------------------
//
// `absl::BitGen` is a general-purpose random bit generator for generating
// random values for use within the Abseil random library. Typically, you use a
// bit generator in combination with a distribution to provide random values.
//
// Example:
//
// // Create an absl::BitGen. There is no need to seed this bit generator.
// absl::BitGen gen;
//
// // Generate an integer value in the closed interval [1,6]
// int die_roll = absl::uniform_int_distribution<int>(1, 6)(gen);
//
// `absl::BitGen` is seeded by default with non-deterministic data to produce
// different sequences of random values across different instances, including
// different binary invocations. This behavior is different than the standard
// library bit generators, which use golden values as their seeds. Default
// construction intentionally provides no stability guarantees, to avoid
// accidental dependence on such a property.
//
// `absl::BitGen` may be constructed with an optional seed sequence type,
// conforming to [rand.req.seed_seq], which will be mixed with additional
// non-deterministic data as detailed below.
//
// Example:
//
// // Create an absl::BitGen using an std::seed_seq seed sequence
// std::seed_seq seq{1,2,3};
// absl::BitGen gen_with_seed(seq);
//
// // Generate an integer value in the closed interval [1,6]
// int die_roll2 = absl::uniform_int_distribution<int>(1, 6)(gen_with_seed);
//
// Constructing two `absl::BitGen`s with the same seed sequence in the same
// process will produce the same sequence of variates, but need not do so across
// multiple processes even if they're executing the same binary.
//
// `absl::BitGen` meets the requirements of the Uniform Random Bit Generator
// (URBG) concept as per the C++17 standard [rand.req.urng] though differs
// slightly with [rand.req.eng]. Like its standard library equivalents (e.g.
// `std::mersenne_twister_engine`) `absl::BitGen` is not cryptographically
// secure.
//
// This type has been optimized to perform better than Mersenne Twister
// (https://en.wikipedia.org/wiki/Mersenne_Twister) and many other complex URBG
// types on modern x86, ARM, and PPC architectures.
//
// This type is thread-compatible, but not thread-safe.
// ---------------------------------------------------------------------------
// absl::BitGen member functions
// ---------------------------------------------------------------------------
// absl::BitGen::operator()()
//
// Calls the BitGen, returning a generated value.
// absl::BitGen::min()
//
// Returns the smallest possible value from this bit generator.
// absl::BitGen::max()
//
// Returns the largest possible value from this bit generator.
// absl::BitGen::discard(num)
//
// Advances the internal state of this bit generator by `num` times, and
// discards the intermediate results.
// ---------------------------------------------------------------------------
using BitGen = random_internal::NonsecureURBGBase<
random_internal::randen_engine<uint64_t>>;
// -----------------------------------------------------------------------------
// absl::InsecureBitGen
// -----------------------------------------------------------------------------
//
// `absl::InsecureBitGen` is an efficient random bit generator for generating
// random values, recommended only for performance-sensitive use cases where
// `absl::BitGen` is not satisfactory when compute-bounded by bit generation
// costs.
//
// Example:
//
// // Create an absl::InsecureBitGen
// absl::InsecureBitGen gen;
// for (size_t i = 0; i < 1000000; i++) {
//
// // Generate a bunch of random values from some complex distribution
// auto my_rnd = some_distribution(gen, 1, 1000);
// }
//
// Like `absl::BitGen`, `absl::InsecureBitGen` is seeded by default with
// non-deterministic data to produce different sequences of random values across
// different instances, including different binary invocations. (This behavior
// is different than the standard library bit generators, which use golden
// values as their seeds.)
//
// `absl::InsecureBitGen` may be constructed with an optional seed sequence
// type, conforming to [rand.req.seed_seq], which will be mixed with additional
// non-deterministic data, as detailed in the `absl::BitGen` comment.
//
// `absl::InsecureBitGen` meets the requirements of the Uniform Random Bit
// Generator (URBG) concept as per the C++17 standard [rand.req.urng] though
// its implementation differs slightly with [rand.req.eng]. Like its standard
// library equivalents (e.g. `std::mersenne_twister_engine`)
// `absl::InsecureBitGen` is not cryptographically secure.
//
// Prefer `absl::BitGen` over `absl::InsecureBitGen` as the general type is
// often fast enough for the vast majority of applications.
using InsecureBitGen =
random_internal::NonsecureURBGBase<random_internal::pcg64_2018_engine>;
// ---------------------------------------------------------------------------
// absl::InsecureBitGen member functions
// ---------------------------------------------------------------------------
// absl::InsecureBitGen::operator()()
//
// Calls the InsecureBitGen, returning a generated value.
// absl::InsecureBitGen::min()
//
// Returns the smallest possible value from this bit generator.
// absl::InsecureBitGen::max()
//
// Returns the largest possible value from this bit generator.
// absl::InsecureBitGen::discard(num)
//
// Advances the internal state of this bit generator by `num` times, and
// discards the intermediate results.
// ---------------------------------------------------------------------------
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_RANDOM_H_

View File

@@ -0,0 +1,46 @@
// 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.
#include "absl/random/seed_gen_exception.h"
#include <iostream>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
static constexpr const char kExceptionMessage[] =
"Failed generating seed-material for URBG.";
SeedGenException::~SeedGenException() = default;
const char* SeedGenException::what() const noexcept {
return kExceptionMessage;
}
namespace random_internal {
void ThrowSeedGenException() {
#ifdef ABSL_HAVE_EXCEPTIONS
throw absl::SeedGenException();
#else
std::cerr << kExceptionMessage << std::endl;
std::terminate();
#endif
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl

View File

@@ -0,0 +1,55 @@
// 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: seed_gen_exception.h
// -----------------------------------------------------------------------------
//
// This header defines an exception class which may be thrown if unpredictable
// events prevent the derivation of suitable seed-material for constructing a
// bit generator conforming to [rand.req.urng] (eg. entropy cannot be read from
// /dev/urandom on a Unix-based system).
//
// Note: if exceptions are disabled, `std::terminate()` is called instead.
#ifndef ABSL_RANDOM_SEED_GEN_EXCEPTION_H_
#define ABSL_RANDOM_SEED_GEN_EXCEPTION_H_
#include <exception>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
//------------------------------------------------------------------------------
// SeedGenException
//------------------------------------------------------------------------------
class SeedGenException : public std::exception {
public:
SeedGenException() = default;
~SeedGenException() override;
const char* what() const noexcept override;
};
namespace random_internal {
// throw delegator
[[noreturn]] void ThrowSeedGenException();
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_SEED_GEN_EXCEPTION_H_

View File

@@ -0,0 +1,29 @@
// 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.
#include "absl/random/seed_sequences.h"
#include "absl/random/internal/pool_urbg.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
SeedSeq MakeSeedSeq() {
SeedSeq::result_type seed_material[8];
random_internal::RandenPool<uint32_t>::Fill(absl::MakeSpan(seed_material));
return SeedSeq(std::begin(seed_material), std::end(seed_material));
}
ABSL_NAMESPACE_END
} // namespace absl

111
Pods/abseil/absl/random/seed_sequences.h generated Normal file
View File

@@ -0,0 +1,111 @@
// 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: seed_sequences.h
// -----------------------------------------------------------------------------
//
// This header contains utilities for creating and working with seed sequences
// conforming to [rand.req.seedseq]. In general, direct construction of seed
// sequences is discouraged, but use-cases for construction of identical bit
// generators (using the same seed sequence) may be helpful (e.g. replaying a
// simulation whose state is derived from variates of a bit generator).
#ifndef ABSL_RANDOM_SEED_SEQUENCES_H_
#define ABSL_RANDOM_SEED_SEQUENCES_H_
#include <iterator>
#include <random>
#include "absl/base/config.h"
#include "absl/random/internal/salted_seed_seq.h"
#include "absl/random/internal/seed_material.h"
#include "absl/random/seed_gen_exception.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// absl::SeedSeq
// -----------------------------------------------------------------------------
//
// `absl::SeedSeq` constructs a seed sequence according to [rand.req.seedseq]
// for use within bit generators. `absl::SeedSeq`, unlike `std::seed_seq`
// additionally salts the generated seeds with extra implementation-defined
// entropy. For that reason, you can use `absl::SeedSeq` in combination with
// standard library bit generators (e.g. `std::mt19937`) to introduce
// non-determinism in your seeds.
//
// Example:
//
// absl::SeedSeq my_seed_seq({a, b, c});
// std::mt19937 my_bitgen(my_seed_seq);
//
using SeedSeq = random_internal::SaltedSeedSeq<std::seed_seq>;
// -----------------------------------------------------------------------------
// absl::CreateSeedSeqFrom(bitgen*)
// -----------------------------------------------------------------------------
//
// Constructs a seed sequence conforming to [rand.req.seedseq] using variates
// produced by a provided bit generator.
//
// You should generally avoid direct construction of seed sequences, but
// use-cases for reuse of a seed sequence to construct identical bit generators
// may be helpful (eg. replaying a simulation whose state is derived from bit
// generator values).
//
// If bitgen == nullptr, then behavior is undefined.
//
// Example:
//
// absl::BitGen my_bitgen;
// auto seed_seq = absl::CreateSeedSeqFrom(&my_bitgen);
// absl::BitGen new_engine(seed_seq); // derived from my_bitgen, but not
// // correlated.
//
template <typename URBG>
SeedSeq CreateSeedSeqFrom(URBG* urbg) {
SeedSeq::result_type
seed_material[random_internal::kEntropyBlocksNeeded];
if (!random_internal::ReadSeedMaterialFromURBG(
urbg, absl::MakeSpan(seed_material))) {
random_internal::ThrowSeedGenException();
}
return SeedSeq(std::begin(seed_material), std::end(seed_material));
}
// -----------------------------------------------------------------------------
// absl::MakeSeedSeq()
// -----------------------------------------------------------------------------
//
// Constructs an `absl::SeedSeq` salting the generated values using
// implementation-defined entropy. The returned sequence can be used to create
// equivalent bit generators correlated using this sequence.
//
// Example:
//
// auto my_seed_seq = absl::MakeSeedSeq();
// std::mt19937 rng1(my_seed_seq);
// std::mt19937 rng2(my_seed_seq);
// EXPECT_EQ(rng1(), rng2());
//
SeedSeq MakeSeedSeq();
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_SEED_SEQUENCES_H_

View File

@@ -0,0 +1,275 @@
// 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: uniform_int_distribution.h
// -----------------------------------------------------------------------------
//
// This header defines a class for representing a uniform integer distribution
// over the closed (inclusive) interval [a,b]. You use this distribution in
// combination with an Abseil random bit generator to produce random values
// according to the rules of the distribution.
//
// `absl::uniform_int_distribution` is a drop-in replacement for the C++11
// `std::uniform_int_distribution` [rand.dist.uni.int] but is considerably
// faster than the libstdc++ implementation.
#ifndef ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_
#define ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_
#include <cassert>
#include <istream>
#include <limits>
#include <type_traits>
#include "absl/base/optimization.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/random/internal/iostream_state_saver.h"
#include "absl/random/internal/traits.h"
#include "absl/random/internal/wide_multiply.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::uniform_int_distribution<T>
//
// This distribution produces random integer values uniformly distributed in the
// closed (inclusive) interval [a, b].
//
// Example:
//
// absl::BitGen gen;
//
// // Use the distribution to produce a value between 1 and 6, inclusive.
// int die_roll = absl::uniform_int_distribution<int>(1, 6)(gen);
//
template <typename IntType = int>
class uniform_int_distribution {
private:
using unsigned_type =
typename random_internal::make_unsigned_bits<IntType>::type;
public:
using result_type = IntType;
class param_type {
public:
using distribution_type = uniform_int_distribution;
explicit param_type(
result_type lo = 0,
result_type hi = (std::numeric_limits<result_type>::max)())
: lo_(lo),
range_(static_cast<unsigned_type>(hi) -
static_cast<unsigned_type>(lo)) {
// [rand.dist.uni.int] precondition 2
assert(lo <= hi);
}
result_type a() const { return lo_; }
result_type b() const {
return static_cast<result_type>(static_cast<unsigned_type>(lo_) + range_);
}
friend bool operator==(const param_type& a, const param_type& b) {
return a.lo_ == b.lo_ && a.range_ == b.range_;
}
friend bool operator!=(const param_type& a, const param_type& b) {
return !(a == b);
}
private:
friend class uniform_int_distribution;
unsigned_type range() const { return range_; }
result_type lo_;
unsigned_type range_;
static_assert(random_internal::IsIntegral<result_type>::value,
"Class-template absl::uniform_int_distribution<> must be "
"parameterized using an integral type.");
}; // param_type
uniform_int_distribution() : uniform_int_distribution(0) {}
explicit uniform_int_distribution(
result_type lo,
result_type hi = (std::numeric_limits<result_type>::max)())
: param_(lo, hi) {}
explicit uniform_int_distribution(const param_type& param) : param_(param) {}
// uniform_int_distribution<T>::reset()
//
// Resets the uniform int distribution. Note that this function has no effect
// because the distribution already produces independent values.
void reset() {}
template <typename URBG>
result_type operator()(URBG& gen) { // NOLINT(runtime/references)
return (*this)(gen, param());
}
template <typename URBG>
result_type operator()(
URBG& gen, const param_type& param) { // NOLINT(runtime/references)
return static_cast<result_type>(param.a() + Generate(gen, param.range()));
}
result_type a() const { return param_.a(); }
result_type b() const { return param_.b(); }
param_type param() const { return param_; }
void param(const param_type& params) { param_ = params; }
result_type(min)() const { return a(); }
result_type(max)() const { return b(); }
friend bool operator==(const uniform_int_distribution& a,
const uniform_int_distribution& b) {
return a.param_ == b.param_;
}
friend bool operator!=(const uniform_int_distribution& a,
const uniform_int_distribution& b) {
return !(a == b);
}
private:
// Generates a value in the *closed* interval [0, R]
template <typename URBG>
unsigned_type Generate(URBG& g, // NOLINT(runtime/references)
unsigned_type R);
param_type param_;
};
// -----------------------------------------------------------------------------
// Implementation details follow
// -----------------------------------------------------------------------------
template <typename CharT, typename Traits, typename IntType>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os,
const uniform_int_distribution<IntType>& x) {
using stream_type =
typename random_internal::stream_format_type<IntType>::type;
auto saver = random_internal::make_ostream_state_saver(os);
os << static_cast<stream_type>(x.a()) << os.fill()
<< static_cast<stream_type>(x.b());
return os;
}
template <typename CharT, typename Traits, typename IntType>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is,
uniform_int_distribution<IntType>& x) {
using param_type = typename uniform_int_distribution<IntType>::param_type;
using result_type = typename uniform_int_distribution<IntType>::result_type;
using stream_type =
typename random_internal::stream_format_type<IntType>::type;
stream_type a;
stream_type b;
auto saver = random_internal::make_istream_state_saver(is);
is >> a >> b;
if (!is.fail()) {
x.param(
param_type(static_cast<result_type>(a), static_cast<result_type>(b)));
}
return is;
}
template <typename IntType>
template <typename URBG>
typename random_internal::make_unsigned_bits<IntType>::type
uniform_int_distribution<IntType>::Generate(
URBG& g, // NOLINT(runtime/references)
typename random_internal::make_unsigned_bits<IntType>::type R) {
random_internal::FastUniformBits<unsigned_type> fast_bits;
unsigned_type bits = fast_bits(g);
const unsigned_type Lim = R + 1;
if ((R & Lim) == 0) {
// If the interval's length is a power of two range, just take the low bits.
return bits & R;
}
// Generates a uniform variate on [0, Lim) using fixed-point multiplication.
// The above fast-path guarantees that Lim is representable in unsigned_type.
//
// Algorithm adapted from
// http://lemire.me/blog/2016/06/30/fast-random-shuffling/, with added
// explanation.
//
// The algorithm creates a uniform variate `bits` in the interval [0, 2^N),
// and treats it as the fractional part of a fixed-point real value in [0, 1),
// multiplied by 2^N. For example, 0.25 would be represented as 2^(N - 2),
// because 2^N * 0.25 == 2^(N - 2).
//
// Next, `bits` and `Lim` are multiplied with a wide-multiply to bring the
// value into the range [0, Lim). The integral part (the high word of the
// multiplication result) is then very nearly the desired result. However,
// this is not quite accurate; viewing the multiplication result as one
// double-width integer, the resulting values for the sample are mapped as
// follows:
//
// If the result lies in this interval: Return this value:
// [0, 2^N) 0
// [2^N, 2 * 2^N) 1
// ... ...
// [K * 2^N, (K + 1) * 2^N) K
// ... ...
// [(Lim - 1) * 2^N, Lim * 2^N) Lim - 1
//
// While all of these intervals have the same size, the result of `bits * Lim`
// must be a multiple of `Lim`, and not all of these intervals contain the
// same number of multiples of `Lim`. In particular, some contain
// `F = floor(2^N / Lim)` and some contain `F + 1 = ceil(2^N / Lim)`. This
// difference produces a small nonuniformity, which is corrected by applying
// rejection sampling to one of the values in the "larger intervals" (i.e.,
// the intervals containing `F + 1` multiples of `Lim`.
//
// An interval contains `F + 1` multiples of `Lim` if and only if its smallest
// value modulo 2^N is less than `2^N % Lim`. The unique value satisfying
// this property is used as the one for rejection. That is, a value of
// `bits * Lim` is rejected if `(bit * Lim) % 2^N < (2^N % Lim)`.
using helper = random_internal::wide_multiply<unsigned_type>;
auto product = helper::multiply(bits, Lim);
// Two optimizations here:
// * Rejection occurs with some probability less than 1/2, and for reasonable
// ranges considerably less (in particular, less than 1/(F+1)), so
// ABSL_PREDICT_FALSE is apt.
// * `Lim` is an overestimate of `threshold`, and doesn't require a divide.
if (ABSL_PREDICT_FALSE(helper::lo(product) < Lim)) {
// This quantity is exactly equal to `2^N % Lim`, but does not require high
// precision calculations: `2^N % Lim` is congruent to `(2^N - Lim) % Lim`.
// Ideally this could be expressed simply as `-X` rather than `2^N - X`, but
// for types smaller than int, this calculation is incorrect due to integer
// promotion rules.
const unsigned_type threshold =
((std::numeric_limits<unsigned_type>::max)() - Lim + 1) % Lim;
while (helper::lo(product) < threshold) {
bits = fast_bits(g);
product = helper::multiply(bits, Lim);
}
}
return helper::hi(product);
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_

View File

@@ -0,0 +1,202 @@
// 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: uniform_real_distribution.h
// -----------------------------------------------------------------------------
//
// This header defines a class for representing a uniform floating-point
// distribution over a half-open interval [a,b). You use this distribution in
// combination with an Abseil random bit generator to produce random values
// according to the rules of the distribution.
//
// `absl::uniform_real_distribution` is a drop-in replacement for the C++11
// `std::uniform_real_distribution` [rand.dist.uni.real] but is considerably
// faster than the libstdc++ implementation.
//
// Note: the standard-library version may occasionally return `1.0` when
// default-initialized. See https://bugs.llvm.org//show_bug.cgi?id=18767
// `absl::uniform_real_distribution` does not exhibit this behavior.
#ifndef ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_
#define ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_
#include <cassert>
#include <cmath>
#include <cstdint>
#include <istream>
#include <limits>
#include <type_traits>
#include "absl/meta/type_traits.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/random/internal/generate_real.h"
#include "absl/random/internal/iostream_state_saver.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::uniform_real_distribution<T>
//
// This distribution produces random floating-point values uniformly distributed
// over the half-open interval [a, b).
//
// Example:
//
// absl::BitGen gen;
//
// // Use the distribution to produce a value between 0.0 (inclusive)
// // and 1.0 (exclusive).
// double value = absl::uniform_real_distribution<double>(0, 1)(gen);
//
template <typename RealType = double>
class uniform_real_distribution {
public:
using result_type = RealType;
class param_type {
public:
using distribution_type = uniform_real_distribution;
explicit param_type(result_type lo = 0, result_type hi = 1)
: lo_(lo), hi_(hi), range_(hi - lo) {
// [rand.dist.uni.real] preconditions 2 & 3
assert(lo <= hi);
// NOTE: For integral types, we can promote the range to an unsigned type,
// which gives full width of the range. However for real (fp) types, this
// is not possible, so value generation cannot use the full range of the
// real type.
assert(range_ <= (std::numeric_limits<result_type>::max)());
}
result_type a() const { return lo_; }
result_type b() const { return hi_; }
friend bool operator==(const param_type& a, const param_type& b) {
return a.lo_ == b.lo_ && a.hi_ == b.hi_;
}
friend bool operator!=(const param_type& a, const param_type& b) {
return !(a == b);
}
private:
friend class uniform_real_distribution;
result_type lo_, hi_, range_;
static_assert(std::is_floating_point<RealType>::value,
"Class-template absl::uniform_real_distribution<> must be "
"parameterized using a floating-point type.");
};
uniform_real_distribution() : uniform_real_distribution(0) {}
explicit uniform_real_distribution(result_type lo, result_type hi = 1)
: param_(lo, hi) {}
explicit uniform_real_distribution(const param_type& param) : param_(param) {}
// uniform_real_distribution<T>::reset()
//
// Resets the uniform real distribution. Note that this function has no effect
// because the distribution already produces independent values.
void reset() {}
template <typename URBG>
result_type operator()(URBG& gen) { // NOLINT(runtime/references)
return operator()(gen, param_);
}
template <typename URBG>
result_type operator()(URBG& gen, // NOLINT(runtime/references)
const param_type& p);
result_type a() const { return param_.a(); }
result_type b() const { return param_.b(); }
param_type param() const { return param_; }
void param(const param_type& params) { param_ = params; }
result_type(min)() const { return a(); }
result_type(max)() const { return b(); }
friend bool operator==(const uniform_real_distribution& a,
const uniform_real_distribution& b) {
return a.param_ == b.param_;
}
friend bool operator!=(const uniform_real_distribution& a,
const uniform_real_distribution& b) {
return a.param_ != b.param_;
}
private:
param_type param_;
random_internal::FastUniformBits<uint64_t> fast_u64_;
};
// -----------------------------------------------------------------------------
// Implementation details follow
// -----------------------------------------------------------------------------
template <typename RealType>
template <typename URBG>
typename uniform_real_distribution<RealType>::result_type
uniform_real_distribution<RealType>::operator()(
URBG& gen, const param_type& p) { // NOLINT(runtime/references)
using random_internal::GeneratePositiveTag;
using random_internal::GenerateRealFromBits;
using real_type =
absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
while (true) {
const result_type sample =
GenerateRealFromBits<real_type, GeneratePositiveTag, true>(
fast_u64_(gen));
const result_type res = p.a() + (sample * p.range_);
if (res < p.b() || p.range_ <= 0 || !std::isfinite(p.range_)) {
return res;
}
// else sample rejected, try again.
}
}
template <typename CharT, typename Traits, typename RealType>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const uniform_real_distribution<RealType>& x) {
auto saver = random_internal::make_ostream_state_saver(os);
os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);
os << x.a() << os.fill() << x.b();
return os;
}
template <typename CharT, typename Traits, typename RealType>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
uniform_real_distribution<RealType>& x) { // NOLINT(runtime/references)
using param_type = typename uniform_real_distribution<RealType>::param_type;
using result_type = typename uniform_real_distribution<RealType>::result_type;
auto saver = random_internal::make_istream_state_saver(is);
auto a = random_internal::read_floating_point<result_type>(is);
if (is.fail()) return is;
auto b = random_internal::read_floating_point<result_type>(is);
if (!is.fail()) {
x.param(param_type(a, b));
}
return is;
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_

View File

@@ -0,0 +1,272 @@
// 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.
#ifndef ABSL_RANDOM_ZIPF_DISTRIBUTION_H_
#define ABSL_RANDOM_ZIPF_DISTRIBUTION_H_
#include <cassert>
#include <cmath>
#include <istream>
#include <limits>
#include <ostream>
#include <type_traits>
#include "absl/random/internal/iostream_state_saver.h"
#include "absl/random/internal/traits.h"
#include "absl/random/uniform_real_distribution.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::zipf_distribution produces random integer-values in the range [0, k],
// distributed according to the unnormalized discrete probability function:
//
// P(x) = (v + x) ^ -q
//
// The parameter `v` must be greater than 0 and the parameter `q` must be
// greater than 1. If either of these parameters take invalid values then the
// behavior is undefined.
//
// IntType is the result_type generated by the generator. It must be of integral
// type; a static_assert ensures this is the case.
//
// The implementation is based on W.Hormann, G.Derflinger:
//
// "Rejection-Inversion to Generate Variates from Monotone Discrete
// Distributions"
//
// http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz
//
template <typename IntType = int>
class zipf_distribution {
public:
using result_type = IntType;
class param_type {
public:
using distribution_type = zipf_distribution;
// Preconditions: k > 0, v > 0, q > 1
// The precondidtions are validated when NDEBUG is not defined via
// a pair of assert() directives.
// If NDEBUG is defined and either or both of these parameters take invalid
// values, the behavior of the class is undefined.
explicit param_type(result_type k = (std::numeric_limits<IntType>::max)(),
double q = 2.0, double v = 1.0);
result_type k() const { return k_; }
double q() const { return q_; }
double v() const { return v_; }
friend bool operator==(const param_type& a, const param_type& b) {
return a.k_ == b.k_ && a.q_ == b.q_ && a.v_ == b.v_;
}
friend bool operator!=(const param_type& a, const param_type& b) {
return !(a == b);
}
private:
friend class zipf_distribution;
inline double h(double x) const;
inline double hinv(double x) const;
inline double compute_s() const;
inline double pow_negative_q(double x) const;
// Parameters here are exactly the same as the parameters of Algorithm ZRI
// in the paper.
IntType k_;
double q_;
double v_;
double one_minus_q_; // 1-q
double s_;
double one_minus_q_inv_; // 1 / 1-q
double hxm_; // h(k + 0.5)
double hx0_minus_hxm_; // h(x0) - h(k + 0.5)
static_assert(random_internal::IsIntegral<IntType>::value,
"Class-template absl::zipf_distribution<> must be "
"parameterized using an integral type.");
};
zipf_distribution()
: zipf_distribution((std::numeric_limits<IntType>::max)()) {}
explicit zipf_distribution(result_type k, double q = 2.0, double v = 1.0)
: param_(k, q, v) {}
explicit zipf_distribution(const param_type& p) : param_(p) {}
void reset() {}
template <typename URBG>
result_type operator()(URBG& g) { // NOLINT(runtime/references)
return (*this)(g, param_);
}
template <typename URBG>
result_type operator()(URBG& g, // NOLINT(runtime/references)
const param_type& p);
result_type k() const { return param_.k(); }
double q() const { return param_.q(); }
double v() const { return param_.v(); }
param_type param() const { return param_; }
void param(const param_type& p) { param_ = p; }
result_type(min)() const { return 0; }
result_type(max)() const { return k(); }
friend bool operator==(const zipf_distribution& a,
const zipf_distribution& b) {
return a.param_ == b.param_;
}
friend bool operator!=(const zipf_distribution& a,
const zipf_distribution& b) {
return a.param_ != b.param_;
}
private:
param_type param_;
};
// --------------------------------------------------------------------------
// Implementation details follow
// --------------------------------------------------------------------------
template <typename IntType>
zipf_distribution<IntType>::param_type::param_type(
typename zipf_distribution<IntType>::result_type k, double q, double v)
: k_(k), q_(q), v_(v), one_minus_q_(1 - q) {
assert(q > 1);
assert(v > 0);
assert(k > 0);
one_minus_q_inv_ = 1 / one_minus_q_;
// Setup for the ZRI algorithm (pg 17 of the paper).
// Compute: h(i max) => h(k + 0.5)
constexpr double kMax = 18446744073709549568.0;
double kd = static_cast<double>(k);
// TODO(absl-team): Determine if this check is needed, and if so, add a test
// that fails for k > kMax
if (kd > kMax) {
// Ensure that our maximum value is capped to a value which will
// round-trip back through double.
kd = kMax;
}
hxm_ = h(kd + 0.5);
// Compute: h(0)
const bool use_precomputed = (v == 1.0 && q == 2.0);
const double h0x5 = use_precomputed ? (-1.0 / 1.5) // exp(-log(1.5))
: h(0.5);
const double elogv_q = (v_ == 1.0) ? 1 : pow_negative_q(v_);
// h(0) = h(0.5) - exp(log(v) * -q)
hx0_minus_hxm_ = (h0x5 - elogv_q) - hxm_;
// And s
s_ = use_precomputed ? 0.46153846153846123 : compute_s();
}
template <typename IntType>
double zipf_distribution<IntType>::param_type::h(double x) const {
// std::exp(one_minus_q_ * std::log(v_ + x)) * one_minus_q_inv_;
x += v_;
return (one_minus_q_ == -1.0)
? (-1.0 / x) // -exp(-log(x))
: (std::exp(std::log(x) * one_minus_q_) * one_minus_q_inv_);
}
template <typename IntType>
double zipf_distribution<IntType>::param_type::hinv(double x) const {
// std::exp(one_minus_q_inv_ * std::log(one_minus_q_ * x)) - v_;
return -v_ + ((one_minus_q_ == -1.0)
? (-1.0 / x) // exp(-log(-x))
: std::exp(one_minus_q_inv_ * std::log(one_minus_q_ * x)));
}
template <typename IntType>
double zipf_distribution<IntType>::param_type::compute_s() const {
// 1 - hinv(h(1.5) - std::exp(std::log(v_ + 1) * -q_));
return 1.0 - hinv(h(1.5) - pow_negative_q(v_ + 1.0));
}
template <typename IntType>
double zipf_distribution<IntType>::param_type::pow_negative_q(double x) const {
// std::exp(std::log(x) * -q_);
return q_ == 2.0 ? (1.0 / (x * x)) : std::exp(std::log(x) * -q_);
}
template <typename IntType>
template <typename URBG>
typename zipf_distribution<IntType>::result_type
zipf_distribution<IntType>::operator()(
URBG& g, const param_type& p) { // NOLINT(runtime/references)
absl::uniform_real_distribution<double> uniform_double;
double k;
for (;;) {
const double v = uniform_double(g);
const double u = p.hxm_ + v * p.hx0_minus_hxm_;
const double x = p.hinv(u);
k = rint(x); // std::floor(x + 0.5);
if (k > static_cast<double>(p.k())) continue; // reject k > max_k
if (k - x <= p.s_) break;
const double h = p.h(k + 0.5);
const double r = p.pow_negative_q(p.v_ + k);
if (u >= h - r) break;
}
IntType ki = static_cast<IntType>(k);
assert(ki <= p.k_);
return ki;
}
template <typename CharT, typename Traits, typename IntType>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
const zipf_distribution<IntType>& x) {
using stream_type =
typename random_internal::stream_format_type<IntType>::type;
auto saver = random_internal::make_ostream_state_saver(os);
os.precision(random_internal::stream_precision_helper<double>::kPrecision);
os << static_cast<stream_type>(x.k()) << os.fill() << x.q() << os.fill()
<< x.v();
return os;
}
template <typename CharT, typename Traits, typename IntType>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
zipf_distribution<IntType>& x) { // NOLINT(runtime/references)
using result_type = typename zipf_distribution<IntType>::result_type;
using param_type = typename zipf_distribution<IntType>::param_type;
using stream_type =
typename random_internal::stream_format_type<IntType>::type;
stream_type k;
double q;
double v;
auto saver = random_internal::make_istream_state_saver(is);
is >> k >> q >> v;
if (!is.fail()) {
x.param(param_type(static_cast<result_type>(k), q, v));
}
return is;
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_ZIPF_DISTRIBUTION_H_