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 20 namespace webrtc { 21 22 class Random { 23 public: 24 // TODO(tommi): Change this so that the seed can be initialized internally, 25 // e.g. by offering two ways of constructing or offer a static method that 26 // returns a seed that's suitable for initialization. 27 // The problem now is that callers are calling clock_->TimeInMicroseconds() 28 // which calls TickTime::Now().Ticks(), which can return a very low value on 29 // Mac and can result in a seed of 0 after conversion to microseconds. 30 // Besides the quality of the random seed being poor, this also requires 31 // the client to take on extra dependencies to generate a seed. 32 // If we go for a static seed generator in Random, we can use something from 33 // webrtc/rtc_base and make sure that it works the same way across platforms. 34 // See also discussion here: https://codereview.webrtc.org/1623543002/ 35 explicit Random(uint64_t seed); 36 37 Random() = delete; 38 Random(const Random&) = delete; 39 Random& operator=(const Random&) = delete; 40 41 // Return pseudo-random integer of the specified type. 42 // We need to limit the size to 32 bits to keep the output close to uniform. 43 template <typename T> Rand()44 T Rand() { 45 static_assert(std::numeric_limits<T>::is_integer && 46 std::numeric_limits<T>::radix == 2 && 47 std::numeric_limits<T>::digits <= 32, 48 "Rand is only supported for built-in integer types that are " 49 "32 bits or smaller."); 50 return static_cast<T>(NextOutput()); 51 } 52 53 // Uniformly distributed pseudo-random number in the interval [0, t]. 54 uint32_t Rand(uint32_t t); 55 56 // Uniformly distributed pseudo-random number in the interval [low, high]. 57 uint32_t Rand(uint32_t low, uint32_t high); 58 59 // Uniformly distributed pseudo-random number in the interval [low, high]. 60 int32_t Rand(int32_t low, int32_t high); 61 62 // Normal Distribution. 63 double Gaussian(double mean, double standard_deviation); 64 65 // Exponential Distribution. 66 double Exponential(double lambda); 67 68 private: 69 // Outputs a nonzero 64-bit random number using Xorshift algorithm. 70 // https://en.wikipedia.org/wiki/Xorshift NextOutput()71 uint64_t NextOutput() { 72 state_ ^= state_ >> 12; 73 state_ ^= state_ << 25; 74 state_ ^= state_ >> 27; 75 RTC_DCHECK(state_ != 0x0ULL); 76 return state_ * 2685821657736338717ull; 77 } 78 79 uint64_t state_; 80 }; 81 82 // Return pseudo-random number in the interval [0.0, 1.0). 83 template <> 84 float Random::Rand<float>(); 85 86 // Return pseudo-random number in the interval [0.0, 1.0). 87 template <> 88 double Random::Rand<double>(); 89 90 // Return pseudo-random boolean value. 91 template <> 92 bool Random::Rand<bool>(); 93 94 } // namespace webrtc 95 96 #endif // RTC_BASE_RANDOM_H_ 97