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 #include "rtc_base/random.h"
11 
12 #include <math.h>
13 
14 #include "rtc_base/checks.h"
15 #include "rtc_base/numerics/safe_conversions.h"
16 
17 namespace webrtc {
18 
Random(uint64_t seed)19 Random::Random(uint64_t seed) {
20   RTC_DCHECK(seed != 0x0ull);
21   state_ = seed;
22 }
23 
Rand(uint32_t t)24 uint32_t Random::Rand(uint32_t t) {
25   // Casting the output to 32 bits will give an almost uniform number.
26   // Pr[x=0] = (2^32-1) / (2^64-1)
27   // Pr[x=k] = 2^32 / (2^64-1) for k!=0
28   // Uniform would be Pr[x=k] = 2^32 / 2^64 for all 32-bit integers k.
29   uint32_t x = NextOutput();
30   // If x / 2^32 is uniform on [0,1), then x / 2^32 * (t+1) is uniform on
31   // the interval [0,t+1), so the integer part is uniform on [0,t].
32   uint64_t result = x * (static_cast<uint64_t>(t) + 1);
33   result >>= 32;
34   return result;
35 }
36 
Rand(uint32_t low,uint32_t high)37 uint32_t Random::Rand(uint32_t low, uint32_t high) {
38   RTC_DCHECK(low <= high);
39   return Rand(high - low) + low;
40 }
41 
Rand(int32_t low,int32_t high)42 int32_t Random::Rand(int32_t low, int32_t high) {
43   RTC_DCHECK(low <= high);
44   const int64_t low_i64{low};
45   return rtc::dchecked_cast<int32_t>(
46       Rand(rtc::dchecked_cast<uint32_t>(high - low_i64)) + low_i64);
47 }
48 
49 template <>
Rand()50 float Random::Rand<float>() {
51   double result = NextOutput() - 1;
52   result = result / 0xFFFFFFFFFFFFFFFEull;
53   return static_cast<float>(result);
54 }
55 
56 template <>
Rand()57 double Random::Rand<double>() {
58   double result = NextOutput() - 1;
59   result = result / 0xFFFFFFFFFFFFFFFEull;
60   return result;
61 }
62 
63 template <>
Rand()64 bool Random::Rand<bool>() {
65   return Rand(0, 1) == 1;
66 }
67 
Gaussian(double mean,double standard_deviation)68 double Random::Gaussian(double mean, double standard_deviation) {
69   // Creating a Normal distribution variable from two independent uniform
70   // variables based on the Box-Muller transform, which is defined on the
71   // interval (0, 1]. Note that we rely on NextOutput to generate integers
72   // in the range [1, 2^64-1]. Normally this behavior is a bit frustrating,
73   // but here it is exactly what we need.
74   const double kPi = 3.14159265358979323846;
75   double u1 = static_cast<double>(NextOutput()) / 0xFFFFFFFFFFFFFFFFull;
76   double u2 = static_cast<double>(NextOutput()) / 0xFFFFFFFFFFFFFFFFull;
77   return mean + standard_deviation * sqrt(-2 * log(u1)) * cos(2 * kPi * u2);
78 }
79 
Exponential(double lambda)80 double Random::Exponential(double lambda) {
81   double uniform = Rand<double>();
82   return -log(uniform) / lambda;
83 }
84 
85 }  // namespace webrtc
86