24
24
| Shawn Cokus <Cokus@math.washington.edu> |
25
25
| David Blackman |
26
26
| Sebastiano Vigna <vigna@acm.org> |
27
+ | Melissa O'Neill <oneill@pcg-random.org> |
27
28
+----------------------------------------------------------------------+
28
29
*/
29
30
#ifndef PHP_RANDOM_H
85
86
# define php_random_int_silent (min , max , result ) \
86
87
php_random_int((min), (max), (result), 0)
87
88
89
+ # if !defined(__SIZEOF_INT128__ ) || defined(FORCE_EMULATE_128 )
90
+ # define RANDOM_PCG64_EMULATED
91
+ typedef struct _random_uint128_t {
92
+ uint64_t hi ;
93
+ uint64_t lo ;
94
+ } random_uint128_t ;
95
+ # define UINT128_HI64 (value ) value.hi;
96
+ # define UINT128_LO64 (value ) value.lo;
97
+ # define UINT128_CON (x , y , result ) \
98
+ do { \
99
+ result.hi = x; \
100
+ result.lo = y; \
101
+ } while (0);
102
+ # define UINT128_ADD (x , y , result ) \
103
+ do { \
104
+ const uint64_t _lo = (x.lo + y.lo), _hi = (x.hi + y.hi + (_lo < x.lo)); \
105
+ result.hi = _hi; \
106
+ result.lo = _lo; \
107
+ } while (0);
108
+ # define UINT128_MUL (x , y , result ) \
109
+ do { \
110
+ const uint64_t \
111
+ _x0 = x.lo & 0xffffffffULL, \
112
+ _x1 = x.lo >> 32, \
113
+ _y0 = y.lo & 0xffffffffULL, \
114
+ _y1 = y.lo >> 32, \
115
+ _z0 = ((_x1 * _y0 + (_x0 * _y0 >> 32)) & 0xffffffffULL) + _x0 * _y1; \
116
+ result.hi = x.hi * y.lo + x.lo * y.hi; \
117
+ result.lo = x.lo * y.lo; \
118
+ result.hi += _x1 * _y1 + ((_x1 * _y0 + (_x0 * _y0 >> 32)) >> 32) + (_z0 >> 32); \
119
+ } while (0);
120
+ # define PCG64_ROTL1OR1 (x , result ) \
121
+ do { \
122
+ result.hi = x.hi << 1U | x.lo >> 63U; \
123
+ result.lo = x.lo << 1U | 1U; \
124
+ } while (0);
125
+ # define PCG64_ROTR64 (x , result ) \
126
+ do { \
127
+ const uint64_t _v = (x.hi ^ x.lo), _s = x.hi >> 58U; \
128
+ result = (_v >> _s) | (_v << ((-_s) & 63)); \
129
+ } while (0);
130
+ # else
131
+ typedef __uint128_t random_uint128_t ;
132
+ # define UINT128_HI64 (value ) (uint64_t) (value >> 64);
133
+ # define UINT128_LO64 (value ) (uint64_t) value;
134
+ # define UINT128_CON (x , y , result ) result = (((random_uint128_t) x << 64) + y);
135
+ # define UINT128_ADD (x , y , result ) result = x + y;
136
+ # define UINT128_MUL (x , y , result ) result = x * y;
137
+ # define PCG64_ROTL1OR1 (x , result ) result = (x << 1U) | 1U;
138
+ # define PCG64_ROTR64 (x , result ) \
139
+ do { \
140
+ uint64_t _v = ((uint64_t) (x >> 64U)) ^ (uint64_t) x, _s = x >> 122U; \
141
+ result = (_v >> _s) | (_v << ((-_s) & 63)); \
142
+ } while (0);
143
+ # endif
144
+
88
145
# define RANDOM_ENGINE_GENERATE (algo , state , result , generated_size , rng_unsafe ) \
89
146
do { \
90
147
result = algo->generate(state, rng_unsafe); \
@@ -132,15 +189,19 @@ extern PHPAPI zend_class_entry *random_ce_Random_SeedableEngine;
132
189
extern PHPAPI zend_class_entry * random_ce_Random_SerializableEngine ;
133
190
134
191
extern PHPAPI zend_class_entry * random_ce_Random_Engine_CombinedLCG ;
192
+ extern PHPAPI zend_class_entry * random_ce_Random_Engine_PCG64 ;
135
193
extern PHPAPI zend_class_entry * random_ce_Random_Engine_MersenneTwister ;
136
194
extern PHPAPI zend_class_entry * random_ce_Random_Engine_Secure ;
195
+ extern PHPAPI zend_class_entry * random_ce_Random_Engine_XorShift128Plus ;
137
196
extern PHPAPI zend_class_entry * random_ce_Random_Engine_Xoshiro256StarStar ;
138
197
extern PHPAPI zend_class_entry * random_ce_Random_Randomizer ;
139
198
140
199
extern const php_random_engine_algo php_random_engine_algo_combinedlcg ;
141
200
extern const php_random_engine_algo php_random_engine_algo_mersennetwister ;
201
+ extern const php_random_engine_algo php_random_engine_algo_pcg64 ;
142
202
extern const php_random_engine_algo php_random_engine_algo_secure ;
143
203
extern const php_random_engine_algo php_random_engine_algo_user ;
204
+ extern const php_random_engine_algo php_random_engine_algo_xorshift128plus ;
144
205
extern const php_random_engine_algo php_random_engine_algo_xoshiro256starstar ;
145
206
146
207
typedef struct _php_random_engine {
@@ -161,12 +222,21 @@ typedef struct _php_random_engine_state_mersennetwister {
161
222
bool seeded ;
162
223
} php_random_engine_state_mersennetwister ;
163
224
225
+ typedef struct _php_random_engine_state_pcg64 {
226
+ random_uint128_t s ;
227
+ random_uint128_t inc ;
228
+ } php_random_engine_state_pcg64 ;
229
+
164
230
typedef struct _php_random_engine_state_user {
165
231
zend_object * object ;
166
232
zend_function * generate_method ;
167
233
size_t last_generate_size ;
168
234
} php_random_engine_state_user ;
169
235
236
+ typedef struct _php_random_engine_state_xorshift128plus {
237
+ uint64_t s [2 ];
238
+ } php_random_engine_state_xorshift128plus ;
239
+
170
240
typedef struct _php_random_engine_state_xoshiro256starstar {
171
241
uint64_t s [4 ];
172
242
} php_random_engine_state_xoshiro256starstar ;
0 commit comments