1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
---|---|
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #include "vm/random.h" |
6 | #include "vm/dart.h" |
7 | #include "vm/flags.h" |
8 | #include "vm/os.h" |
9 | |
10 | namespace dart { |
11 | |
12 | DEFINE_FLAG(uint64_t, |
13 | random_seed, |
14 | 0, |
15 | "Override the random seed for debugging."); |
16 | |
17 | Random::Random() { |
18 | uint64_t seed = FLAG_random_seed; |
19 | if (seed == 0) { |
20 | Dart_EntropySource callback = Dart::entropy_source_callback(); |
21 | if (callback != NULL) { |
22 | if (!callback(reinterpret_cast<uint8_t*>(&seed), sizeof(seed))) { |
23 | // Callback failed. Reset the seed to 0. |
24 | seed = 0; |
25 | } |
26 | } |
27 | } |
28 | if (seed == 0) { |
29 | // We did not get a seed so far. As a fallback we do use the current time. |
30 | seed = OS::GetCurrentTimeMicros(); |
31 | } |
32 | Initialize(seed); |
33 | } |
34 | |
35 | void Random::Initialize(uint64_t seed) { |
36 | ASSERT(seed != 0); |
37 | // Crank the next state a couple of times. |
38 | _state = seed; |
39 | NextState(); |
40 | NextState(); |
41 | NextState(); |
42 | NextState(); |
43 | } |
44 | |
45 | Random::Random(uint64_t seed) { |
46 | Initialize(seed); |
47 | } |
48 | |
49 | Random::~Random() { |
50 | // Nothing to be done here. |
51 | } |
52 | |
53 | // The algorithm used here is Multiply with Carry (MWC) with a Base b = 2^32. |
54 | // http://en.wikipedia.org/wiki/Multiply-with-carry |
55 | // The constant A is selected from "Numerical Recipes 3rd Edition" p.348 B1. |
56 | void Random::NextState() { |
57 | const uint64_t MASK_32 = 0xffffffff; |
58 | const uint64_t A = 0xffffda61; |
59 | |
60 | uint64_t state_lo = _state & MASK_32; |
61 | uint64_t state_hi = (_state >> 32) & MASK_32; |
62 | _state = (A * state_lo) + state_hi; |
63 | } |
64 | |
65 | uint32_t Random::NextUInt32() { |
66 | const uint64_t MASK_32 = 0xffffffff; |
67 | NextState(); |
68 | return static_cast<uint32_t>(_state & MASK_32); |
69 | } |
70 | |
71 | } // namespace dart |
72 |