@@ -127,7 +127,8 @@ struct __attribute__((aligned(64UL))) fd_wsample_private {
127127 uint height ;
128128 char restore_enabled ;
129129 char poisoned_mode ;
130- /* Two bytes of padding here */
130+ uchar rng_algo ;
131+ /* One byte of padding here */
131132
132133 fd_chacha_rng_t * rng ;
133134
@@ -302,6 +303,7 @@ fd_wsample_new_init( void * shmem,
302303 sampler -> height = (uint )height ;
303304 sampler -> restore_enabled = (char )!!restore_enabled ;
304305 sampler -> poisoned_mode = 0 ;
306+ sampler -> rng_algo = 0 ;
305307 sampler -> rng = rng ;
306308
307309 fd_memset ( sampler -> tree , (char )0 , internal_cnt * sizeof (tree_ele_t ) );
@@ -389,18 +391,25 @@ fd_wsample_delete( void * shmem ) {
389391 return shmem ;
390392}
391393
392-
393-
394- fd_chacha_rng_t * fd_wsample_get_rng ( fd_wsample_t * sampler ) { return sampler -> rng ; }
395-
396-
397- /* TODO: Should this function exist at all? */
398394void
399- fd_wsample_seed_rng ( fd_chacha_rng_t * rng ,
400- uchar seed [static 32 ] ) {
401- fd_chacha20_rng_init ( rng , seed );
395+ fd_wsample_seed_rng ( fd_wsample_t * sampler ,
396+ uchar seed [ 32 ],
397+ int use_chacha8 ) {
398+ sampler -> rng_algo = fd_uchar_if ( use_chacha8 , FD_WSAMPLE_RNG_CHACHA8 , FD_WSAMPLE_RNG_CHACHA20 );
399+ if ( FD_UNLIKELY ( sampler -> rng_algo == FD_WSAMPLE_RNG_CHACHA8 ) ) {
400+ fd_chacha8_rng_init ( sampler -> rng , seed );
401+ } else {
402+ fd_chacha20_rng_init ( sampler -> rng , seed );
403+ }
402404}
403405
406+ ulong
407+ fd_wsample_rng_ulong_roll ( fd_wsample_t * sampler , ulong n ) {
408+ if ( FD_UNLIKELY ( sampler -> rng_algo == FD_WSAMPLE_RNG_CHACHA8 ) ) {
409+ return fd_chacha8_rng_ulong_roll ( sampler -> rng , n );
410+ }
411+ return fd_chacha20_rng_ulong_roll ( sampler -> rng , n );
412+ }
404413
405414fd_wsample_t *
406415fd_wsample_restore_all ( fd_wsample_t * sampler ) {
@@ -597,7 +606,7 @@ fd_wsample_remove_idx( fd_wsample_t * sampler,
597606 but operations with mask registers are frustratingly slow. Instead,
598607 we first define x'=x+1, so then v0<=x is equivalent to v0-x'<0, or
599608 whether v0-x' has the high bit set. Because of
600- fd_chacha20_rng_ulong_roll 's contract, we know x<ULONG_MAX, so forming
609+ fd_wsample_rng_ulong_roll 's contract, we know x<ULONG_MAX, so forming
601610 x' is safe. We then use a _mm512_permutexvar_epi8 to essentially
602611 broadcast the high byte from each of the ulongs (really we just need
603612 the high bit) to the whole vector. A popcnt gives us our base
@@ -734,7 +743,7 @@ fd_wsample_sample_and_remove_many( fd_wsample_t * sampler,
734743 for ( ulong i = 0UL ; i < cnt ; i ++ ) {
735744 if ( FD_UNLIKELY ( !sampler -> unremoved_weight ) ) { idxs [ i ] = FD_WSAMPLE_EMPTY ; continue ; }
736745 if ( FD_UNLIKELY ( sampler -> poisoned_mode ) ) { idxs [ i ] = FD_WSAMPLE_INDETERMINATE ; continue ; }
737- ulong unif = fd_chacha20_rng_ulong_roll ( sampler -> rng , sampler -> unremoved_weight + sampler -> poisoned_weight );
746+ ulong unif = fd_wsample_rng_ulong_roll ( sampler , sampler -> unremoved_weight + sampler -> poisoned_weight );
738747 if ( FD_UNLIKELY ( unif >=sampler -> unremoved_weight ) ) {
739748 idxs [ i ] = FD_WSAMPLE_INDETERMINATE ;
740749 sampler -> poisoned_mode = 1 ;
@@ -771,7 +780,7 @@ ulong
771780fd_wsample_sample ( fd_wsample_t * sampler ) {
772781 if ( FD_UNLIKELY ( !sampler -> unremoved_weight ) ) return FD_WSAMPLE_EMPTY ;
773782 if ( FD_UNLIKELY ( sampler -> poisoned_mode ) ) return FD_WSAMPLE_INDETERMINATE ;
774- ulong unif = fd_chacha20_rng_ulong_roll ( sampler -> rng , sampler -> unremoved_weight + sampler -> poisoned_weight );
783+ ulong unif = fd_wsample_rng_ulong_roll ( sampler , sampler -> unremoved_weight + sampler -> poisoned_weight );
775784 if ( FD_UNLIKELY ( unif >=sampler -> unremoved_weight ) ) return FD_WSAMPLE_INDETERMINATE ;
776785 return (ulong )fd_wsample_map_sample ( sampler , unif );
777786}
@@ -780,7 +789,7 @@ ulong
780789fd_wsample_sample_and_remove ( fd_wsample_t * sampler ) {
781790 if ( FD_UNLIKELY ( !sampler -> unremoved_weight ) ) return FD_WSAMPLE_EMPTY ;
782791 if ( FD_UNLIKELY ( sampler -> poisoned_mode ) ) return FD_WSAMPLE_INDETERMINATE ;
783- ulong unif = fd_chacha20_rng_ulong_roll ( sampler -> rng , sampler -> unremoved_weight + sampler -> poisoned_weight );
792+ ulong unif = fd_wsample_rng_ulong_roll ( sampler , sampler -> unremoved_weight + sampler -> poisoned_weight );
784793 if ( FD_UNLIKELY ( unif >=sampler -> unremoved_weight ) ) {
785794 sampler -> poisoned_mode = 1 ;
786795 return FD_WSAMPLE_INDETERMINATE ;
0 commit comments