blob: 5881ef25e391083127ed6087638adf3c42ac3e58 [file] [log] [blame]
[email protected]d7a93ad2011-04-22 13:13:071// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[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]05f9b682008-09-29 22:18:0110
[email protected]c56bef4d2013-10-15 20:29:0311#include <algorithm>
[email protected]94a0f312008-09-30 14:26:3312#include <limits>
13
[email protected]05f9b682008-09-29 22:18:0114#include "base/logging.h"
[email protected]c851cfd2013-06-10 20:11:1415#include "base/strings/string_util.h"
[email protected]05f9b682008-09-29 22:18:0116
[email protected]05f9b682008-09-29 22:18:0117namespace base {
18
John Mellorafab9722017-09-26 16:28:1919uint64_t RandUint64() {
20 uint64_t number;
21 RandBytes(&number, sizeof(number));
22 return number;
23}
24
[email protected]05f9b682008-09-29 22:18:0125int RandInt(int min, int max) {
[email protected]d7a93ad2011-04-22 13:13:0726 DCHECK_LE(min, max);
[email protected]05f9b682008-09-29 22:18:0127
Nico Weber0a3852a72015-10-29 20:42:5828 uint64_t range = static_cast<uint64_t>(max) - min + 1;
29 // |range| is at most UINT_MAX + 1, so the result of RandGenerator(range)
30 // is at most UINT_MAX. Hence it's safe to cast it from uint64_t to int64_t.
31 int result =
32 static_cast<int>(min + static_cast<int64_t>(base::RandGenerator(range)));
[email protected]e1be56d2011-05-04 01:29:3833 DCHECK_GE(result, min);
34 DCHECK_LE(result, max);
[email protected]05f9b682008-09-29 22:18:0135 return result;
36}
37
38double RandDouble() {
[email protected]edafd4c2011-05-10 17:18:5339 return BitsToOpenEndedUnitInterval(base::RandUint64());
40}
41
Nico Weber0a3852a72015-10-29 20:42:5842double BitsToOpenEndedUnitInterval(uint64_t bits) {
[email protected]94a0f312008-09-30 14:26:3343 // We try to get maximum precision by masking out as many bits as will fit
44 // in the target type's mantissa, and raising it to an appropriate power to
45 // produce output in the range [0, 1). For IEEE 754 doubles, the mantissa
46 // is expected to accommodate 53 bits.
[email protected]05f9b682008-09-29 22:18:0147
avi4ec0dff2015-11-24 14:26:2448 static_assert(std::numeric_limits<double>::radix == 2,
49 "otherwise use scalbn");
[email protected]94a0f312008-09-30 14:26:3350 static const int kBits = std::numeric_limits<double>::digits;
Nico Weber0a3852a72015-10-29 20:42:5851 uint64_t random_bits = bits & ((UINT64_C(1) << kBits) - 1);
[email protected]94a0f312008-09-30 14:26:3352 double result = ldexp(static_cast<double>(random_bits), -1 * kBits);
[email protected]e1be56d2011-05-04 01:29:3853 DCHECK_GE(result, 0.0);
54 DCHECK_LT(result, 1.0);
[email protected]05f9b682008-09-29 22:18:0155 return result;
56}
57
Nico Weber0a3852a72015-10-29 20:42:5858uint64_t RandGenerator(uint64_t range) {
[email protected]0173b962011-08-24 19:58:3659 DCHECK_GT(range, 0u);
[email protected]af2e192b2011-05-30 17:39:0960 // We must discard random results above this number, as they would
61 // make the random generator non-uniform (consider e.g. if
[email protected]0173b962011-08-24 19:58:3662 // MAX_UINT64 was 7 and |range| was 5, then a result of 1 would be twice
63 // as likely as a result of 3 or 4).
Nico Weber0a3852a72015-10-29 20:42:5864 uint64_t max_acceptable_value =
65 (std::numeric_limits<uint64_t>::max() / range) * range - 1;
[email protected]af2e192b2011-05-30 17:39:0966
Nico Weber0a3852a72015-10-29 20:42:5867 uint64_t value;
[email protected]af2e192b2011-05-30 17:39:0968 do {
69 value = base::RandUint64();
[email protected]0173b962011-08-24 19:58:3670 } while (value > max_acceptable_value);
[email protected]af2e192b2011-05-30 17:39:0971
[email protected]0173b962011-08-24 19:58:3672 return value % range;
[email protected]a74dcae2010-08-30 21:07:0573}
74
[email protected]51a01812011-05-05 08:46:1175std::string RandBytesAsString(size_t length) {
[email protected]fdce4782011-11-29 20:06:1876 DCHECK_GT(length, 0u);
[email protected]51a01812011-05-05 08:46:1177 std::string result;
78 RandBytes(WriteInto(&result, length + 1), length);
[email protected]29548d82011-04-29 21:03:5479 return result;
80}
81
[email protected]05f9b682008-09-29 22:18:0182} // namespace base