% \iffalse meta-comment % %% File: l3fp-random.dtx Copyright (C) 2016 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this %% license or (at your option) any later version. The latest version %% of this license is in the file %% %% http://www.latex-project.org/lppl.txt %% %% This file is part of the "l3kernel bundle" (The Work in LPPL) %% and all files in that bundle must be distributed together. %% %% The released version of this bundle is available from CTAN. %% %% ----------------------------------------------------------------------- %% %% The development version of the bundle can be found at %% %% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% %%%%%%%%%%% %% NOTE: %% %%%%%%%%%%% %% %% Snapshots taken from the repository represent work in progress and may %% not work or may contain conflicting material! We therefore ask %% people _not_ to put them into distributions, archives, etc. without %% prior consultation with the LaTeX Project Team. %% %% ----------------------------------------------------------------------- %% % %<*driver> \documentclass[full]{l3doc} \GetIdInfo$Id: l3fp-random.dtx 6750 2016-11-21 01:24:26Z bruno $ {L3 Floating-point random numbers} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{The \textsf{l3fp-random} package\thanks{This file % has version number \ExplFileVersion, last % revised \ExplFileDate.}\\ % Floating point random numbers} % \author{^^A % The \LaTeX3 Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } % \date{Released \ExplFileDate} % % \maketitle % % \begin{documentation} % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3fp-random} Implementation} % % \begin{macrocode} %<*initex|package> % \end{macrocode} % % \begin{macrocode} %<@@=fp> % \end{macrocode} % % \subsection{Random floating point} % % \begin{macro}[EXP, int]{\@@_rand_o:Nw} % \begin{macro}[EXP, aux]{\@@_rand_o:} % Check that |random| was called without argument. Random numbers are % only available if the engine defines a primitive equivalent to % \pdfTeX{}'s \tn{pdfuniformdeviate}. A random floating point number % in $[0,1)$, uniformly distributed with equal-spaced steps of % $10^{-16}$ is obtained by combining two integers in $[0,10^8-1]$. % \begin{macrocode} \cs_new:Npn \@@_rand_o:Nw ? #1 @ { \tl_if_empty:nTF {#1} { \@@_rand_o: } { \__msg_kernel_expandable_error:nnnnn { kernel } { fp-num-args } { rand() } { 0 } { 0 } \exp_after:wN \c_nan_fp } } \cs_if_exist:NTF \pdftex_uniformdeviate:D { \cs_new:Npn \@@_rand_o: { \@@_parse_o:n { . \exp_after:wN \use_none:n \__int_value:w \__int_eval:w 1 0000 0000 + \pdftex_uniformdeviate:D 1 0000 0000 \__int_eval_end: \exp_after:wN \use_none:n \__int_value:w \__int_eval:w 1 0000 0000 + \pdftex_uniformdeviate:D 1 0000 0000 \__int_eval_end: } } } { \cs_new:Npn \@@_rand_o: { \__msg_kernel_expandable_error:nn { kernel } { fp-no-random } \exp_after:wN \c_nan_fp } } % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Random integer} % % \begin{macro}[EXP, int]{\@@_randint_o:Nw} % \begin{macro}[EXP, aux] % { % \@@_randint_badarg:w, % \@@_randint_e:w, % \@@_randint_narrow_e:nn, % \@@_randint_wide_e:nn, % \@@_randint_wide_e:nnn, % \@@_randint_wide_e:nnnn, % } % Enforce that there is one argument (then add first argument~$1$) % or two arguments. Enforce that they are integers in % $(-10^{16},10^{16})$ and ordered. % % When the range is narrow (less than $2\times 10^9$) we can % directly use the primitive. Otherwise we use the primitive twice. % To ensure a uniform distribution we combine two uniformly % distributed integers into a total range greater or equal to our % target range and try again if the random number ended up being too % big. % % The strange |+\c_six| ensures that the first argument of % \cs{@@_randint_wide_e:nnn} is larger than $10^{-8}$ times the % difference between the end-points even if these are near % $-10^{16}$ and $+10^{16}$ (their difference is rounded to sixteen % digits). Note that we cannot just concatenate the two random % numbers provided by the engine as that may give an integer up to % (almost) $2\times 10^{16}$ which incurs rounding. % \begin{macrocode} \cs_new:Npn \@@_randint_o:Nw ? #1 @ { \if_case:w \__int_eval:w \@@_array_count:n {#1} - \c_one \__int_eval_end: \exp_after:wN \@@_randint_e:w \c_one_fp #1 \or: \@@_randint_e:w #1 \else: \__msg_kernel_expandable_error:nnnnn { kernel } { fp-num-args } { randint() } { 1 } { 2 } \exp_after:wN \c_nan_fp \exp:w \fi: \exp_after:wN \exp_end: } \cs_new:Npn \@@_randint_badarg:w \s_@@ \@@_chk:w #1#2#3; { \@@_int:wTF \s_@@ \@@_chk:w #1#2#3; { \if_meaning:w 1 #1 \if_int_compare:w \use_i_delimit_by_q_stop:nw #3 \q_stop > \c_sixteen \exp_after:wN \c_one \fi: \fi: } { \c_one } } \cs_new:Npn \@@_randint_e:w #1; #2; { \if_case:w \@@_randint_badarg:w #1; \@@_randint_badarg:w #2; \fp_compare:nNnTF { #1; } > { #2; } { \c_one } { \c_zero } \fp_compare:nNnTF { #1; + 2e9 } < { #2; } { \@@_randint_wide_e:nn } { \@@_randint_narrow_e:nn } { #1; } { #2; } \or: \@@_invalid_operation_tl_o:ff { randint } { \@@_array_to_clist:n { #1; #2; } } \exp:w \fi: } \cs_if_exist:NTF \pdftex_uniformdeviate:D { \cs_new:Npn \@@_randint_narrow_e:nn #1#2 { \@@_parse_o:n { #1 + \pdftex_uniformdeviate:D \int_eval:n { \fp_to_int:n { #2 - #1 } + \c_one } } \exp:w } \cs_new:Npn \@@_randint_wide_e:nn #1 #2 { \exp_args:Nf \@@_randint_wide_e:nnn { \fp_to_int:n { ceil ( ( #2 - #1 + \c_six ) * 1e-8 ) } } {#1} {#2} } \cs_new:Npn \@@_randint_wide_e:nnn #1#2#3 { \exp_args:Nf \@@_randint_wide_e:nnnn { \@@_parse:n { #2 + \pdftex_uniformdeviate:D #1 e 8 + \pdftex_uniformdeviate:D 1 0000 0000 } } {#1} {#2} {#3} } \cs_new:Npn \@@_randint_wide_e:nnnn #1#2#3#4 { \fp_compare:nNnTF {#1} > {#4} { \@@_randint_wide_e:nnn {#2} {#3} {#4} } { \@@_exp_after_o:w #1 \exp:w } } } { \cs_new:Npn \@@_randint_narrow_e:nn #1#2 { \__msg_kernel_expandable_error:nn { kernel } { fp-no-random } \exp_after:wN \c_nan_fp \exp:w } \cs_new:Npn \@@_randint_wide_e:nn #1#2 { \__msg_kernel_expandable_error:nn { kernel } { fp-no-random } \exp_after:wN \c_nan_fp \exp:w } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macrocode} \__msg_kernel_new:nnn { kernel } { fp-no-random } { Random~numbers~unavailable } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \PrintChanges % % \PrintIndex