blob: 7b290f4e4993a9f293ecbc4b465b9e1a54260285 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2011 The Chromium Authors
[email protected]05f9b682008-09-29 22:18:012// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/rand_util.h"
6
avi9b6f42932015-12-26 22:15:147#include <limits.h>
[email protected]05f9b682008-09-29 22:18:018#include <math.h>
tfarina32089922015-05-18 22:14:099#include <stdint.h>
[email protected]94a0f312008-09-30 14:26:3310
John Chen87cc25c2018-04-20 22:49:4911#include <algorithm>
12#include <limits>
13
Hans Wennborgc3cffa62020-04-27 10:09:1214#include "base/check_op.h"
[email protected]c851cfd2013-06-10 20:11:1415#include "base/strings/string_util.h"
Peter Kastingf18c8ca2023-10-04 16:31:5116#include "base/time/time.h"
[email protected]05f9b682008-09-29 22:18:0117
[email protected]05f9b682008-09-29 22:18:0118namespace base {
19
François Doray87e35a82023-05-05 14:44:2820namespace {
21
22bool g_subsampling_enabled = true;
23
24} // namespace
25
John Mellorafab972d2017-09-26 16:28:1926uint64_t RandUint64() {
27 uint64_t number;
28 RandBytes(&number, sizeof(number));
29 return number;
30}
31
[email protected]05f9b682008-09-29 22:18:0132int RandInt(int min, int max) {
[email protected]d7a93ad2011-04-22 13:13:0733 DCHECK_LE(min, max);
[email protected]05f9b682008-09-29 22:18:0134
Peter Kasting28b51cf2022-06-28 15:02:4335 uint64_t range = static_cast<uint64_t>(max) - static_cast<uint64_t>(min) + 1;
John Chen87cc25c2018-04-20 22:49:4936 // |range| is at most UINT_MAX + 1, so the result of RandGenerator(range)
37 // is at most UINT_MAX. Hence it's safe to cast it from uint64_t to int64_t.
38 int result =
39 static_cast<int>(min + static_cast<int64_t>(base::RandGenerator(range)));
[email protected]e1be56d2011-05-04 01:29:3840 DCHECK_GE(result, min);
41 DCHECK_LE(result, max);
[email protected]05f9b682008-09-29 22:18:0142 return result;
43}
44
45double RandDouble() {
[email protected]edafd4c2011-05-10 17:18:5346 return BitsToOpenEndedUnitInterval(base::RandUint64());
47}
48
Avery Musbacheff342b2022-10-06 18:36:0749float RandFloat() {
50 return BitsToOpenEndedUnitIntervalF(base::RandUint64());
51}
52
Peter Kastingf18c8ca2023-10-04 16:31:5153TimeDelta RandTimeDelta(TimeDelta start, TimeDelta limit) {
54 // We must have a finite, non-empty, non-reversed interval.
55 CHECK_LT(start, limit);
56 CHECK(!start.is_min());
57 CHECK(!limit.is_max());
58
59 const int64_t range = (limit - start).InMicroseconds();
60 // Because of the `CHECK_LT()` above, range > 0, so this cast is safe.
61 const uint64_t delta_us = base::RandGenerator(static_cast<uint64_t>(range));
62 // ...and because `range` fit in an `int64_t`, so will `delta_us`.
63 return start + Microseconds(static_cast<int64_t>(delta_us));
64}
65
66TimeDelta RandTimeDeltaUpTo(TimeDelta limit) {
67 return RandTimeDelta(TimeDelta(), limit);
68}
69
Nico Weber0a3852a72015-10-29 20:42:5870double BitsToOpenEndedUnitInterval(uint64_t bits) {
[email protected]94a0f312008-09-30 14:26:3371 // We try to get maximum precision by masking out as many bits as will fit
72 // in the target type's mantissa, and raising it to an appropriate power to
73 // produce output in the range [0, 1). For IEEE 754 doubles, the mantissa
Avery Musbach92a30e382022-09-08 23:30:4174 // is expected to accommodate 53 bits (including the implied bit).
avi4ec0dff2015-11-24 14:26:2475 static_assert(std::numeric_limits<double>::radix == 2,
76 "otherwise use scalbn");
Avery Musbach92a30e382022-09-08 23:30:4177 constexpr int kBits = std::numeric_limits<double>::digits;
78 return ldexp(bits & ((UINT64_C(1) << kBits) - 1u), -kBits);
[email protected]05f9b682008-09-29 22:18:0179}
80
Avery Musbacheff342b2022-10-06 18:36:0781float BitsToOpenEndedUnitIntervalF(uint64_t bits) {
82 // We try to get maximum precision by masking out as many bits as will fit
83 // in the target type's mantissa, and raising it to an appropriate power to
84 // produce output in the range [0, 1). For IEEE 754 floats, the mantissa is
85 // expected to accommodate 12 bits (including the implied bit).
86 static_assert(std::numeric_limits<float>::radix == 2, "otherwise use scalbn");
87 constexpr int kBits = std::numeric_limits<float>::digits;
88 return ldexpf(bits & ((UINT64_C(1) << kBits) - 1u), -kBits);
89}
90
Nico Weber0a3852a72015-10-29 20:42:5891uint64_t RandGenerator(uint64_t range) {
[email protected]0173b962011-08-24 19:58:3692 DCHECK_GT(range, 0u);
[email protected]af2e192b2011-05-30 17:39:0993 // We must discard random results above this number, as they would
94 // make the random generator non-uniform (consider e.g. if
[email protected]0173b962011-08-24 19:58:3695 // MAX_UINT64 was 7 and |range| was 5, then a result of 1 would be twice
96 // as likely as a result of 3 or 4).
Nico Weber0a3852a72015-10-29 20:42:5897 uint64_t max_acceptable_value =
98 (std::numeric_limits<uint64_t>::max() / range) * range - 1;
[email protected]af2e192b2011-05-30 17:39:0999
Nico Weber0a3852a72015-10-29 20:42:58100 uint64_t value;
[email protected]af2e192b2011-05-30 17:39:09101 do {
102 value = base::RandUint64();
[email protected]0173b962011-08-24 19:58:36103 } while (value > max_acceptable_value);
[email protected]af2e192b2011-05-30 17:39:09104
[email protected]0173b962011-08-24 19:58:36105 return value % range;
[email protected]a74dcae2010-08-30 21:07:05106}
107
[email protected]51a01812011-05-05 08:46:11108std::string RandBytesAsString(size_t length) {
[email protected]fdce4782011-11-29 20:06:18109 DCHECK_GT(length, 0u);
[email protected]51a01812011-05-05 08:46:11110 std::string result;
111 RandBytes(WriteInto(&result, length + 1), length);
[email protected]29548d82011-04-29 21:03:54112 return result;
113}
114
Tom Sepez230a75c62023-11-13 23:27:16115std::vector<uint8_t> RandBytesAsVector(size_t length) {
116 std::vector<uint8_t> result(length);
117 if (result.size()) {
118 RandBytes(result.data(), result.size());
119 }
120 return result;
121}
122
Benoit Lize7532d4af2021-08-24 11:34:04123InsecureRandomGenerator::InsecureRandomGenerator() {
Benoit Lize73de21b2021-07-02 08:17:56124 a_ = base::RandUint64();
125 b_ = base::RandUint64();
Benoit Lize73de21b2021-07-02 08:17:56126}
127
Benoit Lize7532d4af2021-08-24 11:34:04128void InsecureRandomGenerator::ReseedForTesting(uint64_t seed) {
Benoit Lize73de21b2021-07-02 08:17:56129 a_ = seed;
130 b_ = seed;
Benoit Lize73de21b2021-07-02 08:17:56131}
132
133uint64_t InsecureRandomGenerator::RandUint64() {
Benoit Lize73de21b2021-07-02 08:17:56134 // Using XorShift128+, which is simple and widely used. See
135 // https://en.wikipedia.org/wiki/Xorshift#xorshift+ for details.
136 uint64_t t = a_;
137 const uint64_t s = b_;
138
139 a_ = s;
140 t ^= t << 23;
141 t ^= t >> 17;
142 t ^= s ^ (s >> 26);
143 b_ = t;
144
145 return t + s;
146}
147
148uint32_t InsecureRandomGenerator::RandUint32() {
149 // The generator usually returns an uint64_t, truncate it.
150 //
151 // It is noted in this paper (https://arxiv.org/abs/1810.05313) that the
152 // lowest 32 bits fail some statistical tests from the Big Crush
153 // suite. Use the higher ones instead.
154 return this->RandUint64() >> 32;
155}
156
Benoit Lized6377142021-07-05 10:17:16157double InsecureRandomGenerator::RandDouble() {
158 uint64_t x = RandUint64();
159 // From https://vigna.di.unimi.it/xorshift/.
160 // 53 bits of mantissa, hence the "hexadecimal exponent" 1p-53.
161 return (x >> 11) * 0x1.0p-53;
162}
163
Benoit Lizeee4fe1e42022-06-29 19:13:48164MetricsSubSampler::MetricsSubSampler() = default;
165bool MetricsSubSampler::ShouldSample(double probability) {
François Doray87e35a82023-05-05 14:44:28166 return !g_subsampling_enabled || generator_.RandDouble() < probability;
167}
168
169MetricsSubSampler::ScopedDisableForTesting::ScopedDisableForTesting() {
170 DCHECK(g_subsampling_enabled);
171 g_subsampling_enabled = false;
172}
173
174MetricsSubSampler::ScopedDisableForTesting::~ScopedDisableForTesting() {
175 DCHECK(!g_subsampling_enabled);
176 g_subsampling_enabled = true;
Benoit Lizeee4fe1e42022-06-29 19:13:48177}
178
[email protected]05f9b682008-09-29 22:18:01179} // namespace base