File: Random.h

package info (click to toggle)
freeorion 0.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 194,940 kB
  • sloc: cpp: 186,508; python: 40,969; ansic: 1,164; xml: 719; makefile: 32; sh: 7
file content (123 lines) | stat: -rw-r--r-- 4,478 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#ifndef _Random_h_
#define _Random_h_

#if defined(_MSC_VER) && defined(int64_t)
#undef int64_t
#endif

#include <array>
#include <random>
#include <ctime>

#include "Export.h"

/** \file
 *
 * A collection of robust and portable random number generation functions that
 * share an underlying random generator and which are guarded with locks for
 * thread safety.
 */

/** seeds the underlying random number generator used to drive all random number distributions */
FO_COMMON_API void Seed(unsigned int seed);

/** seeds the underlying random number generator used to drive all random number distributions with
    the current clock time */
FO_COMMON_API void ClockSeed();

namespace RandomImpl {
    static constexpr uint16_t counter_val =
#if defined(__COUNTER__)
        __COUNTER__ % 8;
#else
        1;
#endif

    // convert time as string like "23:59:59" to an int
    inline consteval uint32_t TimeToInt(std::array<char, 9> t) noexcept
    { return ((t[7]-'0') + 10*(t[6]-'0')) + 60*((t[4]-'0') + 10*(t[3]-'0')) + 3600*((t[1]-'0') + 10*(t[0]-'0')); }

    // shuffle bits in number
    inline consteval uint32_t hash(auto val_in) {
        auto val = static_cast<uint32_t>(val_in);
        val ^= 0x5A5C3AF5;

        // copied from Boost "hash_mix for 32 bit size_t"
        constexpr uint32_t m1 = 0x21f0aaad;
        constexpr uint32_t m2 = 0x735a2d97;
        val ^= val >> 16;
        val *= m1;
        val ^= val >> 15;
        val *= m2;
        val ^= val >> 15;

        return val;
    }
    // generate a compile-time PRNG int that is seeded differently for each second of the day.
    // \a n indicates which value for the current seed to return.
    inline consteval uint32_t CxPRNG(int16_t n = counter_val, std::array<char, 9> seed = std::array<char, 9>{__TIME__}) {
        uint32_t retval{TimeToInt(seed)};
        for (; n > 0; --n)
            retval = hash(retval);
        return retval;
    }
}

/** returns an int from a uniform distribution of integers in the range [\a min, \a max]; */
FO_COMMON_API int RandInt(int min, int max);

/** compile-time "random" time-seeded int from uniform distribution in the range [\a min, \a max] */
inline consteval int32_t RandIntCx(const int32_t min, const int32_t max,
                                   const int16_t n = RandomImpl::counter_val) noexcept
{
    if (min >= max)
        return min;
    const auto range = static_cast<uint32_t>(max - min);
    const auto val_in_range = RandomImpl::CxPRNG(n) % (range + 1);
    return min + static_cast<int32_t>(val_in_range);
}
inline consteval int32_t RandIntCx(const int32_t min, const int32_t max, const int16_t n,
                                   const std::array<char, 9> seed = std::array<char, 9>{__TIME__}) noexcept
{
    if (min >= max)
        return min;
    const auto range = static_cast<uint32_t>(max - min);
    const auto val_in_range = RandomImpl::CxPRNG(n, seed) % (range + 1);
    return min + static_cast<int32_t>(val_in_range);
}
inline consteval bool RandBoolCx(int16_t n = RandomImpl::counter_val) noexcept
{ return RandomImpl::CxPRNG(n) % 2 == 0; }

/** returns a double from a uniform distribution of doubles in the range [0.0, 1.0) */
FO_COMMON_API double RandZeroToOne();

/** compile-time random double from nearly-uniform distribution in the range [0.0, 1.0);
  * \a n indicates which value in the distribution to return. */
inline consteval double RandZeroToOneCx(int16_t n = 4) noexcept {
    const uint32_t arbitrary_prime = 31397;
    const auto val = RandomImpl::CxPRNG(n) % arbitrary_prime;
    return static_cast<double>(val) / arbitrary_prime;
}

/** returns a double from a uniform distribution of doubles in the range [\a min, \a max) */
FO_COMMON_API double RandDouble(double min, double max);

/** compile-time random double from nearly-uniform distribution in the range [min, max);
  * \a n indicates which value in the distribution to return. */
inline consteval double RandDoubleCx(double min, double max, int16_t n = 5) noexcept {
    if (min >= max)
        return min;
    const auto range = max - min;
    return min + RandZeroToOneCx(n)*range;
}

/** returns a double from a Gaussian (normal) distribution of doubles centered around \a mean,
    with standard deviation \a sigma */
FO_COMMON_API double RandGaussian(double mean, double sigma);

/** shuffles contents of container */
FO_COMMON_API void RandomShuffle(std::vector<uint8_t>& c);
FO_COMMON_API void RandomShuffle(std::vector<int>& c);


#endif