Coverage Report

Created: 2024-11-22 21:49

/root/doris/be/src/util/random.h
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <stdint.h>
21
22
namespace doris {
23
24
// A very simple random number generator.  Not especially good at
25
// generating truly random bits, but good enough for our needs in this
26
// package.
27
class Random {
28
private:
29
    uint32_t seed_;
30
31
public:
32
14
    explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) {
33
        // Avoid bad seeds.
34
14
        if (seed_ == 0 || seed_ == 2147483647L) {
35
0
            seed_ = 1;
36
0
        }
37
14
    }
38
20.2k
    uint32_t Next() {
39
20.2k
        static const uint32_t M = 2147483647L; // 2^31-1
40
20.2k
        static const uint64_t A = 16807;       // bits 14, 8, 7, 5, 2, 1, 0
41
        // We are computing
42
        //       seed_ = (seed_ * A) % M,    where M = 2^31-1
43
        //
44
        // seed_ must not be zero or M, or else all subsequent computed values
45
        // will be zero or M respectively.  For all other values, seed_ will end
46
        // up cycling through every number in [1,M-1]
47
20.2k
        uint64_t product = seed_ * A;
48
49
        // Compute (product % M) using the fact that ((x << 31) % M) == x.
50
20.2k
        seed_ = static_cast<uint32_t>((product >> 31) + (product & M));
51
        // The first reduction may overflow by 1 bit, so we may need to
52
        // repeat.  mod == M is not possible; using > allows the faster
53
        // sign-bit-based test.
54
20.2k
        if (seed_ > M) {
55
0
            seed_ -= M;
56
0
        }
57
20.2k
        return seed_;
58
20.2k
    }
59
    // Returns a uniformly distributed value in the range [0..n-1]
60
    // REQUIRES: n > 0
61
9.89k
    uint32_t Uniform(int n) { return Next() % n; }
62
63
    // Randomly returns true ~"1/n" of the time, and false otherwise.
64
    // REQUIRES: n > 0
65
0
    bool OneIn(int n) { return (Next() % n) == 0; }
66
67
    // Skewed: pick "base" uniformly from range [0,max_log] and then
68
    // return "base" random bits.  The effect is to pick a number in the
69
    // range [0,2^max_log-1] with exponential bias towards smaller numbers.
70
0
    uint32_t Skewed(int max_log) { return Uniform(1 << Uniform(max_log + 1)); }
71
};
72
73
} // namespace doris