1 /* 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef RTC_BASE_RANDOM_H_ 12 #define RTC_BASE_RANDOM_H_ 13 14 #include <stdint.h> 15 16 #include <limits> 17 18 #include "rtc_base/checks.h" 19 #include "rtc_base/constructor_magic.h" 20 21 namespace webrtc { 22 23 class Random { 24 public: 25 // TODO(tommi): Change this so that the seed can be initialized internally, 26 // e.g. by offering two ways of constructing or offer a static method that 27 // returns a seed that's suitable for initialization. 28 // The problem now is that callers are calling clock_->TimeInMicroseconds() 29 // which calls TickTime::Now().Ticks(), which can return a very low value on 30 // Mac and can result in a seed of 0 after conversion to microseconds. 31 // Besides the quality of the random seed being poor, this also requires 32 // the client to take on extra dependencies to generate a seed. 33 // If we go for a static seed generator in Random, we can use something from 34 // webrtc/rtc_base and make sure that it works the same way across platforms. 35 // See also discussion here: https://codereview.webrtc.org/1623543002/ 36 explicit Random(uint64_t seed); 37 38 // Return pseudo-random integer of the specified type. 39 // We need to limit the size to 32 bits to keep the output close to uniform. 40 template <typename T> Rand()41 T Rand() { 42 static_assert(std::numeric_limits<T>::is_integer && 43 std::numeric_limits<T>::radix == 2 && 44 std::numeric_limits<T>::digits <= 32, 45 "Rand is only supported for built-in integer types that are " 46 "32 bits or smaller."); 47 return static_cast<T>(NextOutput()); 48 } 49 50 // Uniformly distributed pseudo-random number in the interval [0, t]. 51 uint32_t Rand(uint32_t t); 52 53 // Uniformly distributed pseudo-random number in the interval [low, high]. 54 uint32_t Rand(uint32_t low, uint32_t high); 55 56 // Uniformly distributed pseudo-random number in the interval [low, high]. 57 int32_t Rand(int32_t low, int32_t high); 58 59 // Normal Distribution. 60 double Gaussian(double mean, double standard_deviation); 61 62 // Exponential Distribution. 63 double Exponential(double lambda); 64 65 private: 66 // Outputs a nonzero 64-bit random number. NextOutput()67 uint64_t NextOutput() { 68 state_ ^= state_ >> 12; 69 state_ ^= state_ << 25; 70 state_ ^= state_ >> 27; 71 RTC_DCHECK(state_ != 0x0ULL); 72 return state_ * 2685821657736338717ull; 73 } 74 75 uint64_t state_; 76 77 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Random); 78 }; 79 80 // Return pseudo-random number in the interval [0.0, 1.0). 81 template <> 82 float Random::Rand<float>(); 83 84 // Return pseudo-random number in the interval [0.0, 1.0). 85 template <> 86 double Random::Rand<double>(); 87 88 // Return pseudo-random boolean value. 89 template <> 90 bool Random::Rand<bool>(); 91 92 } // namespace webrtc 93 94 #endif // RTC_BASE_RANDOM_H_ 95