1179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Use of this source code is governed by a BSD-style license that can be
3179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// found in the LICENSE file. See the AUTHORS file for names of contributors.
4179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
5179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#ifndef STORAGE_LEVELDB_UTIL_RANDOM_H_
6179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#define STORAGE_LEVELDB_UTIL_RANDOM_H_
7179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
8179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <stdint.h>
9179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
10179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace leveldb {
11179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
12179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// A very simple random number generator.  Not especially good at
13179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// generating truly random bits, but good enough for our needs in this
14179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// package.
15179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass Random {
16179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org private:
17179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  uint32_t seed_;
18179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public:
1908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org  explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) {
2008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org    // Avoid bad seeds.
2108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org    if (seed_ == 0 || seed_ == 2147483647L) {
2208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org      seed_ = 1;
2308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org    }
2408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org  }
25179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  uint32_t Next() {
26179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    static const uint32_t M = 2147483647L;   // 2^31-1
27179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    static const uint64_t A = 16807;  // bits 14, 8, 7, 5, 2, 1, 0
28179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // We are computing
29179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    //       seed_ = (seed_ * A) % M,    where M = 2^31-1
30179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    //
31179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // seed_ must not be zero or M, or else all subsequent computed values
32179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // will be zero or M respectively.  For all other values, seed_ will end
33179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // up cycling through every number in [1,M-1]
34179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    uint64_t product = seed_ * A;
35179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
36179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // Compute (product % M) using the fact that ((x << 31) % M) == x.
371511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org    seed_ = static_cast<uint32_t>((product >> 31) + (product & M));
38179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // The first reduction may overflow by 1 bit, so we may need to
39179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // repeat.  mod == M is not possible; using > allows the faster
40179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // sign-bit-based test.
41179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (seed_ > M) {
42179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      seed_ -= M;
43179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
44179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return seed_;
45179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
46179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Returns a uniformly distributed value in the range [0..n-1]
47179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // REQUIRES: n > 0
48179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  uint32_t Uniform(int n) { return Next() % n; }
49179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
50179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Randomly returns true ~"1/n" of the time, and false otherwise.
51179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // REQUIRES: n > 0
52179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  bool OneIn(int n) { return (Next() % n) == 0; }
53179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
54179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Skewed: pick "base" uniformly from range [0,max_log] and then
55179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // return "base" random bits.  The effect is to pick a number in the
56179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // range [0,2^max_log-1] with exponential bias towards smaller numbers.
57179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  uint32_t Skewed(int max_log) {
58179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return Uniform(1 << Uniform(max_log + 1));
59179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
60179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org};
61179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
6245b9940be332834440bd5299419f396e38085ebehans@chromium.org}  // namespace leveldb
63179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
64179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#endif  // STORAGE_LEVELDB_UTIL_RANDOM_H_
65