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

View File

@@ -0,0 +1,95 @@
//
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
#define ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
#include <utility>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/base/internal/fast_type_id.h"
#include "absl/utility/utility.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// DistributionCaller provides an opportunity to overload the general
// mechanism for calling a distribution, allowing for mock-RNG classes
// to intercept such calls.
template <typename URBG>
struct DistributionCaller {
static_assert(!std::is_pointer<URBG>::value,
"You must pass a reference, not a pointer.");
// SFINAE to detect whether the URBG type includes a member matching
// bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
//
// These live inside BitGenRef so that they have friend access
// to MockingBitGen. (see similar methods in DistributionCaller).
template <template <class...> class Trait, class AlwaysVoid, class... Args>
struct detector : std::false_type {};
template <template <class...> class Trait, class... Args>
struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
: std::true_type {};
template <class T>
using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
std::declval<::absl::base_internal::FastTypeIdType>(),
std::declval<void*>(), std::declval<void*>()));
using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
// Default implementation of distribution caller.
template <typename DistrT, typename... Args>
static typename DistrT::result_type Impl(std::false_type, URBG* urbg,
Args&&... args) {
DistrT dist(std::forward<Args>(args)...);
return dist(*urbg);
}
// Mock implementation of distribution caller.
// The underlying KeyT must match the KeyT constructed by MockOverloadSet.
template <typename DistrT, typename... Args>
static typename DistrT::result_type Impl(std::true_type, URBG* urbg,
Args&&... args) {
using ResultT = typename DistrT::result_type;
using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
using KeyT = ResultT(DistrT, ArgTupleT);
ArgTupleT arg_tuple(std::forward<Args>(args)...);
ResultT result;
if (!urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
&result)) {
auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
result = dist(*urbg);
}
return result;
}
// Default implementation of distribution caller.
template <typename DistrT, typename... Args>
static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,
std::forward<Args>(args)...);
}
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_

View File

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

View File

@@ -0,0 +1,57 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_FASTMATH_H_
#define ABSL_RANDOM_INTERNAL_FASTMATH_H_
// This file contains fast math functions (bitwise ops as well as some others)
// which are implementation details of various absl random number distributions.
#include <cassert>
#include <cmath>
#include <cstdint>
#include "absl/numeric/bits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Compute log2(n) using integer operations.
// While std::log2 is more accurate than std::log(n) / std::log(2), for
// very large numbers--those close to std::numeric_limits<uint64_t>::max() - 2,
// for instance--std::log2 rounds up rather than down, which introduces
// definite skew in the results.
inline int IntLog2Floor(uint64_t n) {
return (n <= 1) ? 0 : (63 - countl_zero(n));
}
inline int IntLog2Ceil(uint64_t n) {
return (n <= 1) ? 0 : (64 - countl_zero(n - 1));
}
inline double StirlingLogFactorial(double n) {
assert(n >= 1);
// Using Stirling's approximation.
constexpr double kLog2PI = 1.83787706640934548356;
const double logn = std::log(n);
const double ninv = 1.0 / static_cast<double>(n);
return n * logn - n + 0.5 * (kLog2PI + logn) + (1.0 / 12.0) * ninv -
(1.0 / 360.0) * ninv * ninv * ninv;
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_FASTMATH_H_

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,131 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_POOL_URBG_H_
#define ABSL_RANDOM_INTERNAL_POOL_URBG_H_
#include <cinttypes>
#include <limits>
#include "absl/random/internal/traits.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RandenPool is a thread-safe random number generator [random.req.urbg] that
// uses an underlying pool of Randen generators to generate values. Each thread
// has affinity to one instance of the underlying pool generators. Concurrent
// access is guarded by a spin-lock.
template <typename T>
class RandenPool {
public:
using result_type = T;
static_assert(std::is_unsigned<result_type>::value,
"RandenPool template argument must be a built-in unsigned "
"integer type");
static constexpr result_type(min)() {
return (std::numeric_limits<result_type>::min)();
}
static constexpr result_type(max)() {
return (std::numeric_limits<result_type>::max)();
}
RandenPool() {}
// Returns a single value.
inline result_type operator()() { return Generate(); }
// Fill data with random values.
static void Fill(absl::Span<result_type> data);
protected:
// Generate returns a single value.
static result_type Generate();
};
extern template class RandenPool<uint8_t>;
extern template class RandenPool<uint16_t>;
extern template class RandenPool<uint32_t>;
extern template class RandenPool<uint64_t>;
// PoolURBG uses an underlying pool of random generators to implement a
// thread-compatible [random.req.urbg] interface with an internal cache of
// values.
template <typename T, size_t kBufferSize>
class PoolURBG {
// Inheritance to access the protected static members of RandenPool.
using unsigned_type = typename make_unsigned_bits<T>::type;
using PoolType = RandenPool<unsigned_type>;
using SpanType = absl::Span<unsigned_type>;
static constexpr size_t kInitialBuffer = kBufferSize + 1;
static constexpr size_t kHalfBuffer = kBufferSize / 2;
public:
using result_type = T;
static_assert(std::is_unsigned<result_type>::value,
"PoolURBG must be parameterized by an unsigned integer type");
static_assert(kBufferSize > 1,
"PoolURBG must be parameterized by a buffer-size > 1");
static_assert(kBufferSize <= 256,
"PoolURBG must be parameterized by a buffer-size <= 256");
static constexpr result_type(min)() {
return (std::numeric_limits<result_type>::min)();
}
static constexpr result_type(max)() {
return (std::numeric_limits<result_type>::max)();
}
PoolURBG() : next_(kInitialBuffer) {}
// copy-constructor does not copy cache.
PoolURBG(const PoolURBG&) : next_(kInitialBuffer) {}
const PoolURBG& operator=(const PoolURBG&) {
next_ = kInitialBuffer;
return *this;
}
// move-constructor does move cache.
PoolURBG(PoolURBG&&) = default;
PoolURBG& operator=(PoolURBG&&) = default;
inline result_type operator()() {
if (next_ >= kBufferSize) {
next_ = (kBufferSize > 2 && next_ > kBufferSize) ? kHalfBuffer : 0;
PoolType::Fill(SpanType(reinterpret_cast<unsigned_type*>(state_ + next_),
kBufferSize - next_));
}
return state_[next_++];
}
private:
// Buffer size.
size_t next_; // index within state_
result_type state_[kBufferSize];
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_POOL_URBG_H_

View File

@@ -0,0 +1,91 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/random/internal/randen.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/random/internal/randen_detect.h"
// RANDen = RANDom generator or beetroots in Swiss High German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
// High-level summary:
// 1) Reverie (see "A Robust and Sponge-Like PRNG with Improved Efficiency") is
// a sponge-like random generator that requires a cryptographic permutation.
// It improves upon "Provably Robust Sponge-Based PRNGs and KDFs" by
// achieving backtracking resistance with only one Permute() per buffer.
//
// 2) "Simpira v2: A Family of Efficient Permutations Using the AES Round
// Function" constructs up to 1024-bit permutations using an improved
// Generalized Feistel network with 2-round AES-128 functions. This Feistel
// block shuffle achieves diffusion faster and is less vulnerable to
// sliced-biclique attacks than the Type-2 cyclic shuffle.
//
// 3) "Improving the Generalized Feistel" and "New criterion for diffusion
// property" extends the same kind of improved Feistel block shuffle to 16
// branches, which enables a 2048-bit permutation.
//
// We combine these three ideas and also change Simpira's subround keys from
// structured/low-entropy counters to digits of Pi.
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
namespace {
struct RandenState {
const void* keys;
bool has_crypto;
};
RandenState GetRandenState() {
static const RandenState state = []() {
RandenState tmp;
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
// HW AES Dispatch.
if (HasRandenHwAesImplementation() && CPUSupportsRandenHwAes()) {
tmp.has_crypto = true;
tmp.keys = RandenHwAes::GetKeys();
} else {
tmp.has_crypto = false;
tmp.keys = RandenSlow::GetKeys();
}
#elif ABSL_HAVE_ACCELERATED_AES
// HW AES is enabled.
tmp.has_crypto = true;
tmp.keys = RandenHwAes::GetKeys();
#else
// HW AES is disabled.
tmp.has_crypto = false;
tmp.keys = RandenSlow::GetKeys();
#endif
return tmp;
}();
return state;
}
} // namespace
Randen::Randen() {
auto tmp = GetRandenState();
keys_ = tmp.keys;
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
has_crypto_ = tmp.has_crypto;
#endif
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl

View File

@@ -0,0 +1,96 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_H_
#include <cstddef>
#include "absl/random/internal/platform.h"
#include "absl/random/internal/randen_hwaes.h"
#include "absl/random/internal/randen_slow.h"
#include "absl/random/internal/randen_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RANDen = RANDom generator or beetroots in Swiss High German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
// Randen implements the basic state manipulation methods.
class Randen {
public:
static constexpr size_t kStateBytes = RandenTraits::kStateBytes;
static constexpr size_t kCapacityBytes = RandenTraits::kCapacityBytes;
static constexpr size_t kSeedBytes = RandenTraits::kSeedBytes;
~Randen() = default;
Randen();
// Generate updates the randen sponge. The outer portion of the sponge
// (kCapacityBytes .. kStateBytes) may be consumed as PRNG state.
// REQUIRES: state points to kStateBytes of state.
inline void Generate(void* state) const {
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
// HW AES Dispatch.
if (has_crypto_) {
RandenHwAes::Generate(keys_, state);
} else {
RandenSlow::Generate(keys_, state);
}
#elif ABSL_HAVE_ACCELERATED_AES
// HW AES is enabled.
RandenHwAes::Generate(keys_, state);
#else
// HW AES is disabled.
RandenSlow::Generate(keys_, state);
#endif
}
// Absorb incorporates additional seed material into the randen sponge. After
// absorb returns, Generate must be called before the state may be consumed.
// REQUIRES: seed points to kSeedBytes of seed.
// REQUIRES: state points to kStateBytes of state.
inline void Absorb(const void* seed, void* state) const {
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
// HW AES Dispatch.
if (has_crypto_) {
RandenHwAes::Absorb(seed, state);
} else {
RandenSlow::Absorb(seed, state);
}
#elif ABSL_HAVE_ACCELERATED_AES
// HW AES is enabled.
RandenHwAes::Absorb(seed, state);
#else
// HW AES is disabled.
RandenSlow::Absorb(seed, state);
#endif
}
private:
const void* keys_;
#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
bool has_crypto_;
#endif
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_H_

View File

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

View File

@@ -0,0 +1,33 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Returns whether the current CPU supports RandenHwAes implementation.
// This typically involves supporting cryptographic extensions on whichever
// platform is currently running.
bool CPUSupportsRandenHwAes();
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_

View File

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

View File

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

View File

@@ -0,0 +1,50 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_
#include "absl/base/config.h"
// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
// symbols from arbitrary system and other headers, since it may be built
// with different flags from other targets, using different levels of
// optimization, potentially introducing ODR violations.
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RANDen = RANDom generator or beetroots in Swiss High German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
// RandenHwAes implements the basic state manipulation methods.
class RandenHwAes {
public:
static void Generate(const void* keys, void* state_void);
static void Absorb(const void* seed_void, void* state_void);
static const void* GetKeys();
};
// HasRandenHwAesImplementation returns true when there is an accelerated
// implementation, and false otherwise. If there is no implementation,
// then attempting to use it will abort the program.
bool HasRandenHwAesImplementation();
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_

View File

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

View File

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

View File

@@ -0,0 +1,40 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_
#define ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_
#include <cstddef>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// RANDen = RANDom generator or beetroots in Swiss High German.
// RandenSlow implements the basic state manipulation methods for
// architectures lacking AES hardware acceleration intrinsics.
class RandenSlow {
public:
static void Generate(const void* keys, void* state_void);
static void Absorb(const void* seed_void, void* state_void);
static const void* GetKeys();
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,104 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_
#define ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/types/optional.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// Returns the number of 32-bit blocks needed to contain the given number of
// bits.
constexpr size_t SeedBitsToBlocks(size_t seed_size) {
return (seed_size + 31) / 32;
}
// Amount of entropy (measured in bits) used to instantiate a Seed Sequence,
// with which to create a URBG.
constexpr size_t kEntropyBitsNeeded = 256;
// Amount of entropy (measured in 32-bit blocks) used to instantiate a Seed
// Sequence, with which to create a URBG.
constexpr size_t kEntropyBlocksNeeded =
random_internal::SeedBitsToBlocks(kEntropyBitsNeeded);
static_assert(kEntropyBlocksNeeded > 0,
"Entropy used to seed URBGs must be nonzero.");
// Attempts to fill a span of uint32_t-values using an OS-provided source of
// true entropy (eg. /dev/urandom) into an array of uint32_t blocks of data. The
// resulting array may be used to initialize an instance of a class conforming
// to the C++ Standard "Seed Sequence" concept [rand.req.seedseq].
//
// If values.data() == nullptr, the behavior is undefined.
ABSL_MUST_USE_RESULT
bool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values);
// Attempts to fill a span of uint32_t-values using variates generated by an
// existing instance of a class conforming to the C++ Standard "Uniform Random
// Bit Generator" concept [rand.req.urng]. The resulting data may be used to
// initialize an instance of a class conforming to the C++ Standard
// "Seed Sequence" concept [rand.req.seedseq].
//
// If urbg == nullptr or values.data() == nullptr, the behavior is undefined.
template <typename URBG>
ABSL_MUST_USE_RESULT bool ReadSeedMaterialFromURBG(
URBG* urbg, absl::Span<uint32_t> values) {
random_internal::FastUniformBits<uint32_t> distr;
assert(urbg != nullptr && values.data() != nullptr);
if (urbg == nullptr || values.data() == nullptr) {
return false;
}
for (uint32_t& seed_value : values) {
seed_value = distr(*urbg);
}
return true;
}
// Mixes given sequence of values with into given sequence of seed material.
// Time complexity of this function is O(sequence.size() *
// seed_material.size()).
//
// Algorithm is based on code available at
// https://gist.github.com/imneme/540829265469e673d045
// by Melissa O'Neill.
void MixIntoSeedMaterial(absl::Span<const uint32_t> sequence,
absl::Span<uint32_t> seed_material);
// Returns salt value.
//
// Salt is obtained only once and stored in static variable.
//
// May return empty value if optaining the salt was not possible.
absl::optional<uint32_t> GetSaltMaterial();
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_

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

@@ -0,0 +1,149 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_TRAITS_H_
#define ABSL_RANDOM_INTERNAL_TRAITS_H_
#include <cstdint>
#include <limits>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// random_internal::is_widening_convertible<A, B>
//
// Returns whether a type A is widening-convertible to a type B.
//
// A is widening-convertible to B means:
// A a = <any number>;
// B b = a;
// A c = b;
// EXPECT_EQ(a, c);
template <typename A, typename B>
class is_widening_convertible {
// As long as there are enough bits in the exact part of a number:
// - unsigned can fit in float, signed, unsigned
// - signed can fit in float, signed
// - float can fit in float
// So we define rank to be:
// - rank(float) -> 2
// - rank(signed) -> 1
// - rank(unsigned) -> 0
template <class T>
static constexpr int rank() {
return !std::numeric_limits<T>::is_integer +
std::numeric_limits<T>::is_signed;
}
public:
// If an arithmetic-type B can represent at least as many digits as a type A,
// and B belongs to a rank no lower than A, then A can be safely represented
// by B through a widening-conversion.
static constexpr bool value =
std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits &&
rank<A>() <= rank<B>();
};
template <typename T>
struct IsIntegral : std::is_integral<T> {};
template <>
struct IsIntegral<absl::int128> : std::true_type {};
template <>
struct IsIntegral<absl::uint128> : std::true_type {};
template <typename T>
struct MakeUnsigned : std::make_unsigned<T> {};
template <>
struct MakeUnsigned<absl::int128> {
using type = absl::uint128;
};
template <>
struct MakeUnsigned<absl::uint128> {
using type = absl::uint128;
};
template <typename T>
struct IsUnsigned : std::is_unsigned<T> {};
template <>
struct IsUnsigned<absl::int128> : std::false_type {};
template <>
struct IsUnsigned<absl::uint128> : std::true_type {};
// unsigned_bits<N>::type returns the unsigned int type with the indicated
// number of bits.
template <size_t N>
struct unsigned_bits;
template <>
struct unsigned_bits<8> {
using type = uint8_t;
};
template <>
struct unsigned_bits<16> {
using type = uint16_t;
};
template <>
struct unsigned_bits<32> {
using type = uint32_t;
};
template <>
struct unsigned_bits<64> {
using type = uint64_t;
};
template <>
struct unsigned_bits<128> {
using type = absl::uint128;
};
// 256-bit wrapper for wide multiplications.
struct U256 {
uint128 hi;
uint128 lo;
};
template <>
struct unsigned_bits<256> {
using type = U256;
};
template <typename IntType>
struct make_unsigned_bits {
using type = typename unsigned_bits<
std::numeric_limits<typename MakeUnsigned<IntType>::type>::digits>::type;
};
template <typename T>
int BitWidth(T v) {
// Workaround for bit_width not supporting int128.
// Don't hardcode `64` to make sure this code does not trigger compiler
// warnings in smaller types.
constexpr int half_bits = sizeof(T) * 8 / 2;
if (sizeof(T) == 16 && (v >> half_bits) != 0) {
return bit_width(static_cast<uint64_t>(v >> half_bits)) + half_bits;
} else {
return bit_width(static_cast<uint64_t>(v));
}
}
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_TRAITS_H_

View File

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

View File

@@ -0,0 +1,96 @@
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
#define ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
#include <cstdint>
#include <limits>
#include <type_traits>
#if (defined(_WIN32) || defined(_WIN64)) && defined(_M_IA64)
#include <intrin.h> // NOLINT(build/include_order)
#pragma intrinsic(_umul128)
#define ABSL_INTERNAL_USE_UMUL128 1
#endif
#include "absl/base/config.h"
#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
#include "absl/random/internal/traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
// wide_multiply<T> multiplies two N-bit values to a 2N-bit result.
template <typename UIntType>
struct wide_multiply {
static constexpr size_t kN = std::numeric_limits<UIntType>::digits;
using input_type = UIntType;
using result_type = typename random_internal::unsigned_bits<kN * 2>::type;
static result_type multiply(input_type a, input_type b) {
return static_cast<result_type>(a) * b;
}
static input_type hi(result_type r) {
return static_cast<input_type>(r >> kN);
}
static input_type lo(result_type r) { return static_cast<input_type>(r); }
static_assert(std::is_unsigned<UIntType>::value,
"Class-template wide_multiply<> argument must be unsigned.");
};
// MultiplyU128ToU256 multiplies two 128-bit values to a 256-bit value.
inline U256 MultiplyU128ToU256(uint128 a, uint128 b) {
const uint128 a00 = static_cast<uint64_t>(a);
const uint128 a64 = a >> 64;
const uint128 b00 = static_cast<uint64_t>(b);
const uint128 b64 = b >> 64;
const uint128 c00 = a00 * b00;
const uint128 c64a = a00 * b64;
const uint128 c64b = a64 * b00;
const uint128 c128 = a64 * b64;
const uint64_t carry =
static_cast<uint64_t>(((c00 >> 64) + static_cast<uint64_t>(c64a) +
static_cast<uint64_t>(c64b)) >>
64);
return {c128 + (c64a >> 64) + (c64b >> 64) + carry,
c00 + (c64a << 64) + (c64b << 64)};
}
template <>
struct wide_multiply<uint128> {
using input_type = uint128;
using result_type = U256;
static result_type multiply(input_type a, input_type b) {
return MultiplyU128ToU256(a, b);
}
static input_type hi(result_type r) { return r.hi; }
static input_type lo(result_type r) { return r.lo; }
};
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_