Skip to content

Commit 6e4d1e8

Browse files
committed
Do a 4-way split instead of a 2-way
1 parent e372add commit 6e4d1e8

File tree

1 file changed

+19
-14
lines changed

1 file changed

+19
-14
lines changed

lib/stdlib/src/rand.erl

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,8 @@ shuffle_s(List, {#{max:=_, next:=Next} = AlgHandler, R0})
14011401
%%
14021402
%% The `random_bit()` can be generated with small overhead by generating
14031403
%% a random word and cache it, then shift out one bit at the time.
1404+
%%
1405+
%% Also, it is faster to do a 4-way split instead of a 2-way.
14041406

14051407
%% Leaf cases - random permutations for 0..4 elements
14061408
shuffle_r([], Acc, P, S) ->
@@ -1416,25 +1418,28 @@ shuffle_r([X, Y, Z, Q], Acc, P, S) ->
14161418
%% General case - split and recursive shuffle
14171419
shuffle_r([_, _, _, _ | _] = List, Acc, P, S) ->
14181420
%% P and S is bitstream cache and state
1419-
shuffle_r(List, Acc, P, S, [], []).
1421+
shuffle_r(List, Acc, P, S, [], [], [], []).
14201422
%%
1421-
%% Split L into two random subsets: Zero and One
1423+
%% Split L into 4 random subsets
14221424
%%
1423-
shuffle_r([], Acc0, P0, S0, Zero, One) ->
1424-
%% Split done, recursively shuffle Zero and One onto Acc
1425+
shuffle_r([], Acc0, P0, S0, Zero, One, Two, Three) ->
1426+
%% Split done, recursively shuffle the splitted lists onto Acc
14251427
{Acc1, P1, S1} = shuffle_r(Zero, Acc0, P0, S0),
1426-
shuffle_r(One, Acc1, P1, S1);
1427-
shuffle_r([X | L], Acc, P, S, Zero, One)
1428-
when is_integer(P), 1 < P, P < 1 bsl 57 ->
1429-
case P band 1 of
1430-
0 ->
1431-
shuffle_r(L, Acc, P bsr 1, S, [X | Zero], One);
1432-
1 ->
1433-
shuffle_r(L, Acc, P bsr 1, S, Zero, [X | One])
1428+
{Acc2, P2, S2} = shuffle_r(One, Acc1, P1, S1),
1429+
{Acc3, P3, S3} = shuffle_r(Two, Acc2, P2, S2),
1430+
shuffle_r(Three, Acc3, P3, S3);
1431+
shuffle_r([X | L], Acc, P0, S, Zero, One, Two, Three)
1432+
when is_integer(P0), 3 < P0, P0 < 1 bsl 57 ->
1433+
P1 = P0 bsr 2,
1434+
case P0 band 3 of
1435+
0 -> shuffle_r(L, Acc, P1, S, [X | Zero], One, Two, Three);
1436+
1 -> shuffle_r(L, Acc, P1, S, Zero, [X | One], Two, Three);
1437+
2 -> shuffle_r(L, Acc, P1, S, Zero, One, [X | Two], Three);
1438+
3 -> shuffle_r(L, Acc, P1, S, Zero, One, Two, [X | Three])
14341439
end;
1435-
shuffle_r([_ | _] = L, Acc, _P, S0, Zero, One) ->
1440+
shuffle_r([_ | _] = L, Acc, _P, S0, Zero, One, Two, Three) ->
14361441
[P|S1] = shuffle_new_bits(S0),
1437-
shuffle_r(L, Acc, P, S1, Zero, One).
1442+
shuffle_r(L, Acc, P, S1, Zero, One, Two, Three).
14381443

14391444
%% Permute 2 elements
14401445
shuffle_r_2(X, Acc, P, S, Y)

0 commit comments

Comments
 (0)