1
1
/* ***************************************************************************
2
- Copyright (c) 2012 cocos2d-x.org
3
- Copyright (c) 2013-2016 Chukong Technologies Inc.
4
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
5
2
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
6
3
7
4
https://axmol.dev/
28
25
#ifndef __FAST_RNG_H__
29
26
#define __FAST_RNG_H__
30
27
28
+ #include " math/MathBase.h"
29
+ #include < type_traits>
30
+ #include < stdint.h>
31
+
32
+ NS_AX_MATH_BEGIN
33
+
31
34
/* * A fast more effective seeded random number generator struct, uses xoshiro128**.
32
35
* It uses a simple algorithm to improve the speed of generating random numbers with a decent quality,
33
36
* Use this if you're planning to generate large amounts of random numbers in a single frame.
36
39
*/
37
40
struct FastRNG
38
41
{
42
+ private:
39
43
uint32_t s[4 ];
40
44
41
45
// SplitMix64 implementation, doesn't modify any state for this instance
42
46
// but it is used to seed xoshiro128** state
43
- uint64_t nextSeed (uint64_t & state)
47
+ static inline uint64_t nextSeed (uint64_t & state)
44
48
{
45
49
uint64_t z = (state += 0x9e3779b97f4a7c15 );
46
50
z = (z ^ (z >> 30 )) * 0xbf58476d1ce4e5b9 ;
47
51
z = (z ^ (z >> 27 )) * 0x94d049bb133111eb ;
48
52
return z ^ (z >> 31 );
49
53
}
50
54
55
+ // returns a copy of x rotated k bits to the left
56
+ static inline uint32_t rotL (const uint32_t x, int k) { return (x << k) | (x >> (32 - k)); }
57
+
58
+ // generates a random integer from 0 to max exclusive that is uniformly distributed using fastrange algorithm
59
+ uint32_t nextMax (uint32_t max)
60
+ {
61
+ uint64_t multiresult = static_cast <uint64_t >(next ()) * max;
62
+ uint32_t leftover = static_cast <uint32_t >(multiresult);
63
+ if (leftover < max)
64
+ {
65
+ uint32_t threshold = (0 - max) % max;
66
+ while (leftover < threshold)
67
+ {
68
+ multiresult = static_cast <uint64_t >(next ()) * max;
69
+ leftover = static_cast <uint32_t >(multiresult);
70
+ }
71
+ }
72
+ return multiresult >> 32 ;
73
+ }
74
+
75
+ public:
51
76
FastRNG () { seed (static_cast <uint64_t >(rand ()) << 32 | rand ()); }
77
+ FastRNG (uint64_t _seed) { seed (_seed); }
52
78
53
79
// there is no need to seed this instance of FastRNG
54
- // because it has already been seeded with rand() by constructor
80
+ // because it's already been seeded with rand() in constructor
55
81
// you can override the seed by giving your own 64-bit seed
56
82
void seed (uint64_t seed)
57
83
{
58
84
uint64_t state = seed;
59
85
uint64_t states[2 ];
60
86
memset (states, 0 , 16 );
61
- states[0 ] = nextSeed (state);
62
- states[1 ] = nextSeed (state);
87
+ states[0 ] = FastRNG:: nextSeed (state);
88
+ states[1 ] = FastRNG:: nextSeed (state);
63
89
memcpy (s, states, 16 );
64
90
}
65
91
66
- // returns a copy of x rotated k bits to the left
67
- static inline uint32_t rotL (const uint32_t x, int k) { return (x << k) | (x >> (32 - k)); }
68
-
69
92
// steps once into the state, returns a random from 0 to UINT32_MAX
70
93
uint32_t next ()
71
94
{
@@ -89,11 +112,12 @@ struct FastRNG
89
112
template <typename T>
90
113
T nextReal ()
91
114
{
92
- if (std::is_same<T, float >::value)
115
+ if constexpr (std::is_same<T, float >::value)
93
116
return static_cast <T>(next () >> 8 ) * 0x1 .0p-24f ;
94
- else if (std::is_same<T, double >::value)
117
+ else if constexpr (std::is_same<T, double >::value)
95
118
return static_cast <T>((static_cast <uint64_t >(next ()) << 32 | next ()) >> 11 ) * 0x1 .0p-53 ;
96
- return 0 ; // possibly assert?
119
+ else
120
+ AXASSERT (false , " datatype not implemented." );
97
121
}
98
122
99
123
// generates a random real that ranges from min to max
@@ -110,23 +134,6 @@ struct FastRNG
110
134
return min + static_cast <T>(nextMax (static_cast <uint32_t >(max - min)));
111
135
}
112
136
113
- // generates a random integer from 0 to max exclusive that is uniformly distributed using fastrange algorithm
114
- uint32_t nextMax (uint32_t max)
115
- {
116
- uint64_t multiresult = static_cast <uint64_t >(next ()) * max;
117
- uint32_t leftover = static_cast <uint32_t >(multiresult);
118
- if (leftover < max)
119
- {
120
- uint32_t threshold = (0 - max) % max;
121
- while (leftover < threshold)
122
- {
123
- multiresult = static_cast <uint64_t >(next ()) * max;
124
- leftover = static_cast <uint32_t >(multiresult);
125
- }
126
- }
127
- return multiresult >> 32 ;
128
- }
129
-
130
137
// wrapper for nextInt<int32_t>(min, max)
131
138
int32_t range (int32_t min, int32_t max) { return nextInt<int32_t >(min, max); }
132
139
// wrapper for nextInt<int32_t>(0, max)
@@ -150,9 +157,11 @@ struct FastRNG
150
157
// wrapper for nextReal<float>()
151
158
float float01 () { return nextReal<float >(); }
152
159
// wrapper for nextReal<double>()
153
- float double01 () { return nextReal<double >(); }
160
+ double double01 () { return nextReal<double >(); }
154
161
// wrapper for next() & 1, true or false based on LSB
155
- float bool01 () { return next () & 1 ; }
162
+ bool bool01 () { return static_cast < bool >( next () & 1 ) ; }
156
163
};
157
164
165
+ NS_AX_MATH_END
166
+
158
167
#endif // __FAST_RNG_H__
0 commit comments