summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx341
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}