Fast prng is pcg

This commit is contained in:
Vinnie Falco
2019-02-21 10:56:11 -08:00
parent 6ada618c12
commit ee13bfad70
3 changed files with 93 additions and 18 deletions

View File

@ -6,6 +6,7 @@ Version 217:
* Fix file_body_win32
* Use async_initiate
* Check BOOST_NO_CXX11_THREAD_LOCAL
* Fast prng is pcg
--------------------------------------------------------------------------------

View File

@ -0,0 +1,65 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_PCG_HPP
#define BOOST_BEAST_CORE_DETAIL_PCG_HPP
#include <boost/core/ignore_unused.hpp>
#include <cstdint>
#include <random>
namespace boost {
namespace beast {
namespace detail {
class pcg
{
std::uint64_t state_ = 0;
std::uint64_t increment_;
public:
using result_type = std::uint32_t;
// Initialize the generator.
// There are no restrictions on the input values.
pcg(
std::uint64_t seed,
std::uint64_t stream)
{
// increment must be odd
increment_ = 2 * stream + 1;
boost::ignore_unused((*this)());
state_ += seed;
boost::ignore_unused((*this)());
}
std::uint32_t
operator()()
{
std::uint64_t const p = state_;
state_ = p *
6364136223846793005ULL +
increment_;
std::uint32_t const x =
static_cast<std::uint32_t>(
((p >> 18) ^ p) >> 27);
std::uint32_t const r = p >> 59;
#ifdef BOOST_MSVC
return _rotr(x, r);
#else
return (x >> r) | (x << ((1 + ~r) & 31));
#endif
}
};
} // detail
} // beast
} // boost
#endif

View File

@ -11,6 +11,7 @@
#define BOOST_BEAST_WEBSOCKET_DETAIL_IMPL_PRNG_IPP
#include <boost/beast/core/detail/chacha.hpp>
#include <boost/beast/core/detail/pcg.hpp>
#include <boost/align/aligned_alloc.hpp>
#include <boost/throw_exception.hpp>
#include <atomic>
@ -119,21 +120,25 @@ make_prng_no_tls(bool secure)
class fast_prng final : public prng
{
int refs_ = 0;
std::minstd_rand r_;
beast::detail::pcg r_;
public:
fast_prng* next = nullptr;
fast_prng()
: r_([]
{
static std::atomic<
std::uint64_t> nonce{0};
: r_(
[]{
auto const pv = prng_seed();
return static_cast<value_type>(
pv[0] + pv[1] + pv[2] + pv[3] +
pv[4] + pv[5] + pv[6] + pv[7] +
++nonce);
return
((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^
((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^
((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^
((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]);
}(),
[]{
static std::atomic<
std::uint32_t> nonce{0};
return ++nonce;
}())
{
}
@ -215,19 +220,23 @@ make_prng_tls(bool secure)
{
class fast_prng final : public prng
{
std::minstd_rand r_;
beast::detail::pcg r_;
public:
fast_prng()
: r_([]
{
static std::atomic<
std::uint64_t> nonce{0};
: r_(
[]{
auto const pv = prng_seed();
return static_cast<value_type>(
pv[0] + pv[1] + pv[2] + pv[3] +
pv[4] + pv[5] + pv[6] + pv[7] +
++nonce);
return
((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^
((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^
((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^
((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]);
}(),
[]{
static std::atomic<
std::uint32_t> nonce{0};
return ++nonce;
}())
{
}