php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
engine_pcgoneseq128xslrr64.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Go Kudo <zeriyoshi@php.net> |
14 | |
15 | Based on code from: Melissa O'Neill <oneill@pcg-random.org> |
16 +----------------------------------------------------------------------+
17*/
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include "php.h"
24#include "php_random.h"
25#include "php_random_csprng.h"
26#include "php_random_uint128.h"
27
29
30static inline void step(php_random_status_state_pcgoneseq128xslrr64 *s)
31{
32 s->state = php_random_uint128_add(
33 php_random_uint128_multiply(s->state, php_random_uint128_constant(2549297995355413924ULL,4865540595714422341ULL)),
34 php_random_uint128_constant(6364136223846793005ULL,1442695040888963407ULL)
35 );
36}
37
39{
40 s->state = php_random_uint128_constant(0ULL, 0ULL);
41 step(s);
42 s->state = php_random_uint128_add(s->state, seed);
43 step(s);
44}
45
46static php_random_result generate(void *state)
47{
49
50 step(s);
51
52 return (php_random_result){
53 .size = sizeof(uint64_t),
54 .result = php_random_pcgoneseq128xslrr64_rotr64(s->state),
55 };
56}
57
58static zend_long range(void *state, zend_long min, zend_long max)
59{
62 .state = state,
63 }, min, max);
64}
65
66static bool serialize(void *state, HashTable *data)
67{
69 uint64_t u;
70 zval z;
71
72 u = php_random_uint128_hi(s->state);
73 ZVAL_STR(&z, php_random_bin2hex_le(&u, sizeof(uint64_t)));
75
76 u = php_random_uint128_lo(s->state);
77 ZVAL_STR(&z, php_random_bin2hex_le(&u, sizeof(uint64_t)));
79
80 return true;
81}
82
83static bool unserialize(void *state, HashTable *data)
84{
86 uint64_t u[2];
87 zval *t;
88
89 /* Verify the expected number of elements, this implicitly ensures that no additional elements are present. */
90 if (zend_hash_num_elements(data) != 2) {
91 return false;
92 }
93
94 for (uint32_t i = 0; i < 2; i++) {
96 if (!t || Z_TYPE_P(t) != IS_STRING || Z_STRLEN_P(t) != (2 * sizeof(uint64_t))) {
97 return false;
98 }
99 if (!php_random_hex2bin_le(Z_STR_P(t), &u[i])) {
100 return false;
101 }
102 }
103 s->state = php_random_uint128_constant(u[0], u[1]);
104
105 return true;
106}
107
110 generate,
111 range,
112 serialize,
113 unserialize
114};
115
116/* {{{ php_random_pcgoneseq128xslrr64_advance */
118{
120 cur_mult = php_random_uint128_constant(2549297995355413924ULL,4865540595714422341ULL),
121 cur_plus = php_random_uint128_constant(6364136223846793005ULL,1442695040888963407ULL),
122 acc_mult = php_random_uint128_constant(0ULL, 1ULL),
123 acc_plus = php_random_uint128_constant(0ULL, 0ULL);
124
125 while (advance > 0) {
126 if (advance & 1) {
127 acc_mult = php_random_uint128_multiply(acc_mult, cur_mult);
128 acc_plus = php_random_uint128_add(php_random_uint128_multiply(acc_plus, cur_mult), cur_plus);
129 }
130 cur_plus = php_random_uint128_multiply(php_random_uint128_add(cur_mult, php_random_uint128_constant(0ULL, 1ULL)), cur_plus);
131 cur_mult = php_random_uint128_multiply(cur_mult, cur_mult);
132 advance /= 2;
133 }
134
135 state->state = php_random_uint128_add(php_random_uint128_multiply(acc_mult, state->state), acc_plus);
136}
137/* }}} */
138
139/* {{{ Random\Engine\PcgOneseq128XslRr64::__construct */
140PHP_METHOD(Random_Engine_PcgOneseq128XslRr64, __construct)
141{
144 zend_string *str_seed = NULL;
145 zend_long int_seed = 0;
146 bool seed_is_null = true;
147
150 Z_PARAM_STR_OR_LONG_OR_NULL(str_seed, int_seed, seed_is_null);
152
153 if (seed_is_null) {
155
156 if (php_random_bytes_throw(&s, sizeof(s)) == FAILURE) {
157 zend_throw_exception(random_ce_Random_RandomException, "Failed to generate a random seed", 0);
159 }
160
162 } else {
163 if (str_seed) {
164 /* char (byte: 8 bit) * 16 = 128 bits */
165 if (ZSTR_LEN(str_seed) == 16) {
166 uint64_t t[2];
167
168 /* Endianness safe copy */
169 for (uint32_t i = 0; i < 2; i++) {
170 t[i] = 0;
171 for (uint32_t j = 0; j < 8; j++) {
172 t[i] += ((uint64_t) (unsigned char) ZSTR_VAL(str_seed)[(i * 8) + j]) << (j * 8);
173 }
174 }
175
176 php_random_pcgoneseq128xslrr64_seed128(state, php_random_uint128_constant(t[0], t[1]));
177 } else {
178 zend_argument_value_error(1, "must be a 16 byte (128 bit) string");
180 }
181 } else {
182 php_random_pcgoneseq128xslrr64_seed128(state, php_random_uint128_constant(0ULL, (uint64_t) int_seed));
183 }
184 }
185}
186/* }}} */
187
188/* {{{ Random\Engine\PcgOneseq128XslRr64::jump() */
189PHP_METHOD(Random_Engine_PcgOneseq128XslRr64, jump)
190{
193 zend_long advance = 0;
194
196 Z_PARAM_LONG(advance);
198
199 if (UNEXPECTED(advance < 0)) {
200 zend_argument_value_error(1, "must be greater than or equal to 0");
202 }
203
205}
206/* }}} */
char s[4]
Definition cdf.c:77
uint32_t u
Definition cdf.c:78
PHPAPI void php_random_pcgoneseq128xslrr64_seed128(php_random_status_state_pcgoneseq128xslrr64 *s, php_random_uint128_t seed)
PHPAPI const php_random_algo php_random_algo_pcgoneseq128xslrr64
PHPAPI void php_random_pcgoneseq128xslrr64_advance(php_random_status_state_pcgoneseq128xslrr64 *state, uint64_t advance)
#define max(a, b)
Definition exif.c:60
#define NULL
Definition gdcache.h:45
again j
#define PHP_METHOD
Definition php.h:365
#define PHPAPI
Definition php.h:71
#define min(a, b)
PHPAPI zend_string * php_random_bin2hex_le(const void *ptr, const size_t len)
Definition random.c:332
PHPAPI bool php_random_hex2bin_le(zend_string *hexstr, void *dest)
Definition random.c:358
struct _php_random_status_state_pcgoneseq128xslrr64 php_random_status_state_pcgoneseq128xslrr64
struct _php_random_algo_with_state php_random_algo_with_state
PHPAPI zend_class_entry * random_ce_Random_RandomException
#define Z_RANDOM_ENGINE_P(zval)
Definition php_random.h:147
PHPAPI zend_long php_random_range(php_random_algo_with_state engine, zend_long min, zend_long max)
Definition random.c:293
struct _php_random_algo php_random_algo
struct _php_random_result php_random_result
struct _php_random_uint128_t php_random_uint128_t
zend_constant * data
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define Z_PARAM_STR_OR_LONG_OR_NULL(dest_str, dest_long, is_null)
Definition zend_API.h:2168
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define Z_PARAM_LONG(dest)
Definition zend_API.h:1896
#define RETURN_THROWS()
Definition zend_API.h:1060
#define ZEND_THIS
Definition zend_API.h:523
struct _zval_struct zval
ZEND_API ZEND_COLD zend_object * zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code)
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert(HashTable *ht, zval *pData)
Definition zend_hash.c:1224
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
Definition zend_hash.c:2701
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
#define UNEXPECTED(condition)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define ZVAL_STR(z, s)
#define IS_STRING
Definition zend_types.h:606
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
@ FAILURE
Definition zend_types.h:61
bool result