RandomNumberGenerator.cpp revision 274955
1219820Sjeff//===-- RandomNumberGenerator.cpp - Implement RNG class -------------------===// 2219820Sjeff// 3219820Sjeff// The LLVM Compiler Infrastructure 4219820Sjeff// 5219820Sjeff// This file is distributed under the University of Illinois Open Source 6219820Sjeff// License. See LICENSE.TXT for details. 7219820Sjeff// 8219820Sjeff//===----------------------------------------------------------------------===// 9219820Sjeff// 10219820Sjeff// This file implements random number generation (RNG). 11219820Sjeff// The current implementation is NOT cryptographically secure as it uses 12219820Sjeff// the C++11 <random> facilities. 13219820Sjeff// 14219820Sjeff//===----------------------------------------------------------------------===// 15219820Sjeff 16219820Sjeff#define DEBUG_TYPE "rng" 17219820Sjeff#include "llvm/Support/RandomNumberGenerator.h" 18219820Sjeff#include "llvm/Support/CommandLine.h" 19219820Sjeff#include "llvm/Support/Debug.h" 20219820Sjeff 21219820Sjeffusing namespace llvm; 22219820Sjeff 23219820Sjeff// Tracking BUG: 19665 24219820Sjeff// http://llvm.org/bugs/show_bug.cgi?id=19665 25219820Sjeff// 26219820Sjeff// Do not change to cl::opt<uint64_t> since this silently breaks argument parsing. 27219820Sjeffstatic cl::opt<unsigned long long> 28219820SjeffSeed("rng-seed", cl::value_desc("seed"), 29219820Sjeff cl::desc("Seed for the random number generator"), cl::init(0)); 30219820Sjeff 31219820SjeffRandomNumberGenerator::RandomNumberGenerator(StringRef Salt) { 32219820Sjeff DEBUG( 33219820Sjeff if (Seed == 0) 34219820Sjeff errs() << "Warning! Using unseeded random number generator.\n" 35219820Sjeff ); 36219820Sjeff 37219820Sjeff // Combine seed and salt using std::seed_seq. 38219820Sjeff // Entropy: Seed-low, Seed-high, Salt... 39219820Sjeff std::vector<uint32_t> Data; 40219820Sjeff Data.reserve(2 + Salt.size()/4 + 1); 41219820Sjeff Data.push_back(Seed); 42219820Sjeff Data.push_back(Seed >> 32); 43219820Sjeff 44219820Sjeff uint32_t Pack = 0; 45219820Sjeff for (size_t I = 0; I < Salt.size(); ++I) { 46219820Sjeff Pack <<= 8; 47219820Sjeff Pack += Salt[I]; 48219820Sjeff 49219820Sjeff if (I%4 == 3) 50219820Sjeff Data.push_back(Pack); 51219820Sjeff } 52219820Sjeff Data.push_back(Pack); 53219820Sjeff 54219820Sjeff std::seed_seq SeedSeq(Data.begin(), Data.end()); 55219820Sjeff Generator.seed(SeedSeq); 56219820Sjeff} 57219820Sjeff 58219820Sjeffuint64_t RandomNumberGenerator::next(uint64_t Max) { 59219820Sjeff std::uniform_int_distribution<uint64_t> distribution(0, Max - 1); 60219820Sjeff return distribution(Generator); 61219820Sjeff} 62219820Sjeff