File 2964-Increase-mwc59-seed-range-to-58-bits.patch of Package erlang

From 6949861e00c48f5cae13218bd051a572850660a6 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Tue, 10 May 2022 16:25:10 +0200
Subject: [PATCH 4/8] Increase mwc59 seed range to 58 bits

To hash the seed into 58 bits and then add 1 is better than
hashing into 57 bits and then bor 1 bsl 58.  58 bits is more
familiar and twice as large.
---
 lib/stdlib/doc/src/rand.xml    |  4 ++--
 lib/stdlib/src/rand.erl        | 27 +++++++++++++++------------
 lib/stdlib/test/rand_SUITE.erl | 10 +++++-----
 3 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml
index 7eb6a164c8..8b9b924366 100644
--- a/lib/stdlib/doc/src/rand.xml
+++ b/lib/stdlib/doc/src/rand.xml
@@ -1064,8 +1064,8 @@ end.</pre>
       <desc>
         <p>
           Returns a generator state <c><anno>CX</anno></c>.
-          It is set it to <c><anno>S</anno></c>, after folding it
-          into the state's range, if out of range.
+          <c><anno>S</anno></c> is hashed to create the generator state,
+          to avoid that similar seeds create similar sequences.
         </p>
         <p>
           Without <c><anno>S</anno></c>,
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index 14e4f7eb74..ac61acd955 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -1533,29 +1533,32 @@ mwc59_value(CX1) -> % when is_integer(CX1), 1 =< CX1, CX1 < ?MWC59_P ->
 
 -spec mwc59_float(CX :: mwc59_state()) -> V :: float().
 mwc59_float(CX1) ->
-    mwc59_value(CX1) * (1/(1 bsl 59)).
+    CX = ?MASK(59, CX1),
+    CX2 = CX bxor ?BSL(59, CX, ?MWC59_XS1),
+    CX3 = CX2 bxor ?BSL(59, CX2, ?MWC59_XS2),
+    (CX3 bsr (59-53)) * ?TWO_POW_MINUS53.
 
 -spec mwc59_seed() -> CX :: mwc59_state().
 mwc59_seed() ->
     {A1, A2, A3} = default_seed(),
-    X1 = hash57(A1),
-    X2 = hash57(A2),
-    X3 = hash57(A3),
-    ?BIT(58) bor (X1 bxor X2 bxor X3).
+    X1 = hash58(A1),
+    X2 = hash58(A2),
+    X3 = hash58(A3),
+    (X1 bxor X2 bxor X3) + 1.
 
--spec mwc59_seed(S :: 0..?MASK(57)) -> CX :: mwc59_state().
-mwc59_seed(S) when is_integer(S), 0 =< S, S =< ?MASK(57) ->
-    ?BIT(58) bor hash57(S).
+-spec mwc59_seed(S :: 0..?MASK(58)) -> CX :: mwc59_state().
+mwc59_seed(S) when is_integer(S), 0 =< S, S =< ?MASK(58) ->
+    hash58(S) + 1.
 
 %% Constants a'la SplitMix64, MurMurHash, etc.
 %% Not that critical, just mix the bits using bijections
 %% (reversible mappings) to not have any two user input seeds
 %% become the same generator start state.
 %%
-hash57(X) ->
-    X0 = ?MASK(57, X),
-    X1 = ?MASK(57, (X0 bxor (X0 bsr 29)) * 16#151afd7ed558ccd),
-    X2 = ?MASK(57, (X1 bxor (X1 bsr 29)) * 16#0ceb9fe1a85ec53),
+hash58(X) ->
+    X0 = ?MASK(58, X),
+    X1 = ?MASK(58, (X0 bxor (X0 bsr 29)) * 16#351afd7ed558ccd),
+    X2 = ?MASK(58, (X1 bxor (X1 bsr 29)) * 16#0ceb9fe1a85ec53),
     X2 bxor (X2 bsr 29).
 
 
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index e84689ea69..5f3df66bee 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -216,25 +216,25 @@ mwc59_api(Config) when is_list(Config) ->
             error({bad_return, CX1})
     catch
         error : function_clause ->
-            try rand:mwc59_seed(1 bsl 57) of
+            try rand:mwc59_seed(1 bsl 58) of
                 CX2 ->
                     error({bad_return, CX2})
             catch
                 error : function_clause ->
-                    Seed = 324109835948422043,
+                    Seed = 11213862807209314,
                     Seed = rand:mwc59_seed(1),
                     mwc59_api(Seed, 1000000)
             end
     end.
 
 mwc59_api(CX0, 0) ->
-    CX = 394988924775693874,
+    CX = 182322083224642863,
     {CX, CX} = {CX0, CX},
     V0 = rand:mwc59_value32(CX0),
-    V = 3767127090,
+    V = 2905950767,
     {V, V} = {V0, V},
     W0 = rand:mwc59_value(CX0),
-    W = 418709302640385298,
+    W = 269866568368142303,
     {W, W} = {W0, W},
     F0 = rand:mwc59_float(CX0),
     F = (W bsr (59-53)) * (1 / (1 bsl 53)),
-- 
2.35.3

openSUSE Build Service is sponsored by