diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx | 341 |
1 files changed, 305 insertions, 36 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx index d3ef2708afc..62a21ee09ea 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx @@ -1,44 +1,30 @@ % \iffalse meta-comment % %% File: l3candidates.dtx Copyright (C) 2012-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. -%% -%% ----------------------------------------------------------------------- -%% +% +% 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 development version of the bundle can be found at +% +% https://github.com/latex3/latex3 +% +% for those people who are interested. % %<*driver> \documentclass[full]{l3doc} %</driver> %<*driver|package> -\GetIdInfo$Id: l3candidates.dtx 6688 2016-08-19 19:21:48Z bruno $ +\GetIdInfo$Id: l3candidates.dtx 6809 2017-01-01 06:33:13Z bruno $ {L3 Experimental additions to l3kernel} %</driver|package> %<*driver> @@ -317,6 +303,23 @@ % \cs{clist_show:n} which displays the result in the terminal. % \end{function} % +% \begin{function}[EXP, added = 2016-12-06] +% {\clist_rand_item:N, \clist_rand_item:n, \clist_rand_item:c} +% \begin{syntax} +% \cs{clist_rand_item:N} \meta{clist~var} +% \cs{clist_rand_item:n} \Arg{comma list} +% \end{syntax} +% Selects a pseudo-random item of the \meta{comma list}. If the +% \meta{comma list} has no item, the result is empty. This is only +% available in \pdfTeX{} and \LuaTeX{}. +% \begin{texnote} +% The result is returned within the \tn{unexpanded} +% primitive (\cs{exp_not:n}), which means that the \meta{item} +% will not expand further when appearing in an \texttt{x}-type +% argument expansion. +% \end{texnote} +% \end{function} +% % \section{Additions to \pkg{l3coffins}} % % \begin{function}{\coffin_resize:Nnn, \coffin_resize:cnn} @@ -495,6 +498,15 @@ % in the log file. % \end{function} % +% \begin{function}[EXP, added = 2016-12-06]{\int_rand:nn} +% \begin{syntax} +% \cs{int_rand:nn} \Arg{intexpr_1} \Arg{intexpr_2} +% \end{syntax} +% Evaluates the two \meta{integer expressions} and produces a +% pseudo-random number between the two (with bounds included). This +% is only available in \pdfTeX{} and \LuaTeX{}. +% \end{function} +% % \section{Additions to \pkg{l3keys}} % % \begin{function}[added = 2014-08-22]{\keys_log:nn} @@ -673,6 +685,51 @@ % Writes the entries in the \meta{property list} in the log file. % \end{function} % +% \begin{function}[EXP, added = 2016-12-06] +% {\prop_rand_key:N, \prop_rand_key:c} +% \begin{syntax} +% \cs{prop_rand_key:N} \meta{prop~var} +% \end{syntax} +% Selects a pseudo-random key--value pair in the \meta{property list} +% and returns the \meta{key}. If the \meta{property list} is empty +% the result is empty. This is only available in \pdfTeX{} and +% \LuaTeX{}. +% \end{function} +% +% \begin{function}[EXP, added = 2016-12-06] +% {\prop_rand_value:N, \prop_rand_value:c} +% \begin{syntax} +% \cs{prop_rand_value:N} \meta{prop~var} +% \end{syntax} +% Selects a pseudo-random key--value pair in the \meta{property list} +% and returns the \meta{value}. If the \meta{property list} is empty +% the result is empty. This is only available in \pdfTeX{} and +% \LuaTeX{}. +% \begin{texnote} +% The result is returned within the \tn{unexpanded} +% primitive (\cs{exp_not:n}), which means that the \meta{value} +% will not expand further when appearing in an \texttt{x}-type +% argument expansion. +% \end{texnote} +% \end{function} +% +% \begin{function}[EXP, added = 2016-12-06] +% {\prop_rand_key_value:N, \prop_rand_key_value:c} +% \begin{syntax} +% \cs{prop_rand_key_value:N} \meta{prop~var} +% \end{syntax} +% Selects a pseudo-random key--value pair in the \meta{property list} +% and returns \Arg{key}\Arg{value}. If the \meta{property list} is +% empty the result is empty. This is only available in \pdfTeX{} and +% \LuaTeX{}. +% \begin{texnote} +% The result is returned within the \tn{unexpanded} +% primitive (\cs{exp_not:n}), which means that the \meta{value} +% will not expand further when appearing in an \texttt{x}-type +% argument expansion. +% \end{texnote} +% \end{function} +% % \section{Additions to \pkg{l3seq}} % % \begin{function}[rEXP] @@ -733,6 +790,21 @@ % Writes the entries in the \meta{sequence} in the log file. % \end{function} % +% \begin{function}[EXP, added = 2016-12-06]{\seq_rand_item:N, \seq_rand_item:c} +% \begin{syntax} +% \cs{seq_rand_item:N} \meta{seq~var} +% \end{syntax} +% Selects a pseudo-random item of the \meta{sequence}. If the +% \meta{sequence} is empty the result is empty. This is only +% available in \pdfTeX{} and \LuaTeX{}. +% \begin{texnote} +% The result is returned within the \tn{unexpanded} +% primitive (\cs{exp_not:n}), which means that the \meta{item} +% will not expand further when appearing in an \texttt{x}-type +% argument expansion. +% \end{texnote} +% \end{function} +% % \section{Additions to \pkg{l3skip}} % % \begin{function}{\skip_split_finite_else_action:nnNN} @@ -1069,12 +1141,29 @@ % % \begin{function}[added = 2014-08-22]{\tl_log:n} % \begin{syntax} -% \cs{tl_log:n} \meta{token list} +% \cs{tl_log:n} \Arg{token list} % \end{syntax} % Writes the \meta{token list} in the log file. See also % \cs{tl_show:n} which displays the result in the terminal. % \end{function} % +% \begin{function}[EXP, added = 2016-12-06] +% {\tl_rand_item:N, \tl_rand_item:c, \tl_rand_item:n} +% \begin{syntax} +% \cs{tl_rand_item:N} \meta{tl~var} +% \cs{tl_rand_item:n} \Arg{token list} +% \end{syntax} +% Selects a pseudo-random item of the \meta{token list}. If the +% \meta{token list} is blank, the result is empty. This is only +% available in \pdfTeX{} and \LuaTeX{}. +% \begin{texnote} +% The result is returned within the \tn{unexpanded} +% primitive (\cs{exp_not:n}), which means that the \meta{item} +% will not expand further when appearing in an \texttt{x}-type +% argument expansion. +% \end{texnote} +% \end{function} +% % \section{Additions to \pkg{l3tokens}} % % \begin{function}[TF, updated = 2012-12-20]{\peek_N_type:} @@ -1799,6 +1888,33 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\clist_rand_item:n, \clist_rand_item:N, \clist_rand_item:c} +% \begin{macro}[aux]{\@@_rand_item:nn} +% The |N|-type function is not implemented through the |n|-type +% function for efficiency: for instance comma-list variables do not +% require space-trimming of their items. Even testing for emptyness +% of an |n|-type comma-list is slow, so we count items first and use +% that both for the emptyness test and the pseudo-random integer. +% Importantly, \cs{clist_item:Nn} and \cs{clist_item:nn} only evaluate +% their argument once. +% \begin{macrocode} +\cs_new:Npn \clist_rand_item:n #1 + { \exp_args:Nf \@@_rand_item:nn { \clist_count:n {#1} } {#1} } +\cs_new:Npn \@@_rand_item:nn #1#2 + { + \int_compare:nNnF {#1} = \c_zero + { \clist_item:nn {#2} { \int_rand:nn { 1 } {#1} } } + } +\cs_new:Npn \clist_rand_item:N #1 + { + \clist_if_empty:NF #1 + { \clist_item:Nn #1 { \int_rand:nn { 1 } { \clist_count:N #1 } } } + } +\cs_generate_variant:Nn \clist_rand_item:N { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Additions to \pkg{l3coffins}} % % \begin{macrocode} @@ -2338,7 +2454,7 @@ \cs_new_protected:Npn \ior_map_inline:Nn { \@@_map_inline:NNn \ior_get:NN } \cs_new_protected:Npn \ior_str_map_inline:Nn - { \@@_map_inline:NNn \ior_get_str:NN } + { \@@_map_inline:NNn \ior_str_get:NN } \cs_new_protected:Npn \@@_map_inline:NNn { \int_gincr:N \g__prg_map_int @@ -2408,6 +2524,10 @@ % % \subsection{Additions to \pkg{l3int}} % +% \begin{macrocode} +%<@@=int> +% \end{macrocode} +% % \begin{macro}{\int_log:N, \int_log:c} % Redirect output of \cs{int_show:N} to the log. This is not just a % copy of \cs{__kernel_register_log:N} because of subtleties @@ -2428,6 +2548,89 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[EXP]{\int_rand:nn} +% \begin{macro}[aux, EXP] +% { +% \@@_rand:ww, \@@_rand_narrow:n, +% \@@_rand_narrow:nnn, \@@_rand_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| +% 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{@@_rand_narrow:nn} \Arg{choices} |{#1}| where +% \meta{choices} is the number of possible outcomes. Then +% \cs{@@_rand_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__fp_rand_size_int}-1]$, and try again. +% \begin{macrocode} +\cs_if_exist:NTF \pdftex_uniformdeviate:D + { + \cs_new:Npn \int_rand:nn #1#2 + { + \exp_after:wN \@@_rand:ww + \__int_value:w \__int_eval:w #1 \exp_after:wN ; + \__int_value:w \__int_eval:w #2 ; + } + \cs_new:Npn \@@_rand:ww #1; #2; + { + \int_compare:nNnTF {#1} > {#2} + { + \__msg_kernel_expandable_error:nnnn + { kernel } { backward-range } {#1} {#2} + \@@_rand:ww #2; #1; + } + { + \int_compare:nNnTF {#1} > \c_zero + { \int_compare:nNnTF { #2 - #1 } < \c__fp_rand_size_int } + { \int_compare:nNnTF {#2} < { #1 + \c__fp_rand_size_int } } + { + \exp_args:Nf \@@_rand_narrow:nn + { \int_eval:n { #2 - #1 + \c_one } } {#1} + } + { \fp_to_int:n { randint(#1,#2) } } + } + } + \cs_new:Npn \@@_rand_narrow:nn + { + \exp_args:No \@@_rand_narrow:nnn + { \pdftex_uniformdeviate:D \c__fp_rand_size_int } + } + \cs_new:Npn \@@_rand_narrow:nnn #1#2 + { + \exp_args:Nf \@@_rand_narrow:nnnn + { \int_mod:nn {#1} {#2} } {#1} {#2} + } + \cs_new:Npn \@@_rand_narrow:nnnn #1#2#3#4 + { + \int_compare:nNnTF { #2 - #1 + #3 } > \c__fp_rand_size_int + { \@@_rand_narrow:nn {#3} {#4} } + { \int_eval:n { #4 + #1 } } + } + } + { + \cs_new:Npn \int_rand:nn #1#2 + { + \__msg_kernel_expandable_error:nn { kernel } { fp-no-random } + \int_eval:n {#1} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% The following must be added to \pkg{l3msg}. +% \begin{macrocode} +\cs_if_exist:NT \pdftex_uniformdeviate:D + { + \__msg_kernel_new:nnn { kernel } { backward-range } + { Bounds~ordered~backwards~in~\int_rand:nn {#1}~{#2}. } + } +% \end{macrocode} +% % \subsection{Additions to \pkg{l3keys}} % % \begin{macrocode} @@ -2638,6 +2841,47 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[EXP] +% { +% \prop_rand_key:N, \prop_rand_key:c, +% \prop_rand_value:N, \prop_rand_value:c, +% \prop_rand_key_value:N, \prop_rand_key_value:c +% } +% \begin{macro}[aux, EXP]{\@@_rand:NN, \@@_rand_item:Nw} +% Contrarily to |clist|, |seq| and |tl|, there is no function to get +% an item of a |prop| given an integer between $1$ and the number of +% items, so we write the appropriate code. There is no bounds +% checking because \cs{int_rand:nn} is always within bounds. At the +% end, leave either the key |#3| or the value |#4| in the input +% stream. +% \begin{macrocode} +\cs_new:Npn \prop_rand_key:N { \@@_rand:NN \use_i:nnn } +\cs_new:Npn \prop_rand_value:N { \@@_rand:NN \use_none:n } +\cs_new:Npn \prop_rand_key_value:N { \@@_rand:NN \@@_rand:nNn } +\cs_new:Npn \@@_rand:nNn #1#2#3 { \exp_not:n { {#1} {#3} } } +\cs_new:Npn \@@_rand:NN #1#2 + { + \prop_if_empty:NTF #2 { } + { + \exp_after:wN \@@_rand_item:Nw \exp_after:wN #1 + \__int_value:w \int_rand:nn { 1 } { \prop_count:N #2 } #2 + \q_stop + } + } +\cs_new:Npn \@@_rand_item:Nw #1#2 \s_@@ \@@_pair:wn #3 \s_@@ #4 + { + \int_compare:nNnF {#2} > \c_one + { \use_i_delimit_by_q_stop:nw { #1 {#3} \exp_not:n {#4} } } + \exp_after:wN \@@_rand_item:Nw \exp_after:wN #1 + \__int_value:w \int_eval:n { #2 - \c_one } \s_@@ + } +\cs_generate_variant:Nn \prop_rand_key:N { c } +\cs_generate_variant:Nn \prop_rand_value:N { c } +\cs_generate_variant:Nn \prop_rand_key_value:N { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Additions to \pkg{l3seq}} % % \begin{macrocode} @@ -2745,6 +2989,18 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\seq_rand_item:N, \seq_rand_item:c} +% Importantly, \cs{seq_item:Nn} only evaluates its argument once. +% \begin{macrocode} +\cs_new:Npn \seq_rand_item:N #1 + { + \seq_if_empty:NF #1 + { \seq_item:Nn #1 { \int_rand:nn { 1 } { \seq_count:N #1 } } } + } +\cs_generate_variant:Nn \seq_rand_item:N { c } +% \end{macrocode} +% \end{macro} +% % \subsection{Additions to \pkg{l3skip}} % % \begin{macrocode} @@ -2937,7 +3193,7 @@ } } \exp_args:Nno \use:nn - { \cs_set_protected:Npn \@@_from_file_do:w #1 } + { \cs_new_protected:Npn \@@_from_file_do:w #1 } { \c_@@_rescan_marker_tl } { \tl_set:No \l_@@_internal_a_tl {#1} } % \end{macrocode} @@ -4442,6 +4698,19 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\tl_rand_item:n, \tl_rand_item:N, \tl_rand_item:c} +% Importantly \cs{tl_item:nn} only evaluates its argument once. +% \begin{macrocode} +\cs_new:Npn \tl_rand_item:n #1 + { + \tl_if_blank:nF {#1} + { \tl_item:nn {#1} { \int_rand:nn { 1 } { \tl_count:n {#1} } } } + } +\cs_new:Npn \tl_rand_item:N { \exp_args:No \tl_rand_item:n } +\cs_generate_variant:Nn \tl_rand_item:N { c } +% \end{macrocode} +% \end{macro} +% % \subsection{Additions to \pkg{l3tokens}} % % \begin{macrocode} |