@@ -467,15 +467,26 @@ static uint64_t pcg64_generate(void *state, bool *engine_unsafe) {
467467 return result ;
468468}
469469
470+ static void pcg64_seed_full (php_random_engine_state_pcg64 * state ) {
471+ random_uint128_t initstate , initseq ;
472+
473+ initstate = state -> s ;
474+ initseq = state -> inc ;
475+
476+ UINT128_CON (0ULL , 0ULL , state -> s );
477+ PCG64_ROTL1OR1 (initseq , state -> inc );
478+ pcg64_step (state );
479+ UINT128_ADD (initstate , state -> s , state -> s );
480+ pcg64_step (state );
481+ }
482+
470483static void pcg64_seed (void * state , const uint64_t seed ) {
471484 php_random_engine_state_pcg64 * s = state ;
472- random_uint128_t sd ;
473485
474- UINT128_CON (0ULL , seed , sd );
475- PCG64_ROTL1OR1 (s -> s , s -> inc );
476- pcg64_step (s );
477- UINT128_ADD (sd , s -> s , s -> s );
478- pcg64_step (s );
486+ UINT128_CON (0ULL , seed , s -> s );
487+ UINT128_CON (0ULL , 0ULL , s -> inc );
488+
489+ pcg64_seed_full (s );
479490}
480491
481492static int pcg64_serialize (void * state , HashTable * data ) {
@@ -1413,17 +1424,37 @@ PHP_METHOD(Random_Engine_PCG64, __construct)
14131424{
14141425 php_random_engine * engine = Z_RANDOM_ENGINE_P (ZEND_THIS );
14151426 php_random_engine_state_pcg64 * state = engine -> state ;
1416- zend_string * str_seed = NULL ;
1417- zend_long int_seed = 0 ;
1427+ zend_string * str_seed = NULL , * str_seq = NULL ;
1428+ zend_long int_seed = 0 , int_seq = 0 ;
14181429 bool seed_is_null = true;
14191430 int i , j ;
14201431 uint64_t t [2 ];
14211432
1422- ZEND_PARSE_PARAMETERS_START (0 , 1 )
1433+ ZEND_PARSE_PARAMETERS_START (0 , 2 )
14231434 Z_PARAM_OPTIONAL ;
14241435 Z_PARAM_STR_OR_LONG_OR_NULL (str_seed , int_seed , seed_is_null );
1436+ Z_PARAM_STR_OR_LONG (str_seq , int_seq );
14251437 ZEND_PARSE_PARAMETERS_END ();
14261438
1439+ if (str_seq ) {
1440+ /* char (8 bit) * 16 = 128 bits */
1441+ if (ZSTR_LEN (str_seq ) == 16 ) {
1442+ /* Endianness safe copy */
1443+ for (i = 0 ; i < 2 ; i ++ ) {
1444+ t [i ] = 0 ;
1445+ for (j = 0 ; j < 8 ; j ++ ) {
1446+ t [i ] += ((uint64_t ) (unsigned char ) ZSTR_VAL (str_seq )[(i * 8 ) + j ]) << (j * 8 );
1447+ }
1448+ }
1449+ UINT128_CON (t [0 ], t [1 ], state -> inc );
1450+ } else {
1451+ zend_argument_value_error (2 , "sequence strings must be 16 bytes" );
1452+ RETURN_THROWS ();
1453+ }
1454+ } else {
1455+ UINT128_CON (0ULL , int_seq , state -> inc );
1456+ }
1457+
14271458 if (seed_is_null ) {
14281459 if (php_random_bytes_silent (& state -> s , sizeof (random_uint128_t )) == FAILURE ) {
14291460 zend_throw_exception (spl_ce_RuntimeException , "Random number generate failed" , 0 );
@@ -1441,14 +1472,15 @@ PHP_METHOD(Random_Engine_PCG64, __construct)
14411472 }
14421473 }
14431474 UINT128_CON (t [0 ], t [1 ], state -> s );
1444- UINT128_CON (0ULL , 0ULL , state -> inc );
14451475 } else {
14461476 zend_argument_value_error (1 , "state strings must be 16 bytes" );
14471477 RETURN_THROWS ();
14481478 }
14491479 } else {
1450- engine -> algo -> seed ( state , int_seed );
1480+ UINT128_CON ( 0ULL , int_seed , state -> s );
14511481 }
1482+
1483+ pcg64_seed_full (state );
14521484 }
14531485}
14541486/* }}} */
0 commit comments