xref: /aosp_15_r20/external/cronet/base/rand_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/rand_util.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <limits.h>
8*6777b538SAndroid Build Coastguard Worker #include <math.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include <algorithm>
12*6777b538SAndroid Build Coastguard Worker #include <atomic>
13*6777b538SAndroid Build Coastguard Worker #include <limits>
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace base {
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker namespace {
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker // A MetricSubsampler instance is not thread-safe. However, the global
23*6777b538SAndroid Build Coastguard Worker // sampling state may be read concurrently with writing it via testing
24*6777b538SAndroid Build Coastguard Worker // scopers, hence the need to use atomics. All operations use
25*6777b538SAndroid Build Coastguard Worker // memory_order_relaxed because there are no dependent memory accesses.
26*6777b538SAndroid Build Coastguard Worker std::atomic<bool> g_subsampling_always_sample = false;
27*6777b538SAndroid Build Coastguard Worker std::atomic<bool> g_subsampling_never_sample = false;
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker }  // namespace
30*6777b538SAndroid Build Coastguard Worker 
RandUint64()31*6777b538SAndroid Build Coastguard Worker uint64_t RandUint64() {
32*6777b538SAndroid Build Coastguard Worker   uint64_t number;
33*6777b538SAndroid Build Coastguard Worker   RandBytes(&number, sizeof(number));
34*6777b538SAndroid Build Coastguard Worker   return number;
35*6777b538SAndroid Build Coastguard Worker }
36*6777b538SAndroid Build Coastguard Worker 
RandInt(int min,int max)37*6777b538SAndroid Build Coastguard Worker int RandInt(int min, int max) {
38*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(min, max);
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker   uint64_t range = static_cast<uint64_t>(max) - static_cast<uint64_t>(min) + 1;
41*6777b538SAndroid Build Coastguard Worker   // |range| is at most UINT_MAX + 1, so the result of RandGenerator(range)
42*6777b538SAndroid Build Coastguard Worker   // is at most UINT_MAX.  Hence it's safe to cast it from uint64_t to int64_t.
43*6777b538SAndroid Build Coastguard Worker   int result =
44*6777b538SAndroid Build Coastguard Worker       static_cast<int>(min + static_cast<int64_t>(base::RandGenerator(range)));
45*6777b538SAndroid Build Coastguard Worker   DCHECK_GE(result, min);
46*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(result, max);
47*6777b538SAndroid Build Coastguard Worker   return result;
48*6777b538SAndroid Build Coastguard Worker }
49*6777b538SAndroid Build Coastguard Worker 
RandDouble()50*6777b538SAndroid Build Coastguard Worker double RandDouble() {
51*6777b538SAndroid Build Coastguard Worker   return BitsToOpenEndedUnitInterval(base::RandUint64());
52*6777b538SAndroid Build Coastguard Worker }
53*6777b538SAndroid Build Coastguard Worker 
RandFloat()54*6777b538SAndroid Build Coastguard Worker float RandFloat() {
55*6777b538SAndroid Build Coastguard Worker   return BitsToOpenEndedUnitIntervalF(base::RandUint64());
56*6777b538SAndroid Build Coastguard Worker }
57*6777b538SAndroid Build Coastguard Worker 
RandTimeDelta(TimeDelta start,TimeDelta limit)58*6777b538SAndroid Build Coastguard Worker TimeDelta RandTimeDelta(TimeDelta start, TimeDelta limit) {
59*6777b538SAndroid Build Coastguard Worker   // We must have a finite, non-empty, non-reversed interval.
60*6777b538SAndroid Build Coastguard Worker   CHECK_LT(start, limit);
61*6777b538SAndroid Build Coastguard Worker   CHECK(!start.is_min());
62*6777b538SAndroid Build Coastguard Worker   CHECK(!limit.is_max());
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker   const int64_t range = (limit - start).InMicroseconds();
65*6777b538SAndroid Build Coastguard Worker   // Because of the `CHECK_LT()` above, range > 0, so this cast is safe.
66*6777b538SAndroid Build Coastguard Worker   const uint64_t delta_us = base::RandGenerator(static_cast<uint64_t>(range));
67*6777b538SAndroid Build Coastguard Worker   // ...and because `range` fit in an `int64_t`, so will `delta_us`.
68*6777b538SAndroid Build Coastguard Worker   return start + Microseconds(static_cast<int64_t>(delta_us));
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker 
RandTimeDeltaUpTo(TimeDelta limit)71*6777b538SAndroid Build Coastguard Worker TimeDelta RandTimeDeltaUpTo(TimeDelta limit) {
72*6777b538SAndroid Build Coastguard Worker   return RandTimeDelta(TimeDelta(), limit);
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker 
BitsToOpenEndedUnitInterval(uint64_t bits)75*6777b538SAndroid Build Coastguard Worker double BitsToOpenEndedUnitInterval(uint64_t bits) {
76*6777b538SAndroid Build Coastguard Worker   // We try to get maximum precision by masking out as many bits as will fit
77*6777b538SAndroid Build Coastguard Worker   // in the target type's mantissa, and raising it to an appropriate power to
78*6777b538SAndroid Build Coastguard Worker   // produce output in the range [0, 1).  For IEEE 754 doubles, the mantissa
79*6777b538SAndroid Build Coastguard Worker   // is expected to accommodate 53 bits (including the implied bit).
80*6777b538SAndroid Build Coastguard Worker   static_assert(std::numeric_limits<double>::radix == 2,
81*6777b538SAndroid Build Coastguard Worker                 "otherwise use scalbn");
82*6777b538SAndroid Build Coastguard Worker   constexpr int kBits = std::numeric_limits<double>::digits;
83*6777b538SAndroid Build Coastguard Worker   return ldexp(bits & ((UINT64_C(1) << kBits) - 1u), -kBits);
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker 
BitsToOpenEndedUnitIntervalF(uint64_t bits)86*6777b538SAndroid Build Coastguard Worker float BitsToOpenEndedUnitIntervalF(uint64_t bits) {
87*6777b538SAndroid Build Coastguard Worker   // We try to get maximum precision by masking out as many bits as will fit
88*6777b538SAndroid Build Coastguard Worker   // in the target type's mantissa, and raising it to an appropriate power to
89*6777b538SAndroid Build Coastguard Worker   // produce output in the range [0, 1).  For IEEE 754 floats, the mantissa is
90*6777b538SAndroid Build Coastguard Worker   // expected to accommodate 12 bits (including the implied bit).
91*6777b538SAndroid Build Coastguard Worker   static_assert(std::numeric_limits<float>::radix == 2, "otherwise use scalbn");
92*6777b538SAndroid Build Coastguard Worker   constexpr int kBits = std::numeric_limits<float>::digits;
93*6777b538SAndroid Build Coastguard Worker   return ldexpf(bits & ((UINT64_C(1) << kBits) - 1u), -kBits);
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker 
RandGenerator(uint64_t range)96*6777b538SAndroid Build Coastguard Worker uint64_t RandGenerator(uint64_t range) {
97*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(range, 0u);
98*6777b538SAndroid Build Coastguard Worker   // We must discard random results above this number, as they would
99*6777b538SAndroid Build Coastguard Worker   // make the random generator non-uniform (consider e.g. if
100*6777b538SAndroid Build Coastguard Worker   // MAX_UINT64 was 7 and |range| was 5, then a result of 1 would be twice
101*6777b538SAndroid Build Coastguard Worker   // as likely as a result of 3 or 4).
102*6777b538SAndroid Build Coastguard Worker   uint64_t max_acceptable_value =
103*6777b538SAndroid Build Coastguard Worker       (std::numeric_limits<uint64_t>::max() / range) * range - 1;
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker   uint64_t value;
106*6777b538SAndroid Build Coastguard Worker   do {
107*6777b538SAndroid Build Coastguard Worker     value = base::RandUint64();
108*6777b538SAndroid Build Coastguard Worker   } while (value > max_acceptable_value);
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker   return value % range;
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker 
RandBytesAsString(size_t length)113*6777b538SAndroid Build Coastguard Worker std::string RandBytesAsString(size_t length) {
114*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(length, 0u);
115*6777b538SAndroid Build Coastguard Worker   std::string result(length, '\0');
116*6777b538SAndroid Build Coastguard Worker   RandBytes(result.data(), length);
117*6777b538SAndroid Build Coastguard Worker   return result;
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker 
RandBytesAsVector(size_t length)120*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> RandBytesAsVector(size_t length) {
121*6777b538SAndroid Build Coastguard Worker   std::vector<uint8_t> result(length);
122*6777b538SAndroid Build Coastguard Worker   if (result.size()) {
123*6777b538SAndroid Build Coastguard Worker     RandBytes(result);
124*6777b538SAndroid Build Coastguard Worker   }
125*6777b538SAndroid Build Coastguard Worker   return result;
126*6777b538SAndroid Build Coastguard Worker }
127*6777b538SAndroid Build Coastguard Worker 
InsecureRandomGenerator()128*6777b538SAndroid Build Coastguard Worker InsecureRandomGenerator::InsecureRandomGenerator() {
129*6777b538SAndroid Build Coastguard Worker   a_ = base::RandUint64();
130*6777b538SAndroid Build Coastguard Worker   b_ = base::RandUint64();
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker 
ReseedForTesting(uint64_t seed)133*6777b538SAndroid Build Coastguard Worker void InsecureRandomGenerator::ReseedForTesting(uint64_t seed) {
134*6777b538SAndroid Build Coastguard Worker   a_ = seed;
135*6777b538SAndroid Build Coastguard Worker   b_ = seed;
136*6777b538SAndroid Build Coastguard Worker }
137*6777b538SAndroid Build Coastguard Worker 
RandUint64()138*6777b538SAndroid Build Coastguard Worker uint64_t InsecureRandomGenerator::RandUint64() {
139*6777b538SAndroid Build Coastguard Worker   // Using XorShift128+, which is simple and widely used. See
140*6777b538SAndroid Build Coastguard Worker   // https://en.wikipedia.org/wiki/Xorshift#xorshift+ for details.
141*6777b538SAndroid Build Coastguard Worker   uint64_t t = a_;
142*6777b538SAndroid Build Coastguard Worker   const uint64_t s = b_;
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker   a_ = s;
145*6777b538SAndroid Build Coastguard Worker   t ^= t << 23;
146*6777b538SAndroid Build Coastguard Worker   t ^= t >> 17;
147*6777b538SAndroid Build Coastguard Worker   t ^= s ^ (s >> 26);
148*6777b538SAndroid Build Coastguard Worker   b_ = t;
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker   return t + s;
151*6777b538SAndroid Build Coastguard Worker }
152*6777b538SAndroid Build Coastguard Worker 
RandUint32()153*6777b538SAndroid Build Coastguard Worker uint32_t InsecureRandomGenerator::RandUint32() {
154*6777b538SAndroid Build Coastguard Worker   // The generator usually returns an uint64_t, truncate it.
155*6777b538SAndroid Build Coastguard Worker   //
156*6777b538SAndroid Build Coastguard Worker   // It is noted in this paper (https://arxiv.org/abs/1810.05313) that the
157*6777b538SAndroid Build Coastguard Worker   // lowest 32 bits fail some statistical tests from the Big Crush
158*6777b538SAndroid Build Coastguard Worker   // suite. Use the higher ones instead.
159*6777b538SAndroid Build Coastguard Worker   return this->RandUint64() >> 32;
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker 
RandDouble()162*6777b538SAndroid Build Coastguard Worker double InsecureRandomGenerator::RandDouble() {
163*6777b538SAndroid Build Coastguard Worker   uint64_t x = RandUint64();
164*6777b538SAndroid Build Coastguard Worker   // From https://vigna.di.unimi.it/xorshift/.
165*6777b538SAndroid Build Coastguard Worker   // 53 bits of mantissa, hence the "hexadecimal exponent" 1p-53.
166*6777b538SAndroid Build Coastguard Worker   return (x >> 11) * 0x1.0p-53;
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker 
169*6777b538SAndroid Build Coastguard Worker MetricsSubSampler::MetricsSubSampler() = default;
ShouldSample(double probability)170*6777b538SAndroid Build Coastguard Worker bool MetricsSubSampler::ShouldSample(double probability) {
171*6777b538SAndroid Build Coastguard Worker   if (g_subsampling_always_sample.load(std::memory_order_relaxed)) {
172*6777b538SAndroid Build Coastguard Worker     return true;
173*6777b538SAndroid Build Coastguard Worker   }
174*6777b538SAndroid Build Coastguard Worker   if (g_subsampling_never_sample.load(std::memory_order_relaxed)) {
175*6777b538SAndroid Build Coastguard Worker     return false;
176*6777b538SAndroid Build Coastguard Worker   }
177*6777b538SAndroid Build Coastguard Worker 
178*6777b538SAndroid Build Coastguard Worker   return generator_.RandDouble() < probability;
179*6777b538SAndroid Build Coastguard Worker }
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker MetricsSubSampler::ScopedAlwaysSampleForTesting::
ScopedAlwaysSampleForTesting()182*6777b538SAndroid Build Coastguard Worker     ScopedAlwaysSampleForTesting() {
183*6777b538SAndroid Build Coastguard Worker   DCHECK(!g_subsampling_always_sample.load(std::memory_order_relaxed));
184*6777b538SAndroid Build Coastguard Worker   DCHECK(!g_subsampling_never_sample.load(std::memory_order_relaxed));
185*6777b538SAndroid Build Coastguard Worker   g_subsampling_always_sample.store(true, std::memory_order_relaxed);
186*6777b538SAndroid Build Coastguard Worker }
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker MetricsSubSampler::ScopedAlwaysSampleForTesting::
~ScopedAlwaysSampleForTesting()189*6777b538SAndroid Build Coastguard Worker     ~ScopedAlwaysSampleForTesting() {
190*6777b538SAndroid Build Coastguard Worker   DCHECK(g_subsampling_always_sample.load(std::memory_order_relaxed));
191*6777b538SAndroid Build Coastguard Worker   DCHECK(!g_subsampling_never_sample.load(std::memory_order_relaxed));
192*6777b538SAndroid Build Coastguard Worker   g_subsampling_always_sample.store(false, std::memory_order_relaxed);
193*6777b538SAndroid Build Coastguard Worker }
194*6777b538SAndroid Build Coastguard Worker 
ScopedNeverSampleForTesting()195*6777b538SAndroid Build Coastguard Worker MetricsSubSampler::ScopedNeverSampleForTesting::ScopedNeverSampleForTesting() {
196*6777b538SAndroid Build Coastguard Worker   DCHECK(!g_subsampling_always_sample.load(std::memory_order_relaxed));
197*6777b538SAndroid Build Coastguard Worker   DCHECK(!g_subsampling_never_sample.load(std::memory_order_relaxed));
198*6777b538SAndroid Build Coastguard Worker   g_subsampling_never_sample.store(true, std::memory_order_relaxed);
199*6777b538SAndroid Build Coastguard Worker }
200*6777b538SAndroid Build Coastguard Worker 
~ScopedNeverSampleForTesting()201*6777b538SAndroid Build Coastguard Worker MetricsSubSampler::ScopedNeverSampleForTesting::~ScopedNeverSampleForTesting() {
202*6777b538SAndroid Build Coastguard Worker   DCHECK(!g_subsampling_always_sample);
203*6777b538SAndroid Build Coastguard Worker   DCHECK(g_subsampling_never_sample);
204*6777b538SAndroid Build Coastguard Worker   g_subsampling_never_sample.store(false, std::memory_order_relaxed);
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker }  // namespace base
208