LLVM API Documentation

RandomNumberGenerator.cpp
Go to the documentation of this file.
00001 //===-- RandomNumberGenerator.cpp - Implement RNG class -------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements random number generation (RNG).
00011 // The current implementation is NOT cryptographically secure as it uses
00012 // the C++11 <random> facilities.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #define DEBUG_TYPE "rng"
00017 #include "llvm/Support/RandomNumberGenerator.h"
00018 #include "llvm/Support/CommandLine.h"
00019 #include "llvm/Support/Debug.h"
00020 
00021 using namespace llvm;
00022 
00023 // Tracking BUG: 19665
00024 // http://llvm.org/bugs/show_bug.cgi?id=19665
00025 //
00026 // Do not change to cl::opt<uint64_t> since this silently breaks argument parsing.
00027 static cl::opt<unsigned long long>
00028 Seed("rng-seed", cl::value_desc("seed"),
00029      cl::desc("Seed for the random number generator"), cl::init(0));
00030 
00031 RandomNumberGenerator::RandomNumberGenerator(StringRef Salt) {
00032   DEBUG(
00033     if (Seed == 0)
00034       errs() << "Warning! Using unseeded random number generator.\n"
00035   );
00036 
00037   // Combine seed and salt using std::seed_seq.
00038   // Entropy: Seed-low, Seed-high, Salt...
00039   std::vector<uint32_t> Data;
00040   Data.reserve(2 + Salt.size()/4 + 1);
00041   Data.push_back(Seed);
00042   Data.push_back(Seed >> 32);
00043 
00044   uint32_t Pack = 0;
00045   for (size_t I = 0; I < Salt.size(); ++I) {
00046     Pack <<= 8;
00047     Pack += Salt[I];
00048 
00049     if (I%4 == 3)
00050       Data.push_back(Pack);
00051   }
00052   Data.push_back(Pack);
00053 
00054   std::seed_seq SeedSeq(Data.begin(), Data.end());
00055   Generator.seed(SeedSeq);
00056 }
00057 
00058 uint64_t RandomNumberGenerator::next(uint64_t Max) {
00059   std::uniform_int_distribution<uint64_t> distribution(0, Max - 1);
00060   return distribution(Generator);
00061 }