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