create
This commit is contained in:
200
Pods/abseil/absl/random/bernoulli_distribution.h
generated
Normal file
200
Pods/abseil/absl/random/bernoulli_distribution.h
generated
Normal 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_
|
||||
427
Pods/abseil/absl/random/beta_distribution.h
generated
Normal file
427
Pods/abseil/absl/random/beta_distribution.h
generated
Normal 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
185
Pods/abseil/absl/random/bit_gen_ref.h
generated
Normal 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_
|
||||
98
Pods/abseil/absl/random/discrete_distribution.cc
generated
Normal file
98
Pods/abseil/absl/random/discrete_distribution.cc
generated
Normal 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
|
||||
247
Pods/abseil/absl/random/discrete_distribution.h
generated
Normal file
247
Pods/abseil/absl/random/discrete_distribution.h
generated
Normal 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,...,pn−1)=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
452
Pods/abseil/absl/random/distributions.h
generated
Normal 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_
|
||||
165
Pods/abseil/absl/random/exponential_distribution.h
generated
Normal file
165
Pods/abseil/absl/random/exponential_distribution.h
generated
Normal 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_
|
||||
104
Pods/abseil/absl/random/gaussian_distribution.cc
generated
Normal file
104
Pods/abseil/absl/random/gaussian_distribution.cc
generated
Normal 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
|
||||
275
Pods/abseil/absl/random/gaussian_distribution.h
generated
Normal file
275
Pods/abseil/absl/random/gaussian_distribution.h
generated
Normal 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_
|
||||
95
Pods/abseil/absl/random/internal/distribution_caller.h
generated
Normal file
95
Pods/abseil/absl/random/internal/distribution_caller.h
generated
Normal 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_
|
||||
271
Pods/abseil/absl/random/internal/fast_uniform_bits.h
generated
Normal file
271
Pods/abseil/absl/random/internal/fast_uniform_bits.h
generated
Normal 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_
|
||||
57
Pods/abseil/absl/random/internal/fastmath.h
generated
Normal file
57
Pods/abseil/absl/random/internal/fastmath.h
generated
Normal 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_
|
||||
144
Pods/abseil/absl/random/internal/generate_real.h
generated
Normal file
144
Pods/abseil/absl/random/internal/generate_real.h
generated
Normal 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_
|
||||
245
Pods/abseil/absl/random/internal/iostream_state_saver.h
generated
Normal file
245
Pods/abseil/absl/random/internal/iostream_state_saver.h
generated
Normal 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_
|
||||
161
Pods/abseil/absl/random/internal/nonsecure_base.h
generated
Normal file
161
Pods/abseil/absl/random/internal/nonsecure_base.h
generated
Normal 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_
|
||||
287
Pods/abseil/absl/random/internal/pcg_engine.h
generated
Normal file
287
Pods/abseil/absl/random/internal/pcg_engine.h
generated
Normal 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_
|
||||
171
Pods/abseil/absl/random/internal/platform.h
generated
Normal file
171
Pods/abseil/absl/random/internal/platform.h
generated
Normal 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_
|
||||
253
Pods/abseil/absl/random/internal/pool_urbg.cc
generated
Normal file
253
Pods/abseil/absl/random/internal/pool_urbg.cc
generated
Normal 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
|
||||
131
Pods/abseil/absl/random/internal/pool_urbg.h
generated
Normal file
131
Pods/abseil/absl/random/internal/pool_urbg.h
generated
Normal 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_
|
||||
91
Pods/abseil/absl/random/internal/randen.cc
generated
Normal file
91
Pods/abseil/absl/random/internal/randen.cc
generated
Normal 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
|
||||
96
Pods/abseil/absl/random/internal/randen.h
generated
Normal file
96
Pods/abseil/absl/random/internal/randen.h
generated
Normal 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_
|
||||
229
Pods/abseil/absl/random/internal/randen_detect.cc
generated
Normal file
229
Pods/abseil/absl/random/internal/randen_detect.cc
generated
Normal 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
|
||||
33
Pods/abseil/absl/random/internal/randen_detect.h
generated
Normal file
33
Pods/abseil/absl/random/internal/randen_detect.h
generated
Normal 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_
|
||||
264
Pods/abseil/absl/random/internal/randen_engine.h
generated
Normal file
264
Pods/abseil/absl/random/internal/randen_engine.h
generated
Normal 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_
|
||||
526
Pods/abseil/absl/random/internal/randen_hwaes.cc
generated
Normal file
526
Pods/abseil/absl/random/internal/randen_hwaes.cc
generated
Normal 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)
|
||||
50
Pods/abseil/absl/random/internal/randen_hwaes.h
generated
Normal file
50
Pods/abseil/absl/random/internal/randen_hwaes.h
generated
Normal 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_
|
||||
462
Pods/abseil/absl/random/internal/randen_round_keys.cc
generated
Normal file
462
Pods/abseil/absl/random/internal/randen_round_keys.cc
generated
Normal 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
|
||||
471
Pods/abseil/absl/random/internal/randen_slow.cc
generated
Normal file
471
Pods/abseil/absl/random/internal/randen_slow.cc
generated
Normal 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
|
||||
40
Pods/abseil/absl/random/internal/randen_slow.h
generated
Normal file
40
Pods/abseil/absl/random/internal/randen_slow.h
generated
Normal 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_
|
||||
88
Pods/abseil/absl/random/internal/randen_traits.h
generated
Normal file
88
Pods/abseil/absl/random/internal/randen_traits.h
generated
Normal 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_
|
||||
165
Pods/abseil/absl/random/internal/salted_seed_seq.h
generated
Normal file
165
Pods/abseil/absl/random/internal/salted_seed_seq.h
generated
Normal 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_
|
||||
267
Pods/abseil/absl/random/internal/seed_material.cc
generated
Normal file
267
Pods/abseil/absl/random/internal/seed_material.cc
generated
Normal 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
|
||||
104
Pods/abseil/absl/random/internal/seed_material.h
generated
Normal file
104
Pods/abseil/absl/random/internal/seed_material.h
generated
Normal 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
149
Pods/abseil/absl/random/internal/traits.h
generated
Normal 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_
|
||||
244
Pods/abseil/absl/random/internal/uniform_helper.h
generated
Normal file
244
Pods/abseil/absl/random/internal/uniform_helper.h
generated
Normal 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_
|
||||
96
Pods/abseil/absl/random/internal/wide_multiply.h
generated
Normal file
96
Pods/abseil/absl/random/internal/wide_multiply.h
generated
Normal 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_
|
||||
256
Pods/abseil/absl/random/log_uniform_int_distribution.h
generated
Normal file
256
Pods/abseil/absl/random/log_uniform_int_distribution.h
generated
Normal 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_
|
||||
261
Pods/abseil/absl/random/poisson_distribution.h
generated
Normal file
261
Pods/abseil/absl/random/poisson_distribution.h
generated
Normal 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
189
Pods/abseil/absl/random/random.h
generated
Normal 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_
|
||||
46
Pods/abseil/absl/random/seed_gen_exception.cc
generated
Normal file
46
Pods/abseil/absl/random/seed_gen_exception.cc
generated
Normal 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
|
||||
55
Pods/abseil/absl/random/seed_gen_exception.h
generated
Normal file
55
Pods/abseil/absl/random/seed_gen_exception.h
generated
Normal 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_
|
||||
29
Pods/abseil/absl/random/seed_sequences.cc
generated
Normal file
29
Pods/abseil/absl/random/seed_sequences.cc
generated
Normal 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
111
Pods/abseil/absl/random/seed_sequences.h
generated
Normal 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_
|
||||
275
Pods/abseil/absl/random/uniform_int_distribution.h
generated
Normal file
275
Pods/abseil/absl/random/uniform_int_distribution.h
generated
Normal 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_
|
||||
202
Pods/abseil/absl/random/uniform_real_distribution.h
generated
Normal file
202
Pods/abseil/absl/random/uniform_real_distribution.h
generated
Normal 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_
|
||||
272
Pods/abseil/absl/random/zipf_distribution.h
generated
Normal file
272
Pods/abseil/absl/random/zipf_distribution.h
generated
Normal 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_
|
||||
Reference in New Issue
Block a user