OSDN Git Service

Make RandomNumberGenerator compatible with <random>
authorMehdi Amini <mehdi.amini@apple.com>
Tue, 11 Oct 2016 07:13:01 +0000 (07:13 +0000)
committerMehdi Amini <mehdi.amini@apple.com>
Tue, 11 Oct 2016 07:13:01 +0000 (07:13 +0000)
LLVM's RandomNumberGenerator wasn't compatible with
the random distribution from <random>.

Fixes PR25105

Patch by: Serge Guelton <serge.guelton@telecom-bretagne.eu>

Differential Revision: https://reviews.llvm.org/D25443

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283854 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/RandomNumberGenerator.h
lib/Support/RandomNumberGenerator.cpp
unittests/IR/ModuleTest.cpp

index 31ae275..1250132 100644 (file)
@@ -31,9 +31,20 @@ class StringRef;
 /// Module::createRNG to create a new RNG instance for use with that
 /// module.
 class RandomNumberGenerator {
+
+  // 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000
+  // http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine
+  // This RNG is deterministically portable across C++11
+  // implementations.
+  using generator_type = std::mt19937_64;
+
 public:
+  using result_type = generator_type::result_type;
+
   /// Returns a random number in the range [0, Max).
-  uint_fast64_t operator()();
+  result_type operator()();
+  static constexpr result_type min() { return generator_type::min(); }
+  static constexpr result_type max() { return generator_type::max(); }
 
 private:
   /// Seeds and salts the underlying RNG engine.
@@ -42,11 +53,7 @@ private:
   /// Module::createRNG to create a new RNG salted with the Module ID.
   RandomNumberGenerator(StringRef Salt);
 
-  // 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000
-  // http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine
-  // This RNG is deterministically portable across C++11
-  // implementations.
-  std::mt19937_64 Generator;
+  generator_type Generator;
 
   // Noncopyable.
   RandomNumberGenerator(const RandomNumberGenerator &other) = delete;
index 087c671..d340764 100644 (file)
@@ -57,7 +57,7 @@ RandomNumberGenerator::RandomNumberGenerator(StringRef Salt) {
   Generator.seed(SeedSeq);
 }
 
-uint_fast64_t RandomNumberGenerator::operator()() {
+RandomNumberGenerator::result_type RandomNumberGenerator::operator()() {
   return Generator();
 }
 
index c5f0bcb..043ea04 100644 (file)
@@ -9,8 +9,11 @@
 
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/RandomNumberGenerator.h"
 #include "gtest/gtest.h"
 
+#include <random>
+
 using namespace llvm;
 
 namespace {
@@ -45,4 +48,28 @@ TEST(ModuleTest, sortGlobalsByName) {
   }
 }
 
+TEST(ModuleTest, randomNumberGenerator) {
+  LLVMContext Context;
+  static char ID;
+  struct DummyPass : ModulePass {
+    DummyPass() : ModulePass(ID) {}
+    bool runOnModule(Module &) { return true; }
+  } DP;
+
+  Module M("R", Context);
+
+  std::uniform_int_distribution<int> dist;
+  constexpr std::size_t NBCheck = 10;
+
+  std::array<int, NBCheck> RandomStreams[2];
+  for (auto &RandomStream : RandomStreams) {
+    std::unique_ptr<RandomNumberGenerator> RNG{M.createRNG(&DP)};
+    std::generate(RandomStream.begin(), RandomStream.end(),
+                  [&]() { return dist(*RNG); });
+  }
+
+  EXPECT_TRUE(std::equal(RandomStreams[0].begin(), RandomStreams[0].end(),
+                         RandomStreams[1].begin()));
+}
+
 } // end namespace