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