[latex3-commits] [git/LaTeX3-latex3-latex3] master: Change \int_rand:nn (and rand_item functions) to better use the RNG (c83d05b)
Bruno Le Floch
bruno at le-floch.fr
Fri Apr 27 19:37:18 CEST 2018
Repository : https://github.com/latex3/latex3
On branch : master
Link : https://github.com/latex3/latex3/commit/c83d05b3f8ad6778d756b1e08d095e16a3b7e23c
>---------------------------------------------------------------
commit c83d05b3f8ad6778d756b1e08d095e16a3b7e23c
Author: Bruno Le Floch <bruno at le-floch.fr>
Date: Fri Apr 27 13:37:18 2018 -0400
Change \int_rand:nn (and rand_item functions) to better use the RNG
The RNG's low bits are not great, so use in priority its high bits.
>---------------------------------------------------------------
c83d05b3f8ad6778d756b1e08d095e16a3b7e23c
l3kernel/l3fp-random.dtx | 56 +++++++++++++++++++------------
l3kernel/testfiles/m3expl001.luatex.tlg | 2 +-
l3kernel/testfiles/m3expl001.ptex.tlg | 2 +-
l3kernel/testfiles/m3expl001.tlg | 2 +-
l3kernel/testfiles/m3expl001.uptex.tlg | 2 +-
l3kernel/testfiles/m3expl003.luatex.tlg | 2 +-
l3kernel/testfiles/m3expl003.ptex.tlg | 2 +-
l3kernel/testfiles/m3expl003.tlg | 2 +-
l3kernel/testfiles/m3expl003.uptex.tlg | 2 +-
l3kernel/testfiles/m3rand001.lvt | 2 +-
l3kernel/testfiles/m3rand001.tlg | 52 ++++++++++++++--------------
11 files changed, 70 insertions(+), 56 deletions(-)
diff --git a/l3kernel/l3fp-random.dtx b/l3kernel/l3fp-random.dtx
index 439eb85..b05325e 100644
--- a/l3kernel/l3fp-random.dtx
+++ b/l3kernel/l3fp-random.dtx
@@ -334,21 +334,27 @@
%
% \begin{macro}{\int_rand:nn}
% \begin{macro}{\@@_randint:ww}
+% \begin{macro}{\@@_randint_narrow:n}
% \begin{macro}{\@@_randint_narrow:nn}
% \begin{macro}{\@@_randint_narrow:nnn}
-% \begin{macro}{\@@_randint_narrow:nnnn}
% Evaluate the argument and filter out the case where the lower
% bound~|#1| is more than the upper bound~|#2|. Then determine
-% whether the range is narrower than \cs{c__fp_rand_size_int}; |#2-#1|
+% whether the range is narrower than \cs{c_@@_rand_size_int}; |#2-#1|
% may overflow for very large positive~|#2| and negative~|#1|. If the
% range is wide, use slower code from \pkg{l3fp}. If the range is
-% narrow, call \cs{@@_randint_narrow:nn} \Arg{choices} |{#1}| where
-% \meta{choices} is the number of possible outcomes. Then
-% \cs{@@_randint_narrow:nnnn} receives a random number reduced modulo
-% \meta{choices}, the random number itself, \meta{choices} and |#1|.
-% To avoid bias, throw away the random number if it lies in the last,
-% incomplete, interval of size \meta{choices} in
-% $[0,\cs{c_@@_rand_size_int}-1]$, and try again.
+% narrow, call \cs{@@_randint_narrow:n} \Arg{choices} where
+% \meta{choices} is the number of possible outcomes.
+%
+% One option then would be to reduce a random number modulo
+% \meta{choices}, but the low-order bits of random numbers provided by
+% the primitive have poor randomness: empirical tests indicate that
+% taking random numbers modulo~$2$ gives only two possible sequences
+% of bits depending on the seed's parity. Instead, fit in the output
+% range $[0,\cs{c_@@_rand_size_int}-1]$ of the random number generator
+% \meta{choices} equal-size intervals of maximum possible size
+% (obtained using \cs{int_div_truncate:nn}). Given a random number,
+% divide it by the size to determine which interval it falls into; if
+% it is beyond \meta{choices}, try another random number.
% \begin{macrocode}
\cs_new:Npn \int_rand:nn #1#2
{
@@ -369,27 +375,35 @@
{ \int_compare:nNnTF { #2 - #1 } < \c_@@_rand_size_int }
{ \int_compare:nNnTF {#2} < { #1 + \c_@@_rand_size_int } }
{
- \exp_args:Nf \@@_randint_narrow:nn
- { \int_eval:n { #2 - #1 + 1 } } {#1}
+ \int_eval:n
+ {
+ #1 +
+ \exp_args:Nf \@@_randint_narrow:n
+ { \int_eval:n { #2 - #1 + 1 } }
+ }
}
{ \fp_to_int:n { randint(#1,#2) } }
}
}
- \cs_new:Npn \@@_randint_narrow:nn
+ \cs_new:Npn \@@_randint_narrow:n #1
{
- \exp_args:No \@@_randint_narrow:nnn
- { \pdftex_uniformdeviate:D \c_@@_rand_size_int }
+ \exp_args:Nf \@@_randint_narrow:nn
+ { \int_div_truncate:nn \c_@@_rand_size_int {#1} } {#1}
}
- \cs_new:Npn \@@_randint_narrow:nnn #1#2
+ \cs_new:Npn \@@_randint_narrow:nn #1
{
- \exp_args:Nf \@@_randint_narrow:nnnn
- { \int_mod:nn {#1} {#2} } {#1} {#2}
+ \exp_args:Nf \@@_randint_narrow:nnn
+ {
+ \int_div_truncate:nn
+ { \pdftex_uniformdeviate:D \c_@@_rand_size_int } {#1}
+ }
+ {#1}
}
- \cs_new:Npn \@@_randint_narrow:nnnn #1#2#3#4
+ \cs_new:Npn \@@_randint_narrow:nnn #1#2#3
{
- \int_compare:nNnTF { #2 - #1 + #3 } > \c_@@_rand_size_int
- { \@@_randint_narrow:nn {#3} {#4} }
- { \int_eval:n { #4 + #1 } }
+ \int_compare:nNnTF {#1} < {#3}
+ {#1}
+ { \@@_randint_narrow:nn {#2} {#3} }
}
% \end{macrocode}
% \end{macro}
diff --git a/l3kernel/testfiles/m3expl001.luatex.tlg b/l3kernel/testfiles/m3expl001.luatex.tlg
index 07f0464..d502a54 100644
--- a/l3kernel/testfiles/m3expl001.luatex.tlg
+++ b/l3kernel/testfiles/m3expl001.luatex.tlg
@@ -4183,9 +4183,9 @@ Defining \__fp_randint_wide_e:nnnn on line ...
Defining \__fp_randint_wide_e:wnnn on line ...
Defining \int_rand:nn on line ...
Defining \__fp_randint:ww on line ...
+Defining \__fp_randint_narrow:n on line ...
Defining \__fp_randint_narrow:nn on line ...
Defining \__fp_randint_narrow:nnn on line ...
-Defining \__fp_randint_narrow:nnnn on line ...
Defining \c__intarray_sp_dim on line ...
\c__intarray_sp_dim=\dimen...
Defining \g__intarray_font_int on line ...
diff --git a/l3kernel/testfiles/m3expl001.ptex.tlg b/l3kernel/testfiles/m3expl001.ptex.tlg
index fb54e7b..35543de 100644
--- a/l3kernel/testfiles/m3expl001.ptex.tlg
+++ b/l3kernel/testfiles/m3expl001.ptex.tlg
@@ -4437,9 +4437,9 @@ Defining \__fp_randint_wide_e:nnnn on line ...
Defining \__fp_randint_wide_e:wnnn on line ...
Defining \int_rand:nn on line ...
Defining \__fp_randint:ww on line ...
+Defining \__fp_randint_narrow:n on line ...
Defining \__fp_randint_narrow:nn on line ...
Defining \__fp_randint_narrow:nnn on line ...
-Defining \__fp_randint_narrow:nnnn on line ...
Defining \c__intarray_sp_dim on line ...
\c__intarray_sp_dim=\dimen...
Defining \g__intarray_font_int on line ...
diff --git a/l3kernel/testfiles/m3expl001.tlg b/l3kernel/testfiles/m3expl001.tlg
index dee9b8e..a6ffb80 100644
--- a/l3kernel/testfiles/m3expl001.tlg
+++ b/l3kernel/testfiles/m3expl001.tlg
@@ -4437,9 +4437,9 @@ Defining \__fp_randint_wide_e:nnnn on line ...
Defining \__fp_randint_wide_e:wnnn on line ...
Defining \int_rand:nn on line ...
Defining \__fp_randint:ww on line ...
+Defining \__fp_randint_narrow:n on line ...
Defining \__fp_randint_narrow:nn on line ...
Defining \__fp_randint_narrow:nnn on line ...
-Defining \__fp_randint_narrow:nnnn on line ...
Defining \c__intarray_sp_dim on line ...
\c__intarray_sp_dim=\dimen...
Defining \g__intarray_font_int on line ...
diff --git a/l3kernel/testfiles/m3expl001.uptex.tlg b/l3kernel/testfiles/m3expl001.uptex.tlg
index 10fcf3e..dda643b 100644
--- a/l3kernel/testfiles/m3expl001.uptex.tlg
+++ b/l3kernel/testfiles/m3expl001.uptex.tlg
@@ -4437,9 +4437,9 @@ Defining \__fp_randint_wide_e:nnnn on line ...
Defining \__fp_randint_wide_e:wnnn on line ...
Defining \int_rand:nn on line ...
Defining \__fp_randint:ww on line ...
+Defining \__fp_randint_narrow:n on line ...
Defining \__fp_randint_narrow:nn on line ...
Defining \__fp_randint_narrow:nnn on line ...
-Defining \__fp_randint_narrow:nnnn on line ...
Defining \c__intarray_sp_dim on line ...
\c__intarray_sp_dim=\dimen...
Defining \g__intarray_font_int on line ...
diff --git a/l3kernel/testfiles/m3expl003.luatex.tlg b/l3kernel/testfiles/m3expl003.luatex.tlg
index 07f0464..d502a54 100644
--- a/l3kernel/testfiles/m3expl003.luatex.tlg
+++ b/l3kernel/testfiles/m3expl003.luatex.tlg
@@ -4183,9 +4183,9 @@ Defining \__fp_randint_wide_e:nnnn on line ...
Defining \__fp_randint_wide_e:wnnn on line ...
Defining \int_rand:nn on line ...
Defining \__fp_randint:ww on line ...
+Defining \__fp_randint_narrow:n on line ...
Defining \__fp_randint_narrow:nn on line ...
Defining \__fp_randint_narrow:nnn on line ...
-Defining \__fp_randint_narrow:nnnn on line ...
Defining \c__intarray_sp_dim on line ...
\c__intarray_sp_dim=\dimen...
Defining \g__intarray_font_int on line ...
diff --git a/l3kernel/testfiles/m3expl003.ptex.tlg b/l3kernel/testfiles/m3expl003.ptex.tlg
index fb54e7b..35543de 100644
--- a/l3kernel/testfiles/m3expl003.ptex.tlg
+++ b/l3kernel/testfiles/m3expl003.ptex.tlg
@@ -4437,9 +4437,9 @@ Defining \__fp_randint_wide_e:nnnn on line ...
Defining \__fp_randint_wide_e:wnnn on line ...
Defining \int_rand:nn on line ...
Defining \__fp_randint:ww on line ...
+Defining \__fp_randint_narrow:n on line ...
Defining \__fp_randint_narrow:nn on line ...
Defining \__fp_randint_narrow:nnn on line ...
-Defining \__fp_randint_narrow:nnnn on line ...
Defining \c__intarray_sp_dim on line ...
\c__intarray_sp_dim=\dimen...
Defining \g__intarray_font_int on line ...
diff --git a/l3kernel/testfiles/m3expl003.tlg b/l3kernel/testfiles/m3expl003.tlg
index dee9b8e..a6ffb80 100644
--- a/l3kernel/testfiles/m3expl003.tlg
+++ b/l3kernel/testfiles/m3expl003.tlg
@@ -4437,9 +4437,9 @@ Defining \__fp_randint_wide_e:nnnn on line ...
Defining \__fp_randint_wide_e:wnnn on line ...
Defining \int_rand:nn on line ...
Defining \__fp_randint:ww on line ...
+Defining \__fp_randint_narrow:n on line ...
Defining \__fp_randint_narrow:nn on line ...
Defining \__fp_randint_narrow:nnn on line ...
-Defining \__fp_randint_narrow:nnnn on line ...
Defining \c__intarray_sp_dim on line ...
\c__intarray_sp_dim=\dimen...
Defining \g__intarray_font_int on line ...
diff --git a/l3kernel/testfiles/m3expl003.uptex.tlg b/l3kernel/testfiles/m3expl003.uptex.tlg
index 10fcf3e..dda643b 100644
--- a/l3kernel/testfiles/m3expl003.uptex.tlg
+++ b/l3kernel/testfiles/m3expl003.uptex.tlg
@@ -4437,9 +4437,9 @@ Defining \__fp_randint_wide_e:nnnn on line ...
Defining \__fp_randint_wide_e:wnnn on line ...
Defining \int_rand:nn on line ...
Defining \__fp_randint:ww on line ...
+Defining \__fp_randint_narrow:n on line ...
Defining \__fp_randint_narrow:nn on line ...
Defining \__fp_randint_narrow:nnn on line ...
-Defining \__fp_randint_narrow:nnnn on line ...
Defining \c__intarray_sp_dim on line ...
\c__intarray_sp_dim=\dimen...
Defining \g__intarray_font_int on line ...
diff --git a/l3kernel/testfiles/m3rand001.lvt b/l3kernel/testfiles/m3rand001.lvt
index 65b588a..73f163c 100644
--- a/l3kernel/testfiles/m3rand001.lvt
+++ b/l3kernel/testfiles/m3rand001.lvt
@@ -17,7 +17,7 @@
{
\sys_gset_rand_seed:n { 0 }
\cs_new:Npn \test:n #1 { \prg_replicate:nn { 5 } { \fp_to_tl:n {#1} \NEWLINE } }
- \cs_new:Npn \test_ii:n #1 { | \prg_replicate:nn { 5 } { #1 | } \NEWLINE }
+ \cs_new:Npn \test_ii:n #1 { | \prg_replicate:nn { 15 } { #1 | } \NEWLINE }
}
{
\cs_new:Npn \test:n #1 { \fp_to_tl:n {#1} , ~ }
diff --git a/l3kernel/testfiles/m3rand001.tlg b/l3kernel/testfiles/m3rand001.tlg
index b037084..ff4d480 100644
--- a/l3kernel/testfiles/m3rand001.tlg
+++ b/l3kernel/testfiles/m3rand001.tlg
@@ -226,52 +226,52 @@ nan
============================================================
TEST 4: Random integer in a range
============================================================
-|-1|-1|1|0|-1|
-|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|
-|-2147483645|-2147483644|-2147483638|-2147483647|-2147483644|
-|-758446477|1931291650|79608793|-160587022|1579678534|
+|0|-1|0|1|0|1|0|0|-1|1|-1|0|1|1|0|
+|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|
+|-2147483638|-2147483643|-2147483642|-2147483642|-2147483642|-2147483645|-2147483641|-2147483646|-2147483646|-2147483644|-2147483647|-2147483639|-2147483642|-2147483645|-2147483646|
+|-1383802119|1847464213|1896138077|1141097059|-1805716453|303683616|630789435|83660916|1553919714|2065890169|-143934675|-1879794472|-640520242|1146446601|-1026621466|
============================================================
============================================================
TEST 5: Random tl item
============================================================
||
-|\A |\A |\A |\A |\A |
-| \B | \B | \B |\A |\A |
-|\C |{\B }|\C |\C |{\B }|
-||||||
-||||||
-||| | | |
-|\A |##|\A | |\A |
+|\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |
+|\A |\A | \B |\A | \B | \B | \B | \B | \B |\A | \B | \B | \B |\A | \B |
+|\C |\A |\C |\C |\A |{\B }|\A |{\B }|\C |{\B }|\A |\A |{\B }|\C |{\B }|
+||||||||||||||||
+||||||||||||||||
+| | | | | |||| | || | | ||
+| | | |\A |&|\A |##|##|##| |##|##|\A | |\A |
============================================================
============================================================
TEST 6: Random clist item
============================================================
||
-|\A |\A |\A |\A |\A |
-|\A |{}|{}| \B | ,|
-||||||
-|| ,| ,|||
-|&|##|##|&|##|
+|\B |\A |\A |\B |\B |\B |\A |\B |\B |\A |\B |\B |\B |\A |\B |
+|{}|\A |\A |\A |\A |\A |\A |\A |\A | \B |\A |\A |{}|\A | ,|
+||||||||||||||||
+| ,|| ,|| ,|| ,||||| ,|| ,||
+|,|,|##|,|,|\\|##|,|&|\\|\\|##|,|,|,|
============================================================
============================================================
TEST 7: Random seq item
============================================================
-||||||
-||| ,|||
-|{\\}|##|##|,|\A |
+||||||||||||||||
+| ,| ,| ,|| ,| ,| ,||| ,| ,||| ,||
+|,|\A |##|&|\A |,|\A |\A |,|##|\A |\A |##|&|##|
============================================================
============================================================
TEST 8: Random prop key/value
============================================================
-||||||
-|{\a }{\A }|{\e }{}|{\b }{{\B }}|{\b }{{\B }}|{\a }{\A }|
+||||||||||||||||
+|{\a }{\A }|{\b }{{\B }}|{\a }{\A }|{\e }{}|{\a }{\A }|{\a }{\A }|{\b }{{\B }}|{\e }{}|{\a }{\A }|{\a }{\A }|{\a }{\A }|{\e }{}|{\b }{{\B }}|{\a }{\A }|{\a }{\A }|
============================================================
============================================================
TEST 9: sys rand commands
============================================================
-1,30
-0,89
-0,79
-1,30
-1,8
+1,71
+0,25
+0,73
+1,71
+1,10
============================================================
More information about the latex3-commits
mailing list