83 lines
2.8 KiB
C++
83 lines
2.8 KiB
C++
// PCG Random Number Generation for C++
|
|
//
|
|
// Copyright 2014-2019 Melissa O'Neill <oneill@pcg-random.org>,
|
|
// and the PCG Project contributors.
|
|
//
|
|
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (provided in
|
|
// LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0)
|
|
// or under the MIT license (provided in LICENSE-MIT.txt and at
|
|
// http://opensource.org/licenses/MIT), at your option. This file may not
|
|
// be copied, modified, or distributed except according to those terms.
|
|
//
|
|
// Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either
|
|
// express or implied. See your chosen license for details.
|
|
//
|
|
// For additional information about the PCG random number generation scheme,
|
|
// visit http://www.pcg-random.org/.
|
|
//
|
|
// -----------------------------------------------------------------------------
|
|
//
|
|
// Leonard Hecker <lhecker@microsoft.com>:
|
|
// The following contents are an extract of pcg_engines::oneseq_dxsm_64_32
|
|
// reduced down to the bare essentials, while retaining base functionality.
|
|
|
|
namespace pcg_engines {
|
|
class oneseq_dxsm_64_32 {
|
|
using xtype = uint32_t;
|
|
using itype = uint64_t;
|
|
|
|
itype state_;
|
|
|
|
static constexpr uint64_t multiplier() {
|
|
return 6364136223846793005ULL;
|
|
}
|
|
|
|
static constexpr uint64_t increment() {
|
|
return 1442695040888963407ULL;
|
|
}
|
|
|
|
static itype bump(itype state) {
|
|
return state * multiplier() + increment();
|
|
}
|
|
|
|
itype base_generate0() {
|
|
itype old_state = state_;
|
|
state_ = bump(state_);
|
|
return old_state;
|
|
}
|
|
|
|
public:
|
|
explicit oneseq_dxsm_64_32(itype state = 0xcafef00dd15ea5e5ULL) : state_(bump(state + increment())) {
|
|
}
|
|
|
|
// Returns a value in the interval [0, UINT32_MAX].
|
|
xtype operator()() {
|
|
constexpr auto xtypebits = uint8_t(sizeof(xtype) * 8);
|
|
constexpr auto itypebits = uint8_t(sizeof(itype) * 8);
|
|
|
|
auto internal = base_generate0();
|
|
auto hi = xtype(internal >> (itypebits - xtypebits));
|
|
auto lo = xtype(internal);
|
|
|
|
lo |= 1;
|
|
hi ^= hi >> (xtypebits / 2);
|
|
hi *= xtype(multiplier());
|
|
hi ^= hi >> (3 * (xtypebits / 4));
|
|
hi *= lo;
|
|
return hi;
|
|
}
|
|
|
|
// Returns a value in the interval [0, upper_bound).
|
|
xtype operator()(xtype upper_bound) {
|
|
uint32_t threshold = (UINT64_MAX + uint32_t(1) - upper_bound) % upper_bound;
|
|
for (;;) {
|
|
auto r = operator()();
|
|
if (r >= threshold)
|
|
return r % upper_bound;
|
|
}
|
|
}
|
|
};
|
|
}
|