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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
|
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Rasmus Lerdorf <rasmus@php.net> |
| Zeev Suraski <zeev@php.net> |
| Sascha Schumann <sascha@schumann.cx> |
| Pedro Melo <melo@ip.pt> |
| Sterling Hughes <sterling@php.net> |
| Sammy Kaye Powers <me@sammyk.me> |
| Go Kudo <zeriyoshi@php.net> |
| |
| Based on code from: Richard J. Wagner <rjwagner@writeme.com> |
| Makoto Matsumoto <matumoto@math.keio.ac.jp> |
| Takuji Nishimura |
| Shawn Cokus <Cokus@math.washington.edu> |
| David Blackman |
| Sebastiano Vigna <vigna@acm.org> |
| Melissa O'Neill <oneill@pcg-random.org> |
+----------------------------------------------------------------------+
*/
#ifndef PHP_RANDOM_H
# define PHP_RANDOM_H
# include "php.h"
PHPAPI double php_combined_lcg(void);
/*
* A bit of tricky math here. We want to avoid using a modulus because
* that simply tosses the high-order bits and might skew the distribution
* of random values over the range. Instead we map the range directly.
*
* We need to map the range from 0...M evenly to the range a...b
* Let n = the random number and n' = the mapped random number
*
* Then we have: n' = a + n(b-a)/M
*
* We have a problem here in that only n==M will get mapped to b which
* means the chances of getting b is much much less than getting any of
* the other values in the range. We can fix this by increasing our range
* artificially and using:
*
* n' = a + n(b-a+1)/M
*
* Now we only have a problem if n==M which would cause us to produce a
* number of b+1 which would be bad. So we bump M up by one to make sure
* this will never happen, and the final algorithm looks like this:
*
* n' = a + n(b-a+1)/(M+1)
*
* -RL
*/
# define RAND_RANGE_BADSCALING(__n, __min, __max, __tmax) \
(__n) = (__min) + (zend_long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
# ifdef PHP_WIN32
# define GENERATE_SEED() (((zend_long) ((zend_ulong) time(NULL) * (zend_ulong) GetCurrentProcessId())) ^ ((zend_long) (1000000.0 * php_combined_lcg())))
# else
# define GENERATE_SEED() (((zend_long) ((zend_ulong) time(NULL) * (zend_ulong) getpid())) ^ ((zend_long) (1000000.0 * php_combined_lcg())))
# endif
# define PHP_MT_RAND_MAX ((zend_long) (0x7FFFFFFF)) /* (1<<31) - 1 */
# define MT_RAND_MT19937 0
# define MT_RAND_PHP 1
# define MT_N (624)
PHPAPI void php_mt_srand(uint32_t seed);
PHPAPI uint32_t php_mt_rand(void);
PHPAPI zend_long php_mt_rand_range(zend_long min, zend_long max);
PHPAPI zend_long php_mt_rand_common(zend_long min, zend_long max);
# ifndef RAND_MAX
# define RAND_MAX PHP_MT_RAND_MAX
# endif
# define PHP_RAND_MAX PHP_MT_RAND_MAX
PHPAPI void php_srand(zend_long seed);
PHPAPI zend_long php_rand(void);
# if !defined(__SIZEOF_INT128__) || defined(PHP_RANDOM_FORCE_EMULATE_128)
typedef struct _php_random_uint128_t {
uint64_t hi;
uint64_t lo;
} php_random_uint128_t;
static inline uint64_t php_random_uint128_hi(php_random_uint128_t num)
{
return num.hi;
}
static inline uint64_t php_random_uint128_lo(php_random_uint128_t num)
{
return num.lo;
}
static inline php_random_uint128_t php_random_uint128_constant(uint64_t hi, uint64_t lo)
{
php_random_uint128_t r;
r.hi = hi;
r.lo = lo;
return r;
}
static inline php_random_uint128_t php_random_uint128_add(php_random_uint128_t num1, php_random_uint128_t num2)
{
php_random_uint128_t r;
r.lo = (num1.lo + num2.lo);
r.hi = (num1.hi + num2.hi + (r.lo < num1.lo));
return r;
}
static inline php_random_uint128_t php_random_uint128_multiply(php_random_uint128_t num1, php_random_uint128_t num2)
{
php_random_uint128_t r;
const uint64_t
x0 = num1.lo & 0xffffffffULL,
x1 = num1.lo >> 32,
y0 = num2.lo & 0xffffffffULL,
y1 = num2.lo >> 32,
z0 = (((x1 * y0) + (x0 * y0 >> 32)) & 0xffffffffULL) + x0 * y1;
r.hi = num1.hi * num2.lo + num1.lo * num2.hi;
r.lo = num1.lo * num2.lo;
r.hi += x1 * y1 + ((x1 * y0 + (x0 * y0 >> 32)) >> 32) + (z0 >> 32);
return r;
}
static inline uint64_t php_random_pcgoneseq128xslrr64_rotr64(php_random_uint128_t num)
{
const uint64_t
v = (num.hi ^ num.lo),
s = num.hi >> 58U;
return (v >> s) | (v << ((-s) & 63));
}
# else
typedef __uint128_t php_random_uint128_t;
static inline uint64_t php_random_uint128_hi(php_random_uint128_t num)
{
return (uint64_t) (num >> 64);
}
static inline uint64_t php_random_uint128_lo(php_random_uint128_t num)
{
return (uint64_t) num;
}
static inline php_random_uint128_t php_random_uint128_constant(uint64_t hi, uint64_t lo)
{
php_random_uint128_t r;
r = ((php_random_uint128_t) hi << 64) + lo;
return r;
}
static inline php_random_uint128_t php_random_uint128_add(php_random_uint128_t num1, php_random_uint128_t num2)
{
return num1 + num2;
}
static inline php_random_uint128_t php_random_uint128_multiply(php_random_uint128_t num1, php_random_uint128_t num2)
{
return num1 * num2;
}
static inline uint64_t php_random_pcgoneseq128xslrr64_rotr64(php_random_uint128_t num)
{
const uint64_t
v = ((uint64_t) (num >> 64U)) ^ (uint64_t) num,
s = num >> 122U;
return (v >> s) | (v << ((-s) & 63));
}
# endif
# define php_random_bytes_throw(b, s) php_random_bytes((b), (s), 1)
# define php_random_bytes_silent(b, s) php_random_bytes((b), (s), 0)
# define php_random_int_throw(min, max, result) php_random_int((min), (max), (result), 1)
# define php_random_int_silent(min, max, result) php_random_int((min), (max), (result), 0)
PHPAPI int php_random_bytes(void *bytes, size_t size, bool should_throw);
PHPAPI int php_random_int(zend_long min, zend_long max, zend_long *result, bool should_throw);
typedef struct _php_random_status_ {
size_t last_generated_size;
void *state;
} php_random_status;
typedef struct _php_random_status_state_combinedlcg {
int32_t state[2];
} php_random_status_state_combinedlcg;
typedef struct _php_random_status_state_mt19937 {
uint32_t state[MT_N];
uint32_t count;
uint8_t mode;
} php_random_status_state_mt19937;
typedef struct _php_random_status_state_pcgoneseq128xslrr64 {
php_random_uint128_t state;
} php_random_status_state_pcgoneseq128xslrr64;
typedef struct _php_random_status_state_xoshiro256starstar {
uint64_t state[4];
} php_random_status_state_xoshiro256starstar;
typedef struct _php_random_status_state_user {
zend_object *object;
zend_function *generate_method;
} php_random_status_state_user;
typedef struct _php_random_algo {
const size_t generate_size;
const size_t state_size;
void (*seed)(php_random_status *status, uint64_t seed);
uint64_t (*generate)(php_random_status *status);
zend_long (*range)(php_random_status *status, zend_long min, zend_long max);
bool (*serialize)(php_random_status *status, HashTable *data);
bool (*unserialize)(php_random_status *status, HashTable *data);
} php_random_algo;
extern PHPAPI const php_random_algo php_random_algo_combinedlcg;
extern PHPAPI const php_random_algo php_random_algo_mt19937;
extern PHPAPI const php_random_algo php_random_algo_pcgoneseq128xslrr64;
extern PHPAPI const php_random_algo php_random_algo_xoshiro256starstar;
extern PHPAPI const php_random_algo php_random_algo_secure;
extern PHPAPI const php_random_algo php_random_algo_user;
typedef struct _php_random_engine {
const php_random_algo *algo;
php_random_status *status;
zend_object std;
} php_random_engine;
typedef struct _php_random_randomizer {
const php_random_algo *algo;
php_random_status *status;
bool is_userland_algo;
zend_object std;
} php_random_randomizer;
extern PHPAPI zend_class_entry *random_ce_Random_Engine;
extern PHPAPI zend_class_entry *random_ce_Random_CryptoSafeEngine;
extern PHPAPI zend_class_entry *random_ce_Random_RandomError;
extern PHPAPI zend_class_entry *random_ce_Random_BrokenRandomEngineError;
extern PHPAPI zend_class_entry *random_ce_Random_RandomException;
extern PHPAPI zend_class_entry *random_ce_Random_Engine_PcgOneseq128XslRr64;
extern PHPAPI zend_class_entry *random_ce_Random_Engine_Mt19937;
extern PHPAPI zend_class_entry *random_ce_Random_Engine_Xoshiro256StarStar;
extern PHPAPI zend_class_entry *random_ce_Random_Engine_Secure;
extern PHPAPI zend_class_entry *random_ce_Random_Randomizer;
static inline php_random_engine *php_random_engine_from_obj(zend_object *object) {
return (php_random_engine *)((char *)(object) - XtOffsetOf(php_random_engine, std));
}
static inline php_random_randomizer *php_random_randomizer_from_obj(zend_object *object) {
return (php_random_randomizer *)((char *)(object) - XtOffsetOf(php_random_randomizer, std));
}
# define Z_RANDOM_ENGINE_P(zval) php_random_engine_from_obj(Z_OBJ_P(zval))
# define Z_RANDOM_RANDOMIZER_P(zval) php_random_randomizer_from_obj(Z_OBJ_P(zval));
PHPAPI php_random_status *php_random_status_alloc(const php_random_algo *algo, const bool persistent);
PHPAPI php_random_status *php_random_status_copy(const php_random_algo *algo, php_random_status *old_status, php_random_status *new_status);
PHPAPI void php_random_status_free(php_random_status *status, const bool persistent);
PHPAPI php_random_engine *php_random_engine_common_init(zend_class_entry *ce, zend_object_handlers *handlers, const php_random_algo *algo);
PHPAPI void php_random_engine_common_free_object(zend_object *object);
PHPAPI zend_object *php_random_engine_common_clone_object(zend_object *object);
PHPAPI zend_long php_random_range(const php_random_algo *algo, php_random_status *status, zend_long min, zend_long max);
PHPAPI const php_random_algo *php_random_default_algo(void);
PHPAPI php_random_status *php_random_default_status(void);
PHPAPI zend_string *php_random_bin2hex_le(const void *ptr, const size_t len);
PHPAPI bool php_random_hex2bin_le(zend_string *hexstr, void *dest);
PHPAPI void php_random_combinedlcg_seed_default(php_random_status_state_combinedlcg *state);
PHPAPI void php_random_mt19937_seed_default(php_random_status_state_mt19937 *state);
PHPAPI void php_random_pcgoneseq128xslrr64_advance(php_random_status_state_pcgoneseq128xslrr64 *state, uint64_t advance);
PHPAPI void php_random_xoshiro256starstar_jump(php_random_status_state_xoshiro256starstar *state);
PHPAPI void php_random_xoshiro256starstar_jump_long(php_random_status_state_xoshiro256starstar *state);
extern zend_module_entry random_module_entry;
# define phpext_random_ptr &random_module_entry
PHP_MINIT_FUNCTION(random);
PHP_MSHUTDOWN_FUNCTION(random);
PHP_RINIT_FUNCTION(random);
ZEND_BEGIN_MODULE_GLOBALS(random)
php_random_status *combined_lcg;
bool combined_lcg_seeded;
php_random_status *mt19937;
bool mt19937_seeded;
int random_fd;
ZEND_END_MODULE_GLOBALS(random)
PHPAPI ZEND_EXTERN_MODULE_GLOBALS(random)
# define RANDOM_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(random, v)
#endif /* PHP_RANDOM_H */
|