@@ -1832,6 +1832,9 @@ and the [`NewState`](`t:state/0`).
18321832 when
18331833 List :: list (),
18341834 State :: state ().
1835+ shuffle_s (List , {#{type := mwc59 } = AlgHandler , CX0 }) ->
1836+ {ShuffledList , _P1 , CX1 } = shuffle_s_mwc59 (List , CX0 ),
1837+ {ShuffledList , {AlgHandler , CX1 }};
18351838shuffle_s (List , {AlgHandler , R0 })
18361839 when is_list (List ) ->
18371840 [P0 |S0 ] = shuffle_init_bitstream (R0 , AlgHandler ),
@@ -3239,6 +3242,83 @@ hash58(X) ->
32393242 X2 = ? MASK (58 , (X1 bxor (X1 bsr 29 )) * 16#0ceb9fe1a85ec53 ),
32403243 X2 bxor (X2 bsr 29 ).
32413244
3245+ % % -------
3246+
3247+ shuffle_s_mwc59 (List , S ) ->
3248+ shuffle_mwc59_r (List , [], 1 , S ).
3249+
3250+ % % Leaf cases - random permutations for 0..3 elements
3251+ shuffle_mwc59_r ([], Acc , P , S ) ->
3252+ {Acc , P , S };
3253+ shuffle_mwc59_r ([X ], Acc , P , S ) ->
3254+ {[X | Acc ], P , S };
3255+ shuffle_mwc59_r ([X , Y ], Acc , P , S ) ->
3256+ shuffle_mwc59_r_2 (X , Acc , P , S , Y );
3257+ shuffle_mwc59_r ([X , Y , Z ], Acc , P , S ) ->
3258+ shuffle_mwc59_r_3 (X , Acc , P , S , Y , Z );
3259+ % % General case - split and recursive shuffle
3260+ shuffle_mwc59_r ([_ , _ , _ | _ ] = List , Acc , P , S ) ->
3261+ % % P and S is bitstream cache and state
3262+ shuffle_mwc59_r (List , Acc , P , S , [], [], [], []).
3263+ % %
3264+ % % Split L into 4 random subsets
3265+ % %
3266+ shuffle_mwc59_r ([], Acc0 , P0 , S0 , Zero , One , Two , Three ) ->
3267+ % % Split done, recursively shuffle the splitted lists onto Acc
3268+ {Acc1 , P1 , S1 } = shuffle_mwc59_r (Zero , Acc0 , P0 , S0 ),
3269+ {Acc2 , P2 , S2 } = shuffle_mwc59_r (One , Acc1 , P1 , S1 ),
3270+ {Acc3 , P3 , S3 } = shuffle_mwc59_r (Two , Acc2 , P2 , S2 ),
3271+ shuffle_mwc59_r (Three , Acc3 , P3 , S3 );
3272+ shuffle_mwc59_r ([X | L ], Acc , P0 , S , Zero , One , Two , Three )
3273+ when is_integer (P0 ), 3 < P0 , P0 =< ? MASK (59 ) ->
3274+ P1 = P0 bsr 2 ,
3275+ case P0 band 3 of
3276+ 0 -> shuffle_mwc59_r (L , Acc , P1 , S , [X | Zero ], One , Two , Three );
3277+ 1 -> shuffle_mwc59_r (L , Acc , P1 , S , Zero , [X | One ], Two , Three );
3278+ 2 -> shuffle_mwc59_r (L , Acc , P1 , S , Zero , One , [X | Two ], Three );
3279+ 3 -> shuffle_mwc59_r (L , Acc , P1 , S , Zero , One , Two , [X | Three ])
3280+ end ;
3281+ shuffle_mwc59_r ([_ | _ ] = L , Acc , _P , S0 , Zero , One , Two , Three ) ->
3282+ S1 = ? mwc59 (S0 , C , D ),
3283+ P = ? mwc59_value (S1 , Tmp ) bor ? BIT (58 ),
3284+ shuffle_mwc59_r (L , Acc , P , S1 , Zero , One , Two , Three ).
3285+
3286+ % % Permute 2 elements
3287+ shuffle_mwc59_r_2 (X , Acc , P , S , Y )
3288+ when is_integer (P ), 1 < P , P =< ? MASK (59 ) ->
3289+ {case P band 1 of
3290+ 0 -> [Y , X | Acc ];
3291+ 1 -> [X , Y | Acc ]
3292+ end , P bsr 1 , S };
3293+ shuffle_mwc59_r_2 (X , Acc , _P , S0 , Y ) ->
3294+ S1 = ? mwc59 (S0 , C , D ),
3295+ P = ? mwc59_value (S1 , Tmp ) bor ? BIT (58 ),
3296+ shuffle_mwc59_r_2 (X , Acc , P , S1 , Y ).
3297+
3298+ % % Permute 3 elements
3299+ % %
3300+ % % Uses 3 random bits per iteration with a probability of 1/4
3301+ % % to reject and retry, which on average is 3 * 4/3
3302+ % % (infinite sum of (1/4)^k) = 4 bits per permutation
3303+ shuffle_mwc59_r_3 (X , Acc , P0 , S , Y , Z )
3304+ when is_integer (P0 ), 7 < P0 , P0 =< ? MASK (59 ) ->
3305+ P1 = P0 bsr 3 ,
3306+ case P0 band 7 of
3307+ 0 -> {[Z , Y , X | Acc ], P1 , S };
3308+ 1 -> {[Y , Z , X | Acc ], P1 , S };
3309+ 2 -> {[Z , X , Y | Acc ], P1 , S };
3310+ 3 -> {[X , Z , Y | Acc ], P1 , S };
3311+ 4 -> {[Y , X , Z | Acc ], P1 , S };
3312+ 5 -> {[X , Y , Z | Acc ], P1 , S };
3313+ _ -> % Reject and retry
3314+ shuffle_mwc59_r_3 (X , Acc , P1 , S , Y , Z )
3315+ end ;
3316+ shuffle_mwc59_r_3 (X , Acc , _P , S0 , Y , Z ) ->
3317+ S1 = ? mwc59 (S0 , C , D ),
3318+ P = ? mwc59_value (S1 , Tmp ) bor ? BIT (58 ),
3319+ shuffle_mwc59_r_3 (X , Acc , P , S1 , Y , Z ).
3320+
3321+
32423322% % =====================================================================
32433323% % Mask and fill state list, ensure not all zeros
32443324% % =====================================================================
0 commit comments