Skip to content

Commit

Permalink
Make FastRandomContext support standard C++11 RNG interface
Browse files Browse the repository at this point in the history
This makes it possible to plug it into the various standard C++11 random
distribution algorithms and other functions like std::shuffle.

Cherry-picked from: 1ec1602
  • Loading branch information
sipa authored and xanimo committed Apr 3, 2024
1 parent 99e0be1 commit 0ae9436
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "uint256.h"

#include <stdint.h>
#include <limits>

/* Seed OpenSSL PRNG with additional entropy data */
void RandAddSeed();
Expand Down Expand Up @@ -114,6 +115,12 @@ class FastRandomContext {

/** Generate a random boolean. */
bool randbool() { return randbits(1); }

// Compatibility with the C++11 UniformRandomBitGenerator concept
typedef uint64_t result_type;
static constexpr uint64_t min() { return 0; }
static constexpr uint64_t max() { return std::numeric_limits<uint64_t>::max(); }
inline uint64_t operator()() { return rand64(); }
};

/* Number of random bytes returned by GetOSRand.
Expand Down
22 changes: 22 additions & 0 deletions src/test/random_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

#include <boost/test/unit_test.hpp>

#include <random>
#include <algorithm>

BOOST_FIXTURE_TEST_SUITE(random_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(osrandom_tests)
Expand Down Expand Up @@ -57,4 +60,23 @@ BOOST_AUTO_TEST_CASE(fastrandom_randbits)
}
}

/** Does-it-compile test for compatibility with standard C++11 RNG interface. */
BOOST_AUTO_TEST_CASE(stdrandom_test)
{
FastRandomContext ctx;
std::uniform_int_distribution<int> distribution(3, 9);
for (int i = 0; i < 100; ++i) {
int x = distribution(ctx);
BOOST_CHECK(x >= 3);
BOOST_CHECK(x <= 9);

std::vector<int> test{1,2,3,4,5,6,7,8,9,10};
std::shuffle(test.begin(), test.end(), ctx);
for (int j = 1; j <= 10; ++j) {
BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
}
}

}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 0ae9436

Please sign in to comment.