[latex3-commits] [git/LaTeX3-latex3-latex3] master: Implement \int_rand:nn for large ranges without using floating points (a4f0d6d)

Bruno Le Floch bruno at le-floch.fr
Sun May 6 18:54:41 CEST 2018


Repository : https://github.com/latex3/latex3
On branch  : master
Link       : https://github.com/latex3/latex3/commit/a4f0d6d392214da7091172e0f21a94edcb0a39a0

>---------------------------------------------------------------

commit a4f0d6d392214da7091172e0f21a94edcb0a39a0
Author: Bruno Le Floch <bruno at le-floch.fr>
Date:   Sun May 6 12:54:41 2018 -0400

    Implement \int_rand:nn for large ranges without using floating points
    
    Now \int_rand:nn always uses exactly two random numbers from the engine.


>---------------------------------------------------------------

a4f0d6d392214da7091172e0f21a94edcb0a39a0
 l3kernel/l3fp-random.dtx                |  181 ++++++++++++++++++++++++-------
 l3kernel/l3int.dtx                      |   21 ++++
 l3kernel/l3intarray.dtx                 |   11 +-
 l3kernel/l3kernel-functions.dtx         |   43 ++++++--
 l3kernel/testfiles/m3expl001.luatex.tlg |    8 +-
 l3kernel/testfiles/m3expl001.ptex.tlg   |    8 +-
 l3kernel/testfiles/m3expl001.tlg        |    8 +-
 l3kernel/testfiles/m3expl001.uptex.tlg  |    8 +-
 l3kernel/testfiles/m3expl001.xetex.tlg  |    1 +
 l3kernel/testfiles/m3expl003.luatex.tlg |    8 +-
 l3kernel/testfiles/m3expl003.ptex.tlg   |    8 +-
 l3kernel/testfiles/m3expl003.tlg        |    8 +-
 l3kernel/testfiles/m3expl003.uptex.tlg  |    8 +-
 l3kernel/testfiles/m3expl003.xetex.tlg  |    1 +
 l3kernel/testfiles/m3rand001.tlg        |   32 +++---
 15 files changed, 279 insertions(+), 75 deletions(-)

diff --git a/l3kernel/l3fp-random.dtx b/l3kernel/l3fp-random.dtx
index 5c19766..ed22ef4 100644
--- a/l3kernel/l3fp-random.dtx
+++ b/l3kernel/l3fp-random.dtx
@@ -188,11 +188,11 @@
 % $\operatorname{ediv}(p,q)$ the \eTeX{} rounding division giving
 % $\lfloor p/q+1/2\rfloor$.  Denote by $\meta{min}$, $\meta{max}$ and
 % $R=\meta{max}-\meta{min}+1$ the arguments of \cs{int_min:nn} and the
-% number of possible outcomes.  Note that $R\in [0,2^{32}-1]$ cannot
-% necessarily be represented as an integer.  Our strategy is to get two
-% $28$-bit integers $X$ and $Y$ from the RNG, split each into $14$-bit
-% integers, as $X=X_1\times 2^{14}+X_0$ and $Y=Y_1\times 2^{14}+Y_0$
-% then return essentially
+% number of possible outcomes.  Note that $R\in [1,2^{32}-1]$ cannot
+% necessarily be represented as an integer (however, $R-2^{31}$ can).
+% Our strategy is to get two $28$-bit integers $X$ and $Y$ from the RNG,
+% split each into $14$-bit integers, as $X=X_1\times 2^{14}+X_0$ and
+% $Y=Y_1\times 2^{14}+Y_0$ then return essentially
 % $\meta{min} + \lfloor R (X_1\times 2^{-14} + Y_1\times 2^{-28} +
 % Y_0\times 2^{-42} + X_0\times 2^{-56})\rfloor$.  For small~$R$ the
 % $X_0$ term has a tiny effect so we ignore it and we can compute
@@ -205,23 +205,43 @@
 %   ensures that the number obtained before the shift and division is at
 %   most $2^{17}(2^{14}-1)+(2^{17}-1)=\cs{c_max_int}$.  The
 %   non-uniformity is at most of order $2^{17}/2^{42} = 2^{-25}$.
-% \item Since it is not clear that the plan outlined in the following
-%   paragraph has good uniformity, we implement large ranges directly in
-%   terms of the floating point |randint|.
-%
-%   Earlier plan: \enquote{Otherwise,
-%   split $R=R_2\times 2^{28}+R_1\times 2^{14}+R_0$,
-%   precompute $R_{21}=R_2\times 2^{14}+R_1$ and
-%   $R_{10}=R_1\times 2^{14}+R_0$ and $Z = X_1\times 2^{14}+Y_1$.  Then
-%   compute on the one hand
-%   $\meta{min}+8\times Z+(R_2-8)\times Z+R_1\times X_1$ (where the
-%   weird split of $R_2\times Z$ avoids a possible overflow) and
-%   $\operatorname{ediv}(R_2\times Y_0 + R_0\times X_1 +
-%   \operatorname{ediv}(R_{21}\times X_0,2^{28}) +
-%   \operatorname{ediv}(R_{10}\times Y,2^{28}),2^{14})$ then sum them
-%   (this may give $2^{31}$, an overflow).  If the result is greater
-%   than $\meta{max}$ (in particular if it overflows) then replace it by
-%   $\meta{min}$.}
+% \item Split $R=R_2\times 2^{28}+R_1\times 2^{14}+R_0$, where
+%   $R_2\in [0,15]$.  Compute
+%   $\meta{min} + R_2 X_1 2^{14} + (R_2 Y_1 + R_1 X_1) +
+%   \operatorname{ediv}(R_2 Y_0 + R_1 Y_1 + R_0 X_1 +
+%   \operatorname{ediv}(R_2 X_0 + R_0 Y_1 + \operatorname{ediv}((2^{14}
+%   R_1 + R_0) (2^{14} Y_0 + X_0), 2^{28}), 2^{14}), 2^{14})$ then map a
+%   result of $\meta{max}+1$ to $\meta{min}$.  Writing each
+%   $\operatorname{ediv}$ in terms of truncated division with a shift,
+%   and using
+%   $\lfloor(p+\lfloor r/s\rfloor)/q\rfloor =
+%   \lfloor(ps+r)/(sq)\rfloor$, what we compute is equal to
+%   $\lfloor\meta{exact}+2^{-29}+2^{-15}+2^{-1}\rfloor$ with
+%   $\meta{exact}=\meta{min} + R \times 0.X_1Y_1Y_0X_0$.  Given we map
+%   $\meta{max}+1$ to $\meta{min}$, the shift has no effect on
+%   uniformity.  The non-uniformity is bounded by $2^{56}/R<2^{24}$.  It
+%   may be possible to speed up the code by dropping tiny terms such as
+%   $R_0 X_0$, but the analysis of non-uniformity proves too difficult.
+%
+%   To avoid the overflow when the computation yields $\meta{max}+1$
+%   with $\meta{max}=2^{31}-1$ (note that $R$ is then arbitrary), we
+%   compute the result in two pieces.  Compute
+%   $\meta{first} = \meta{min} + R_2 X_1 2^{14}$ if $R_2<8$ or
+%   $\meta{min} + 8 X_1 2^{14} + (R_2-8) X_1 2^{14}$ if $R_2\geq 8$, the
+%   expressions being chosen to avoid overflow.  Compute
+%   $\meta{second} = R_2 Y_1 + R_1 X_1 + \operatorname{ediv}({\dots})$,
+%   at most
+%   $R_2 2^{14} + R_1 2^{14} + R_0\leq 2^{28} + 15\times 2^{14} - 1$,
+%   not at risk of overflowing.  We have
+%   $\meta{first}+\meta{second}=\meta{max}+1=\meta{min}+R$ if and only
+%   if $\meta{second} = R1 2^{14} + R_0 + R_2 2^{14}$ and
+%   $2^{14} R_2 X_1 = 2^{28} R_2 - 2^{14} R_2$ (namely $R_2=0$ or
+%   $X_1=2^{14}-1$).  In that case, return \meta{min}, otherwise return
+%   $\meta{first}+\meta{second}$, which is safe because it is at most
+%   \meta{max}.  Note that the decision of what to return does not need
+%   \meta{first} explicitly so we don't actually compute it, just put it
+%   in an integer expression in which \meta{second} is eventually added
+%   (or not).
 % \item To get a floating point number in $[0,1)$ just call the
 %   $R=10000\leq 2^{17}$ procedure above to produce four blocks of four
 %   digits.
@@ -240,17 +260,16 @@
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{macro}[EXP]{\__kernel_randint:nn}
-%   Used in an integer expression, \cs{__kernel_randint:nn} \Arg{min}
-%   |{|$R$|}| gives a random number
+% \begin{macro}[EXP]{\__kernel_randint:n}
+%   Used in an integer expression, \cs{__kernel_randint:n} |{|$R$|}|
+%   gives a random number
 %   $\lfloor(R\operatorname{random}(2^{14}) +
-%   \operatorname{random}(R))/2^{14}\rfloor$.  that is between
-%   \meta{min} and $\meta{min}+R-1$ inclusive.
+%   \operatorname{random}(R))/2^{14}\rfloor$ that is in $[0,R-1]$.
 %    \begin{macrocode}
-    \cs_new:Npn \__kernel_randint:nn #1#2
+    \cs_new:Npn \__kernel_randint:n #1
       {
-        #1 + (#2 * \tex_uniformdeviate:D 1 6384
-              + \tex_uniformdeviate:D #2 - 8192 ) / 16384
+        (#1 * \tex_uniformdeviate:D 1 6384
+        + \tex_uniformdeviate:D #1 - 8192 ) / 16384
       }
 %    \end{macrocode}
 % \end{macro}
@@ -269,8 +288,8 @@
       {
         #1
         \exp_after:wN \@@_rand_myriads_get:w
-        \int_value:w \@@_int_eval:w
-          \__kernel_randint:nn { 10000 } { 10000 }
+        \int_value:w \@@_int_eval:w 10000 +
+          \__kernel_randint:n { 10000 }
         \@@_rand_myriads_loop:w
       }
     \cs_new:Npn \@@_rand_myriads_get:w 1 #1 ; { ; {#1} }
@@ -454,9 +473,9 @@
 %   bound~|#1| is more than the upper bound~|#2|.  Then determine
 %   whether the range is narrower than \cs{c__kernel_randint_max_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{__kernel_randint:nn} |{#1}| \Arg{choices} where
-%   \meta{choices} is the number of possible outcomes.
+%   If the range is narrow, call \cs{__kernel_randint:n} \Arg{choices}
+%   where \meta{choices} is the number of possible outcomes.  If the
+%   range is wide, use somewhat slower code.
 %    \begin{macrocode}
     \cs_new:Npn \int_rand:nn #1#2
       {
@@ -482,16 +501,100 @@
               \fi:
               \c__kernel_randint_max_int
               \@@_int_eval_end:
-            \__kernel_randint:nn {#1}
+            #1 +
+            \__kernel_randint:n
               { \@@_int_eval:w #2 - #1 + 1 \@@_int_eval_end: }
           \else:
-            \fp_to_int:n { randint(#1,#2) }
+            \__kernel_randint:nn {#1} {#2}
           \fi:
         \fi:
       }
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}
+%   {
+%     \__kernel_randint:nn, \@@_randint_split_o:Nw, \@@_randint_split_aux:w,
+%     \@@_randinat_wide_aux:w, \@@_randinat_wide_auxii:w,
+%   }
+%   Any $n\in[-2^{31}+1,2^{31}-1]$ is uniquely written as
+%   $2^{14}n_1+n_2$ with $n_1\in[-2^{17},2^{17}-1]$ and
+%   $n_2\in[0,2^{14}-1]$.  Calling \cs{@@_randint_split_o:Nw} $n$ |;|
+%   gives $n_1$|;| $n_2$|;| and expands the next token once.  We do this
+%   for two random numbers and apply \cs{@@_randint_split_o:Nw} twice to
+%   fully decompose the range~$R$.  One subtlety is that we compute
+%   $R-2^{31}=\meta{max}-\meta{min}-(2^{31}-1)\in[-2^{31}+1,2^{31}-1]$
+%   rather than $R$ to avoid overflow.
+%
+%   Then we have \cs{@@_randint_wide_aux:w} \meta{X_1}|;|\meta{X_0}|;|
+%   \meta{Y_1}|;|\meta{Y_0}|;| \meta{R_2}|;|\meta{R_1}|;|\meta{R_0}|;.|
+%   and we apply the algorithm described earlier.
+%    \begin{macrocode}
+    \cs_new:Npn \__kernel_randint:nn #1#2
+      {
+        #1
+        \exp_after:wN \@@_randint_wide_aux:w
+        \int_value:w
+          \exp_after:wN \@@_randint_split_o:Nw
+          \tex_uniformdeviate:D 268435456 ;
+        \int_value:w
+          \exp_after:wN \@@_randint_split_o:Nw
+          \tex_uniformdeviate:D 268435456 ;
+        \int_value:w
+          \exp_after:wN \@@_randint_split_o:Nw
+          \int_value:w \@@_int_eval:w 131072 +
+            \exp_after:wN \@@_randint_split_o:Nw
+            \int_value:w
+              \__kernel_int_add:nnn {#2} { -#1 } { -\c_max_int } ;
+        .
+      }
+    \cs_new:Npn \@@_randint_split_o:Nw #1#2 ;
+      {
+        \if_meaning:w 0 #1
+          0 \exp_after:wN ; \int_value:w 0
+        \else:
+          \exp_after:wN \@@_randint_split_aux:w
+          \int_value:w \@@_int_eval:w (#1#2 - 8192) / 16384 ;
+          + #1#2
+        \fi:
+        \exp_after:wN ;
+      }
+    \cs_new:Npn \@@_randint_split_aux:w #1 ;
+      {
+        #1 \exp_after:wN ;
+        \int_value:w \@@_int_eval:w - #1 * 16384
+      }
+    \cs_new:Npn \@@_randint_wide_aux:w #1;#2; #3;#4; #5;#6;#7; .
+      {
+        \exp_after:wN \@@_randint_wide_auxii:w
+        \int_value:w \@@_int_eval:w #5 * #3 + #6 * #1 +
+          (#5 * #4 + #6 * #3 + #7 * #1 +
+           (#5 * #2 +           #7 * #3 +
+            (16384 * #6 + #7) * (16384 * #4 + #2) / 268435456) / 16384
+          ) / 16384 \exp_after:wN ;
+        \int_value:w \@@_int_eval:w (#5 + #6) * 16384 + #7 ;
+        #1 ; #5 ;
+      }
+    \cs_new:Npn \@@_randint_wide_auxii:w #1; #2; #3; #4;
+      {
+        \if_int_odd:w 0
+            \if_int_compare:w #1 = #2 \else: \exp_stop_f: \fi:
+            \if_int_compare:w #4 = \c_zero 1 \fi:
+            \if_int_compare:w #3 = 16383 ~ 1 \fi:
+            \exp_stop_f:
+          \exp_after:wN \prg_break:
+        \fi:
+        \if_int_compare:w #4 < 8 \exp_stop_f:
+          + #4 * #3 * 16384
+        \else:
+          + 8 * #3 * 16384 + (#4 - 8) * #3 * 16384
+        \fi:
+        + #1
+        \prg_break_point:
+      }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\int_rand:n, \@@_randint:n}
 %   Similar to \cs{int_rand:nn}, but needs fewer checks.
 %    \begin{macrocode}
@@ -508,9 +611,9 @@
           \@@_randint:ww #1; 1;
         \else:
           \if_int_compare:w #1 > \c__kernel_randint_max_int
-            \fp_to_int:n { randint(#1) }
+            \__kernel_randint:nn { 1 } {#1}
           \else:
-            \__kernel_randint:nn {1} {#1}
+            1 + \__kernel_randint:n {#1}
           \fi:
         \fi:
       }
diff --git a/l3kernel/l3int.dtx b/l3kernel/l3int.dtx
index bfff6b4..1942f11 100644
--- a/l3kernel/l3int.dtx
+++ b/l3kernel/l3int.dtx
@@ -1178,6 +1178,27 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}[EXP]{\__kernel_int_add:nnn}
+%   Equivalent to \cs{int_eval:n} |{#1+#2+#3}| except that overflow only
+%   occurs if the final result overflows $[-2^{31}+1,2^{31}-1]$.  The
+%   idea is to choose the order in which the three numbers are added
+%   together.  If |#1| and |#2| have opposite signs (one is in
+%   $[-2^{31}+1,-1]$ and the other in $[0,2^{31}-1]$) then |#1+#2|
+%   cannot overflow so we compute the result as |#1+#2+#3|.  If they
+%   have the same sign, then either |#3| has the same sign and the order
+%   does not matter, or |#3| has the opposite sign and any order in
+%   which |#3| is not last will work.  We use |#1+#3+#2|.
+%    \begin{macrocode}
+\cs_new:Npn \__kernel_int_add:nnn #1#2#3
+  {
+    \int_value:w \@@_eval:w #1
+      \if_int_compare:w #2 < \c_zero \exp_after:wN \reverse_if:N \fi:
+      \if_int_compare:w #1 < \c_zero + #2 + #3 \else: + #3 + #2 \fi:
+    \@@_eval_end:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \subsection{Creating and initialising integers}
 %
 % \begin{macro}{\int_new:N, \int_new:c}
diff --git a/l3kernel/l3intarray.dtx b/l3kernel/l3intarray.dtx
index b54d706..5b2ea16 100644
--- a/l3kernel/l3intarray.dtx
+++ b/l3kernel/l3intarray.dtx
@@ -461,8 +461,8 @@
 %   avoid a spurious \enquote{at position \texttt{\#1}} part in the
 %   error message.  Then calculate the number of choices: this is at
 %   most $(2^{30}-1)-(-(2^{30}-1))+1=2^{31}-1$, which just barely does
-%   not overflow.  For small ranges use \cs{__kernel_randint:nn},
-%   otherwise use the (very much slower) floating point |randint|.
+%   not overflow.  For small ranges use \cs{__kernel_randint:n},
+%   otherwise \cs{__kernel_randint:nn}.
 %   Finally, if there are no random numbers do not define any of the
 %   auxiliaries.
 %    \begin{macrocode}
@@ -504,10 +504,13 @@
         \exp_args:NNf \@@_gset_all_same:Nn #1
           {
             \int_compare:nNnTF {#2} > \c__kernel_randint_max_int
-              { \exp_stop_f: \fp_to_int:n { randint(#3,#4) } }
               {
                 \exp_stop_f:
-                \int_eval:n { \__kernel_randint:nn {#3} {#2} }
+                \int_eval:n { \__kernel_randint:nn {#3} {#4} }
+              }
+              {
+                \exp_stop_f:
+                \int_eval:n { #3 + \__kernel_randint:n {#2} }
               }
           }
       }
diff --git a/l3kernel/l3kernel-functions.dtx b/l3kernel/l3kernel-functions.dtx
index 0883990..b857e18 100644
--- a/l3kernel/l3kernel-functions.dtx
+++ b/l3kernel/l3kernel-functions.dtx
@@ -199,6 +199,18 @@
 %   in package mode, where interfacing with the \LaTeXe{} kernel is necessary.
 % \end{function}
 %
+% \begin{function}[EXP]{\__kernel_int_add:nnn}
+%   \begin{syntax}
+%     \cs{__kernel_int_add:nnn} \Arg{integer_1} \Arg{integer_2} \Arg{integer_3}
+%   \end{syntax}
+%   Expands to the result of adding the three \meta{integers} (which
+%   must be suitable input for \cs{int_eval:w}), avoiding intermediate
+%   overflow.  Overflow occurs only if the overall result is outside
+%   $[-2^{31}+1,2^{31}-1]$.  The \meta{integers} may be of the form
+%   \cs{int_eval:w} \dots{} \cs{scan_stop:} but may be evaluated more
+%   than once.
+% \end{function}
+%
 % \begin{function}{\__kernel_ior_open:Nn, \__kernel_ior_open:No}
 %   \begin{syntax}
 %     \cs{__kernel_ior_open:Nn} \meta{stream} \Arg{file name}
@@ -429,19 +441,34 @@
 %   and variable mappings.
 % \end{variable}
 %
-% \begin{function}{\__kernel_randint:nn}
+% \begin{variable}{\c__kernel_randint_max_int}
+%   Maximal allowed argument to \cs{__kernel_randint:n}.  Equal to
+%   $2^{17}$.
+% \end{variable}
+%
+% \begin{function}{\__kernel_randint:n}
 %   \begin{syntax}
-%     \cs{__kernel_randint:nn} \Arg{min} \Arg{choices}
+%     \cs{__kernel_randint:n} \Arg{choices}
 %   \end{syntax}
 %   Used in an integer expression this gives a pseudo-random number
-%   between \meta{min} and $\meta{min} + \meta{choices} - 1$ included.
-%   One must have $\meta{choices}\leq 2^{17}$.
+%   between $0$ and $\meta{choices} - 1$ included.  One must have
+%   $\meta{choices}\leq 2^{17}$.  The \meta{choices} must be suitable
+%   for \cs{int_value:w} (and any \cs{int_eval:w} must be terminated by
+%   \cs{scan_stop:} or equivalent).
 % \end{function}
 %
-% \begin{variable}{\c__kernel_randint_max_int}
-%   Maximal allowed second argument to \cs{__kernel_randint:nn}.  Equal
-%   to $2^{17}$.
-% \end{variable}
+% \begin{function}{\__kernel_randint:nn}
+%   \begin{syntax}
+%     \cs{__kernel_randint:nn} \Arg{min} \Arg{max}
+%   \end{syntax}
+%   Used in an integer expression this gives a pseudo-random number
+%   between $\meta{min}$ and $\meta{max}$ included.  The \meta{min} and
+%   \meta{max} must be suitable for \cs{int_value:w} (and any
+%   \cs{int_eval:w} must be terminated by \cs{scan_stop:} or
+%   equivalent).  For small ranges
+%   $R=\meta{max}-\meta{min}+1\leq 2^{17}$,
+%   $\meta{min} + \cs{__kernel_randint:n} |{|R|}|$ is faster.
+% \end{function}
 %
 % \begin{function}{\__kernel_register_show:N, \__kernel_register_show:c}
 %   \begin{syntax}
diff --git a/l3kernel/testfiles/m3expl001.luatex.tlg b/l3kernel/testfiles/m3expl001.luatex.tlg
index 52e6cc6..9366adb 100644
--- a/l3kernel/testfiles/m3expl001.luatex.tlg
+++ b/l3kernel/testfiles/m3expl001.luatex.tlg
@@ -1256,6 +1256,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
@@ -4236,7 +4237,7 @@ Defining \__fp_array_to_clist_loop:Nw on line ...
 Defining \__fp_parse_word_rand:N on line ...
 Defining \__fp_parse_word_randint:N on line ...
 Defining \c__kernel_randint_max_int on line ...
-Defining \__kernel_randint:nn on line ...
+Defining \__kernel_randint:n on line ...
 Defining \__fp_rand_myriads:n on line ...
 Defining \__fp_rand_myriads_loop:w on line ...
 Defining \__fp_rand_myriads_get:w on line ...
@@ -4253,6 +4254,11 @@ Defining \__fp_randint_auxiv_o:ww on line ...
 Defining \__fp_randint_auxv_o:w on line ...
 Defining \int_rand:nn on line ...
 Defining \__fp_randint:ww on line ...
+Defining \__kernel_randint:nn on line ...
+Defining \__fp_randint_split_o:Nw on line ...
+Defining \__fp_randint_split_aux:w on line ...
+Defining \__fp_randint_wide_aux:w on line ...
+Defining \__fp_randint_wide_auxii:w on line ...
 Defining \int_rand:n on line ...
 Defining \__fp_randint:n on line ...
 Defining \g__fp_array_int on line ...
diff --git a/l3kernel/testfiles/m3expl001.ptex.tlg b/l3kernel/testfiles/m3expl001.ptex.tlg
index 3bb58be..b54ae48 100644
--- a/l3kernel/testfiles/m3expl001.ptex.tlg
+++ b/l3kernel/testfiles/m3expl001.ptex.tlg
@@ -1254,6 +1254,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
@@ -4491,7 +4492,7 @@ Defining \__fp_parse_word_rand:N on line ...
 Defining \__fp_parse_word_randint:N on line ...
 Defining \c__kernel_randint_max_int on line ...
 \c__kernel_randint_max_int=\count...
-Defining \__kernel_randint:nn on line ...
+Defining \__kernel_randint:n on line ...
 Defining \__fp_rand_myriads:n on line ...
 Defining \__fp_rand_myriads_loop:w on line ...
 Defining \__fp_rand_myriads_get:w on line ...
@@ -4508,6 +4509,11 @@ Defining \__fp_randint_auxiv_o:ww on line ...
 Defining \__fp_randint_auxv_o:w on line ...
 Defining \int_rand:nn on line ...
 Defining \__fp_randint:ww on line ...
+Defining \__kernel_randint:nn on line ...
+Defining \__fp_randint_split_o:Nw on line ...
+Defining \__fp_randint_split_aux:w on line ...
+Defining \__fp_randint_wide_aux:w on line ...
+Defining \__fp_randint_wide_auxii:w on line ...
 Defining \int_rand:n on line ...
 Defining \__fp_randint:n on line ...
 Defining \g__fp_array_int on line ...
diff --git a/l3kernel/testfiles/m3expl001.tlg b/l3kernel/testfiles/m3expl001.tlg
index 06cf5f3..4b0b1cd 100644
--- a/l3kernel/testfiles/m3expl001.tlg
+++ b/l3kernel/testfiles/m3expl001.tlg
@@ -1254,6 +1254,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
@@ -4491,7 +4492,7 @@ Defining \__fp_parse_word_rand:N on line ...
 Defining \__fp_parse_word_randint:N on line ...
 Defining \c__kernel_randint_max_int on line ...
 \c__kernel_randint_max_int=\count...
-Defining \__kernel_randint:nn on line ...
+Defining \__kernel_randint:n on line ...
 Defining \__fp_rand_myriads:n on line ...
 Defining \__fp_rand_myriads_loop:w on line ...
 Defining \__fp_rand_myriads_get:w on line ...
@@ -4508,6 +4509,11 @@ Defining \__fp_randint_auxiv_o:ww on line ...
 Defining \__fp_randint_auxv_o:w on line ...
 Defining \int_rand:nn on line ...
 Defining \__fp_randint:ww on line ...
+Defining \__kernel_randint:nn on line ...
+Defining \__fp_randint_split_o:Nw on line ...
+Defining \__fp_randint_split_aux:w on line ...
+Defining \__fp_randint_wide_aux:w on line ...
+Defining \__fp_randint_wide_auxii:w on line ...
 Defining \int_rand:n on line ...
 Defining \__fp_randint:n on line ...
 Defining \g__fp_array_int on line ...
diff --git a/l3kernel/testfiles/m3expl001.uptex.tlg b/l3kernel/testfiles/m3expl001.uptex.tlg
index a81e100..c31e3b7 100644
--- a/l3kernel/testfiles/m3expl001.uptex.tlg
+++ b/l3kernel/testfiles/m3expl001.uptex.tlg
@@ -1254,6 +1254,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
@@ -4490,7 +4491,7 @@ Defining \__fp_array_to_clist_loop:Nw on line ...
 Defining \__fp_parse_word_rand:N on line ...
 Defining \__fp_parse_word_randint:N on line ...
 Defining \c__kernel_randint_max_int on line ...
-Defining \__kernel_randint:nn on line ...
+Defining \__kernel_randint:n on line ...
 Defining \__fp_rand_myriads:n on line ...
 Defining \__fp_rand_myriads_loop:w on line ...
 Defining \__fp_rand_myriads_get:w on line ...
@@ -4507,6 +4508,11 @@ Defining \__fp_randint_auxiv_o:ww on line ...
 Defining \__fp_randint_auxv_o:w on line ...
 Defining \int_rand:nn on line ...
 Defining \__fp_randint:ww on line ...
+Defining \__kernel_randint:nn on line ...
+Defining \__fp_randint_split_o:Nw on line ...
+Defining \__fp_randint_split_aux:w on line ...
+Defining \__fp_randint_wide_aux:w on line ...
+Defining \__fp_randint_wide_auxii:w on line ...
 Defining \int_rand:n on line ...
 Defining \__fp_randint:n on line ...
 Defining \g__fp_array_int on line ...
diff --git a/l3kernel/testfiles/m3expl001.xetex.tlg b/l3kernel/testfiles/m3expl001.xetex.tlg
index 69f7e2e..21685eb 100644
--- a/l3kernel/testfiles/m3expl001.xetex.tlg
+++ b/l3kernel/testfiles/m3expl001.xetex.tlg
@@ -1254,6 +1254,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
diff --git a/l3kernel/testfiles/m3expl003.luatex.tlg b/l3kernel/testfiles/m3expl003.luatex.tlg
index 52e6cc6..9366adb 100644
--- a/l3kernel/testfiles/m3expl003.luatex.tlg
+++ b/l3kernel/testfiles/m3expl003.luatex.tlg
@@ -1256,6 +1256,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
@@ -4236,7 +4237,7 @@ Defining \__fp_array_to_clist_loop:Nw on line ...
 Defining \__fp_parse_word_rand:N on line ...
 Defining \__fp_parse_word_randint:N on line ...
 Defining \c__kernel_randint_max_int on line ...
-Defining \__kernel_randint:nn on line ...
+Defining \__kernel_randint:n on line ...
 Defining \__fp_rand_myriads:n on line ...
 Defining \__fp_rand_myriads_loop:w on line ...
 Defining \__fp_rand_myriads_get:w on line ...
@@ -4253,6 +4254,11 @@ Defining \__fp_randint_auxiv_o:ww on line ...
 Defining \__fp_randint_auxv_o:w on line ...
 Defining \int_rand:nn on line ...
 Defining \__fp_randint:ww on line ...
+Defining \__kernel_randint:nn on line ...
+Defining \__fp_randint_split_o:Nw on line ...
+Defining \__fp_randint_split_aux:w on line ...
+Defining \__fp_randint_wide_aux:w on line ...
+Defining \__fp_randint_wide_auxii:w on line ...
 Defining \int_rand:n on line ...
 Defining \__fp_randint:n on line ...
 Defining \g__fp_array_int on line ...
diff --git a/l3kernel/testfiles/m3expl003.ptex.tlg b/l3kernel/testfiles/m3expl003.ptex.tlg
index 3bb58be..b54ae48 100644
--- a/l3kernel/testfiles/m3expl003.ptex.tlg
+++ b/l3kernel/testfiles/m3expl003.ptex.tlg
@@ -1254,6 +1254,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
@@ -4491,7 +4492,7 @@ Defining \__fp_parse_word_rand:N on line ...
 Defining \__fp_parse_word_randint:N on line ...
 Defining \c__kernel_randint_max_int on line ...
 \c__kernel_randint_max_int=\count...
-Defining \__kernel_randint:nn on line ...
+Defining \__kernel_randint:n on line ...
 Defining \__fp_rand_myriads:n on line ...
 Defining \__fp_rand_myriads_loop:w on line ...
 Defining \__fp_rand_myriads_get:w on line ...
@@ -4508,6 +4509,11 @@ Defining \__fp_randint_auxiv_o:ww on line ...
 Defining \__fp_randint_auxv_o:w on line ...
 Defining \int_rand:nn on line ...
 Defining \__fp_randint:ww on line ...
+Defining \__kernel_randint:nn on line ...
+Defining \__fp_randint_split_o:Nw on line ...
+Defining \__fp_randint_split_aux:w on line ...
+Defining \__fp_randint_wide_aux:w on line ...
+Defining \__fp_randint_wide_auxii:w on line ...
 Defining \int_rand:n on line ...
 Defining \__fp_randint:n on line ...
 Defining \g__fp_array_int on line ...
diff --git a/l3kernel/testfiles/m3expl003.tlg b/l3kernel/testfiles/m3expl003.tlg
index 06cf5f3..4b0b1cd 100644
--- a/l3kernel/testfiles/m3expl003.tlg
+++ b/l3kernel/testfiles/m3expl003.tlg
@@ -1254,6 +1254,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
@@ -4491,7 +4492,7 @@ Defining \__fp_parse_word_rand:N on line ...
 Defining \__fp_parse_word_randint:N on line ...
 Defining \c__kernel_randint_max_int on line ...
 \c__kernel_randint_max_int=\count...
-Defining \__kernel_randint:nn on line ...
+Defining \__kernel_randint:n on line ...
 Defining \__fp_rand_myriads:n on line ...
 Defining \__fp_rand_myriads_loop:w on line ...
 Defining \__fp_rand_myriads_get:w on line ...
@@ -4508,6 +4509,11 @@ Defining \__fp_randint_auxiv_o:ww on line ...
 Defining \__fp_randint_auxv_o:w on line ...
 Defining \int_rand:nn on line ...
 Defining \__fp_randint:ww on line ...
+Defining \__kernel_randint:nn on line ...
+Defining \__fp_randint_split_o:Nw on line ...
+Defining \__fp_randint_split_aux:w on line ...
+Defining \__fp_randint_wide_aux:w on line ...
+Defining \__fp_randint_wide_auxii:w on line ...
 Defining \int_rand:n on line ...
 Defining \__fp_randint:n on line ...
 Defining \g__fp_array_int on line ...
diff --git a/l3kernel/testfiles/m3expl003.uptex.tlg b/l3kernel/testfiles/m3expl003.uptex.tlg
index a81e100..c31e3b7 100644
--- a/l3kernel/testfiles/m3expl003.uptex.tlg
+++ b/l3kernel/testfiles/m3expl003.uptex.tlg
@@ -1254,6 +1254,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
@@ -4490,7 +4491,7 @@ Defining \__fp_array_to_clist_loop:Nw on line ...
 Defining \__fp_parse_word_rand:N on line ...
 Defining \__fp_parse_word_randint:N on line ...
 Defining \c__kernel_randint_max_int on line ...
-Defining \__kernel_randint:nn on line ...
+Defining \__kernel_randint:n on line ...
 Defining \__fp_rand_myriads:n on line ...
 Defining \__fp_rand_myriads_loop:w on line ...
 Defining \__fp_rand_myriads_get:w on line ...
@@ -4507,6 +4508,11 @@ Defining \__fp_randint_auxiv_o:ww on line ...
 Defining \__fp_randint_auxv_o:w on line ...
 Defining \int_rand:nn on line ...
 Defining \__fp_randint:ww on line ...
+Defining \__kernel_randint:nn on line ...
+Defining \__fp_randint_split_o:Nw on line ...
+Defining \__fp_randint_split_aux:w on line ...
+Defining \__fp_randint_wide_aux:w on line ...
+Defining \__fp_randint_wide_auxii:w on line ...
 Defining \int_rand:n on line ...
 Defining \__fp_randint:n on line ...
 Defining \g__fp_array_int on line ...
diff --git a/l3kernel/testfiles/m3expl003.xetex.tlg b/l3kernel/testfiles/m3expl003.xetex.tlg
index 69f7e2e..21685eb 100644
--- a/l3kernel/testfiles/m3expl003.xetex.tlg
+++ b/l3kernel/testfiles/m3expl003.xetex.tlg
@@ -1254,6 +1254,7 @@ Defining \__int_div_truncate:NwNw on line ...
 Defining \int_div_round:nn on line ...
 Defining \int_mod:nn on line ...
 Defining \__int_mod:ww on line ...
+Defining \__kernel_int_add:nnn on line ...
 Defining \int_new:N on line ...
 Defining \int_new:c on line ...
 Defining \int_const:Nn on line ...
diff --git a/l3kernel/testfiles/m3rand001.tlg b/l3kernel/testfiles/m3rand001.tlg
index 1fe6112..d9d25f8 100644
--- a/l3kernel/testfiles/m3rand001.tlg
+++ b/l3kernel/testfiles/m3rand001.tlg
@@ -229,42 +229,42 @@ TEST 4: Random integer in a range
 |-1|1|-1|1|0|0|1|-1|1|0|1|1|-1|-1|1|
 |-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|-2147483647|
 |-2147483645|-2147483647|-2147483645|-2147483639|-2147483646|-2147483641|-2147483637|-2147483641|-2147483637|-2147483643|-2147483639|-2147483642|-2147483644|-2147483637|-2147483645|
-|-596602719|-440743317|1859629516|1035797053|-83292061|1733661836|-1455563191|-1354595511|1588647823|215900686|-1947340226|-1997076099|-1997696982|378940000|1354742325|
+|-596581922|1829512184|-11249077|167662723|1619170613|-591422440|-440749724|1350338119|2054692807|-1880919426|-973590519|645137860|1859361099|1234117834|925471348|
 ============================================================
 ============================================================
 TEST 5: Random tl item
 ============================================================
 ||
 |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |\A |
-| \B |\A |\A |\A | \B |\A |\A |\A | \B |\A | \B |\A |\A | \B |\A |
-|{\B }|{\B }|\C |\A |{\B }|\A |\A |\C |\A |{\B }|\C |\C |\A |{\B }|\A |
+| \B |\A |\A |\A | \B |\A |\A |\A | \B | \B | \B | \B |\A |\A | \B |
+|\C |\A |\C |\C |\C |{\B }|\A |\A |\A |{\B }|\C |{\B }|\C |{\B }|{\B }|
 ||||||||||||||||
 ||||||||||||||||
-| | || | |||| | | | || ||
-|\A |&| |&|&|##|&|&| |\A |##| |##|&| |
+| || | | || | || | | | |||
+|&| |&|&|##|##|&| | | |##| |\A | | |
 ============================================================
 ============================================================
 TEST 6: Random clist item
 ============================================================
 ||
-|\A |\B |\A |\B |\A |\A |\A |\B |\A |\B |\A |\A |\A |\B |\B |
-| ,|\A |\A | \B |{}|\A | ,|{}| \B | \B |\A |\A | ,| \B | \B |
+|\A |\B |\B |\A |\A |\A |\B |\A |\B |\B |\A |\B |\A |\B |\A |
+| \B |\A | ,| ,|{}|\A | ,| ,| \B | ,| \B |\A |\A |{}|\A |
 ||||||||||||||||
-| ,| ,|| ,| ,| ,| ,| ,|| ,| ,| ,|| ,||
-|##|##|,|,|##|##|##|&|\A |,|\A |,|\\|\A |&|
+|||| ,| ,| ,| ,|| ,|||| ,| ,| ,|
+|##|##|\\|&|##|,|,|,|\A |##|\A |&|,|\A |\\|
 ============================================================
 ============================================================
 TEST 7: Random seq item
 ============================================================
 ||||||||||||||||
-| ,|| ,| ,| ,||||| ,|| ,| ,|||
-|\A |,|##|{\\}|\A |\A |\A |##|{\\}|,|##|\A |&|,|&|
+| ,||||| ,|||| ,| ,|| ,|||
+|\A |{\\}|\A |&|\A |##|\A |&|\A |,|##|\A |##|{\\}|,|
 ============================================================
 ============================================================
 TEST 8: Random prop key/value
 ============================================================
 ||||||||||||||||
-|{\b }{{\B }}|{\a }{\A }|{\b }{{\B }}|{\b }{{\B }}|{\a }{\A }|{\a }{\A }|{\e }{}|{\a }{\A }|{\e }{}|{\e }{}|{\a }{\A }|{\e }{}|{\b }{{\B }}|{\e }{}|{\b }{{\B }}|
+|{\e }{}|{\e }{}|{\a }{\A }|{\b }{{\B }}|{\b }{{\B }}|{\a }{\A }|{\e }{}|{\b }{{\B }}|{\b }{{\B }}|{\a }{\A }|{\e }{}|{\a }{\A }|{\e }{}|{\a }{\A }|{\a }{\A }|
 ============================================================
 ============================================================
 TEST 9: sys rand commands
@@ -288,9 +288,9 @@ misspelled it (e.g., `\hobx'), type `I' and the correct
 spelling (e.g., `I\hbox'). Otherwise just continue,
 and I'll forget about whatever was undefined.
 0
-|1226983952|2137676231|708840819|1697269430|585282601|1640562914|568795804|124937418|1811019699|262907525|625094442|1065693082|1052955123|921192786|389984657|
+|1226726384|1265411165|1466672355|1314947273|1555392836|894057289|2137710626|710093757|1198929759|1627898431|721692715|464072634|708598373|1712025573|1781216300|
 |1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|
-|2|10|7|9|6|11|10|6|6|2|4|1|3|1|2|
+|9|6|10|4|6|10|3|8|7|1|6|2|1|9|10|
 ============================================================
 ============================================================
 TEST 11: Random intarray item
@@ -314,12 +314,12 @@ misspelled it (e.g., `\hobx'), type `I' and the correct
 spelling (e.g., `I\hbox'). Otherwise just continue,
 and I'll forget about whatever was undefined.
 0
-|3|1|3|1|3|3|3|1|3|1|3|3|1|3|1|
+|1|3|1|3|3|3|1|3|3|3|3|3|3|3|3|
 ============================================================
 Defining \g_testb_intarray on line ...
 ============================================================
 TEST 12: Random intarray contents
 ============================================================
 -1,0,2,-2,2,-1,2,-2,3,-1,3,2,0,4,5
-820649670,-76691285,-492843675,964914867,-36140785,421358030,-646354023,1060444501,-447645417,267975480,-671975694,-407769766,-332046542,-666077711,1040688595
+820580739,-112220571,-698712122,-22653540,596754623,569851830,-76814189,812455767,554030471,858568271,-761913564,-698174727,-492774578,-1035763579,1060453552
 ============================================================





More information about the latex3-commits mailing list