1*144829d3SJF Bastien //===-- RandomNumberGenerator.cpp - Implement RNG class -------------------===//
2*144829d3SJF Bastien //
3*144829d3SJF Bastien //                     The LLVM Compiler Infrastructure
4*144829d3SJF Bastien //
5*144829d3SJF Bastien // This file is distributed under the University of Illinois Open Source
6*144829d3SJF Bastien // License. See LICENSE.TXT for details.
7*144829d3SJF Bastien //
8*144829d3SJF Bastien //===----------------------------------------------------------------------===//
9*144829d3SJF Bastien //
10*144829d3SJF Bastien // This file implements random number generation (RNG).
11*144829d3SJF Bastien // The current implementation is NOT cryptographically secure as it uses
12*144829d3SJF Bastien // the C++11 <random> facilities.
13*144829d3SJF Bastien //
14*144829d3SJF Bastien //===----------------------------------------------------------------------===//
15*144829d3SJF Bastien 
16*144829d3SJF Bastien #define DEBUG_TYPE "rng"
17*144829d3SJF Bastien #include "llvm/Support/RandomNumberGenerator.h"
18*144829d3SJF Bastien #include "llvm/Support/CommandLine.h"
19*144829d3SJF Bastien #include "llvm/Support/Debug.h"
20*144829d3SJF Bastien 
21*144829d3SJF Bastien using namespace llvm;
22*144829d3SJF Bastien 
23*144829d3SJF Bastien // Tracking BUG: 19665
24*144829d3SJF Bastien // http://llvm.org/bugs/show_bug.cgi?id=19665
25*144829d3SJF Bastien //
26*144829d3SJF Bastien // Do not change to cl::opt<uint64_t> since this silently breaks argument parsing.
27*144829d3SJF Bastien static cl::opt<unsigned long long>
28*144829d3SJF Bastien Seed("rng-seed", cl::value_desc("seed"),
29*144829d3SJF Bastien      cl::desc("Seed for the random number generator"), cl::init(0));
30*144829d3SJF Bastien 
31*144829d3SJF Bastien RandomNumberGenerator::RandomNumberGenerator(StringRef Salt) {
32*144829d3SJF Bastien   DEBUG(
33*144829d3SJF Bastien     if (Seed == 0)
34*144829d3SJF Bastien       errs() << "Warning! Using unseeded random number generator.\n"
35*144829d3SJF Bastien   );
36*144829d3SJF Bastien 
37*144829d3SJF Bastien   // Combine seed and salt using std::seed_seq.
38*144829d3SJF Bastien   // Entropy: Seed-low, Seed-high, Salt...
39*144829d3SJF Bastien   std::vector<uint32_t> Data;
40*144829d3SJF Bastien   Data.reserve(2 + Salt.size()/4 + 1);
41*144829d3SJF Bastien   Data.push_back(Seed);
42*144829d3SJF Bastien   Data.push_back(Seed >> 32);
43*144829d3SJF Bastien 
44*144829d3SJF Bastien   uint32_t Pack = 0;
45*144829d3SJF Bastien   for (size_t I = 0; I < Salt.size(); ++I) {
46*144829d3SJF Bastien     Pack <<= 8;
47*144829d3SJF Bastien     Pack += Salt[I];
48*144829d3SJF Bastien 
49*144829d3SJF Bastien     if (I%4 == 3)
50*144829d3SJF Bastien       Data.push_back(Pack);
51*144829d3SJF Bastien   }
52*144829d3SJF Bastien   Data.push_back(Pack);
53*144829d3SJF Bastien 
54*144829d3SJF Bastien   std::seed_seq SeedSeq(Data.begin(), Data.end());
55*144829d3SJF Bastien   Generator.seed(SeedSeq);
56*144829d3SJF Bastien }
57*144829d3SJF Bastien 
58*144829d3SJF Bastien uint64_t RandomNumberGenerator::next(uint64_t Max) {
59*144829d3SJF Bastien   std::uniform_int_distribution<uint64_t> distribution(0, Max - 1);
60*144829d3SJF Bastien   return distribution(Generator);
61*144829d3SJF Bastien }
62