blob: 15a3dee90e0eeeec010522144335faccd8a64b1a [file] [log] [blame]
Matt Wala1bd2fce2014-08-08 14:02:09 -07001//===- subzero/src/IceRNG.h - Random number generator -----------*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares a random number generator.
Andrew Scull9612d322015-07-06 14:53:25 -070012///
Matt Wala1bd2fce2014-08-08 14:02:09 -070013//===----------------------------------------------------------------------===//
14
15#ifndef SUBZERO_SRC_ICERNG_H
16#define SUBZERO_SRC_ICERNG_H
17
Matt Wala1bd2fce2014-08-08 14:02:09 -070018#include "llvm/ADT/StringRef.h"
Matt Walac3302742014-08-15 16:21:56 -070019#include "llvm/Support/Compiler.h"
Qining Luaee5fa82015-08-20 14:59:03 -070020#include "IceDefs.h"
21
John Porto67f8de92015-06-25 10:14:17 -070022#include <cstdint>
Matt Wala1bd2fce2014-08-08 14:02:09 -070023
24namespace Ice {
25
26class RandomNumberGenerator {
Jim Stichnothc6ead202015-02-24 09:30:30 -080027 RandomNumberGenerator() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070028 RandomNumberGenerator(const RandomNumberGenerator &) = delete;
29 RandomNumberGenerator &operator=(const RandomNumberGenerator &) = delete;
30
Matt Wala1bd2fce2014-08-08 14:02:09 -070031public:
Jan Voung1f47ad02015-03-20 15:01:26 -070032 explicit RandomNumberGenerator(uint64_t Seed, llvm::StringRef Salt = "");
Qining Luaee5fa82015-08-20 14:59:03 -070033 /// Create a random number generator with: global seed, randomization pass ID
34 /// and a salt uint64_t integer.
35 /// @param Seed should be a global seed.
36 /// @param RandomizationPassID should be one of RandomizationPassesEnum.
37 /// @param Salt should be an additional integer input for generating unique
38 /// RNG.
39 /// The global seed is 64 bits; since it is likely to originate from the
40 /// system time, the lower bits are more "valuable" than the upper bits. As
41 /// such, we merge the randomization pass ID and the salt into the global seed
42 /// by xor'ing them into high bit ranges. We expect the pass ID to fit within
43 /// 4 bits, so it gets shifted by 60 to merge into the upper 4 bits. We expect
44 /// the salt (usually the function sequence number) to fit within 12 bits, so
45 /// it gets shifted by 48 before merging.
46 explicit RandomNumberGenerator(uint64_t Seed,
47 RandomizationPassesEnum RandomizationPassID,
48 uint64_t Salt = 0);
Matt Wala1bd2fce2014-08-08 14:02:09 -070049 uint64_t next(uint64_t Max);
50
51private:
52 uint64_t State;
53};
54
Andrew Scull57e12682015-09-16 11:30:19 -070055/// This class adds additional random number generator utilities. The reason for
56/// the wrapper class is that we want to keep the RandomNumberGenerator
57/// interface identical to LLVM's.
Matt Walac3302742014-08-15 16:21:56 -070058class RandomNumberGeneratorWrapper {
Jim Stichnothc6ead202015-02-24 09:30:30 -080059 RandomNumberGeneratorWrapper() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070060 RandomNumberGeneratorWrapper(const RandomNumberGeneratorWrapper &) = delete;
61 RandomNumberGeneratorWrapper &
62 operator=(const RandomNumberGeneratorWrapper &) = delete;
63
Matt Walac3302742014-08-15 16:21:56 -070064public:
Jim Stichnothe6d24782014-12-19 05:42:24 -080065 uint64_t operator()(uint64_t Max) { return RNG.next(Max); }
Matt Walac3302742014-08-15 16:21:56 -070066 bool getTrueWithProbability(float Probability);
Jim Stichnothc6ead202015-02-24 09:30:30 -080067 explicit RandomNumberGeneratorWrapper(RandomNumberGenerator &RNG)
68 : RNG(RNG) {}
Matt Walac3302742014-08-15 16:21:56 -070069
70private:
Matt Walac3302742014-08-15 16:21:56 -070071 RandomNumberGenerator &RNG;
72};
73
Andrew Scull57e12682015-09-16 11:30:19 -070074/// RandomShuffle is an implementation of std::random_shuffle() that doesn't
75/// change across stdlib implementations. Adapted from a sample implementation
76/// at cppreference.com.
Jim Stichnothcaef3482015-04-09 11:19:38 -070077template <class RandomIt, class RandomFunc>
78void RandomShuffle(RandomIt First, RandomIt Last, RandomFunc &&RNG) {
79 for (auto i = Last - First - 1; i > 0; --i)
80 std::swap(First[i], First[RNG(i + 1)]);
81}
82
Matt Wala1bd2fce2014-08-08 14:02:09 -070083} // end of namespace Ice
84
85#endif // SUBZERO_SRC_ICERNG_H